gradle / gradle

Adaptable, fast automation for all
https://gradle.org
Apache License 2.0
17.02k stars 4.78k forks source link

Upgrading to log4j2 2.24.0 will print ERRORs to the console #30554

Open sdavids opened 2 months ago

sdavids commented 2 months ago

Current Behavior

Upgrading to log4j2 2.24.0 will print ERRORs to the console when executing tests:

2024-09-15T12:16:15.863833Z main ERROR Cannot set JUL log level through log4j-api: ignoring call to Logger.setLevel(SEVERE)
2024-09-15T12:16:15.969729Z Test worker ERROR Cannot set JUL log level through log4j-api: ignoring call to Logger.setLevel(SEVERE)

To be clear:

The ERRORs come from Gradle setting up its logging plumbing.

Expected Behavior

No ERRORs.

Context

https://logging.apache.org/log4j/2.x/log4j-jul.html#log4j2.julLoggerAdapter

Since version 2.24.0 the default value changed to ApiLoggerAdapter. If you need to modify log levels via JUL, you need to select CoreLoggerAdapter explicitly.

Self-contained Reproducer Project

$ mkdir /tmp/test && cd "$_"
$ gradle init \
  --type java-library \
  --java-version 21 \
  --dsl kotlin \
  --test-framework junit-jupiter \
  --no-comments \
  --incubating \
  --quiet \
  --project-name test
$ git init -q && git add -A && git commit -q -m initial
$ cat << 'EOF' >lib/build.gradle.kts
plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

dependencies {
    api(libs.commons.math3)

    implementation(libs.guava)
}

testing {
    suites {
        val test by getting(JvmTestSuite::class) {
            useJUnitJupiter("5.10.3")
            dependencies {
                runtimeOnly("org.apache.logging.log4j:log4j-core:2.23.0")
                runtimeOnly("org.apache.logging.log4j:log4j-jul:2.23.0")
            }
            targets {
                all {
                    testTask.configure {
                        systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
                    }
                }
            }
        }
    }
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}
EOF
$ git diff
diff --git i/lib/build.gradle.kts w/lib/build.gradle.kts
index 8c435fa..219b43a 100644
--- i/lib/build.gradle.kts
+++ w/lib/build.gradle.kts
@@ -16,6 +16,17 @@ testing {
     suites {
         val test by getting(JvmTestSuite::class) {
             useJUnitJupiter("5.10.3")
+            dependencies {
+                runtimeOnly("org.apache.logging.log4j:log4j-core:2.23.0")
+                runtimeOnly("org.apache.logging.log4j:log4j-jul:2.23.0")
+            }
+            targets {
+                all {
+                    testTask.configure {
+                        systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
+                    }
+                }
+            }
         }
     }
 }
$ git add -A && git commit -q -m 'log4j2 2.23.0'
$ ./gradlew -q test
$ sed 's/2.23.0/2.24.0/g' lib/build.gradle.kts > lib/build.gradle.kts.tmp && mv lib/build.gradle.kts.tmp lib/build.gradle.kts
$ git diff
diff --git i/lib/build.gradle.kts w/lib/build.gradle.kts
index 219b43a..8448ac8 100644
--- i/lib/build.gradle.kts
+++ w/lib/build.gradle.kts
@@ -17,8 +17,8 @@ testing {
         val test by getting(JvmTestSuite::class) {
             useJUnitJupiter("5.10.3")
             dependencies {
-                runtimeOnly("org.apache.logging.log4j:log4j-core:2.23.0")
-                runtimeOnly("org.apache.logging.log4j:log4j-jul:2.23.0")
+                runtimeOnly("org.apache.logging.log4j:log4j-core:2.24.0")
+                runtimeOnly("org.apache.logging.log4j:log4j-jul:2.24.0")
             }
             targets {
                 all {
$ git add -A && git commit -q -m 'log4j2 2.24.0'
$ ./gradlew -q test --rerun-tasks
2024-09-15T12:16:15.863833Z main ERROR Cannot set JUL log level through log4j-api: ignoring call to Logger.setLevel(SEVERE)
2024-09-15T12:16:15.969729Z Test worker ERROR Cannot set JUL log level through log4j-api: ignoring call to Logger.setLevel(SEVERE)

Gradle version

8.10.1

sdavids commented 2 months ago

A workaround is to set log4j2.julLoggerAdapter to org.apache.logging.log4j.jul.CoreLoggerAdapter:


cat << 'EOF' >lib/build.gradle.kts
plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

dependencies {
    api(libs.commons.math3)

    implementation(libs.guava)
}

testing {
    suites {
        val test by getting(JvmTestSuite::class) {
            useJUnitJupiter("5.10.3")
            dependencies {
                runtimeOnly("org.apache.logging.log4j:log4j-core:2.24.0")
                runtimeOnly("org.apache.logging.log4j:log4j-jul:2.24.0")
            }
            targets {
                all {
                    testTask.configure {
                        systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
                        systemProperty("log4j2.julLoggerAdapter", "org.apache.logging.log4j.jul.CoreLoggerAdapter")
                    }
                }
            }
        }
    }
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}
EOF
$ git diff
diff --git i/lib/build.gradle.kts w/lib/build.gradle.kts
index 8448ac8..16a5ea2 100644
--- i/lib/build.gradle.kts
+++ w/lib/build.gradle.kts
@@ -24,6 +24,7 @@ testing {
                 all {
                     testTask.configure {
                         systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
+                        systemProperty("log4j2.julLoggerAdapter", "org.apache.logging.log4j.jul.CoreLoggerAdapter")
                     }
                 }
             }
$ git add -A && git commit -q -m 'log4j2.julLoggerAdapter'
$ ./gradlew -q test --rerun-tasks
sdavids commented 2 months ago
setLevel:92, ApiLogger (org.apache.logging.log4j.jul)
install:110, JavaUtilLoggingSystem (org.gradle.internal.logging.source)
startCapture:73, JavaUtilLoggingSystem (org.gradle.internal.logging.source)
start:330, DefaultLoggingManager$StartableLoggingSystem (org.gradle.internal.logging.services)
start:81, DefaultLoggingManager (org.gradle.internal.logging.services)
1 hidden frame
call:115, SystemApplicationClassLoaderWorker (org.gradle.process.internal.worker.child)
3 hidden frames
ljacomet commented 2 months ago

The issue is in the backlog of the relevant team, but the existence of a workaround means it might take a while before a fix is made.


See workaround above

This is caused by Gradle logging setup leaking in the test workers. This should not happen in a way that limits logging options for user code tests.

sdavids commented 2 months ago

The unfortunate side effect of using the workaround is that you mask the ERRORs raised by you own code—they then turn up during production.