Spring-Boot: v2.3.5.RELEASE Log4J2: 2.13.3 (spring-managed)

Display default configuration

$ curl http://$SERVER/actuator/loggers json {"levels":["OFF","FATAL","ERROR","WARN","INFO","DEBUG","TRACE"],"loggers":{ "ROOT":{"configuredLevel":null,"effectiveLevel":"WARN"}, "de":{"configuredLevel":null, "effectiveLevel":"WARN"},

Configure de Log Level

$ curl http://$SERVER/actuator/loggers/de -d '{"configuredLevel":"info"}' -H "Content-Type: application/json" $ curl http://$SERVER/actuator/loggers json {"levels":["OFF","FATAL","ERROR","WARN","INFO","DEBUG","TRACE"],"loggers":{ "ROOT":{"configuredLevel":null,"effectiveLevel":"WARN"}, "de":{"configuredLevel":"INFO","effectiveLevel":"INFO"},

Reset/inherit de Log Level

$ curl http://$SERVER/actuator/loggers/de -d '{"configuredLevel":null}' -H "Content-Type: application/json" $ curl http://$SERVER/actuator/loggers json {"levels":["OFF","FATAL","ERROR","WARN","INFO","DEBUG","TRACE"],"loggers":{ "ROOT":{"configuredLevel":null,"effectiveLevel":"WARN"}, "de":{"configuredLevel":"WARN", "effectiveLevel":"WARN"},

Configure ROOT Log Level

$ curl http://$SERVER/actuator/loggers/ROOT -d '{"configuredLevel":"error"}' -H "Content-Type: application/json" $ curl http://$SERVER/actuator/loggers json {"levels":["OFF","FATAL","ERROR","WARN","INFO","DEBUG","TRACE"],"loggers":{ "ROOT":{"configuredLevel":null,"effectiveLevel":"ERROR"}, "de":{"configuredLevel":"ERROR", "effectiveLevel":"ERROR"},

As you can see the last two jsons display de as configured, but the value (even for the configured flag) is inherited from ROOT.

Comment From: snicoll

@ST-DDT thanks for the report. FTR, there is no need to specify a null configuredLevel according to the documentation.

That's not a problem with the actuator as it merely get that information from the LoggingSystem. When we reset the log level that doesn't remove the logging config but rather makes sure that the existing logging config inherits from its parent. Logback does not have the same behaviour so we need to investigate if we can request log4j to remove the logging config.

Comment From: snicoll

The problem can be reproduced by the following test:

@Test
void getLoggingConfigurationWithResetLevelShouldReturnLoggerWithNullConfiguredLevel() {
    this.loggingSystem.beforeInitialize();
    this.loggingSystem.initialize(null, null, null);
    this.loggingSystem.setLogLevel("com.example", LogLevel.WARN);
    this.loggingSystem.setLogLevel("com.example.test", LogLevel.DEBUG);
    LoggerConfiguration configuration = this.loggingSystem.getLoggerConfiguration("com.example.test");
    assertThat(configuration).isEqualTo(new LoggerConfiguration("com.example.test", LogLevel.DEBUG, LogLevel.DEBUG));
    this.loggingSystem.setLogLevel("com.example.test", null);
    LoggerConfiguration updatedConfiguration = this.loggingSystem.getLoggerConfiguration("com.example.test");
    assertThat(updatedConfiguration).isEqualTo(new LoggerConfiguration("com.example.test", null, LogLevel.WARN));
}

Comment From: mbhave

Log4J2 LoggerConfig, returns the parent's log level if the log level for that logger is null. I'm not sure how we can tell if the logLevel itself is null without reflection.

Comment From: philwebb

I've had a go at fixing this one in https://github.com/philwebb/spring-boot/tree/gh-24298. The commit message describes the idea behind the fix.

I'm not confident enough to merge it without a review.

Comment From: snicoll

I did review that commit back then and I seem to remember that LevelSetLoggerConfig could be a problem if AsyncLoggerConfig is used. Reading the commit again, I am not so sure anymore. Or maybe it was for a different issue?