Only bridge JUL into SLF4J when JUL has not be customized
Previously, Slf4jLoggingSystem would install SLF4JBridgeHandler into JUL but would only remove a single root handler that was a ConsoleHandler. If there were was than one root handler or the single root handler was of a different type, they would not be uninstalled. When deploying an application to Tomcat, this led to duplicate log messages appearing in Tomcat’s console output and to logging from other application or Tomcat itself being routed into an application-specific log file enabled using the logging.file configuration property. A secondary, related problem was that LogbackLoggingSystem installs a LevelChangePropagator so that Logback’s log level configuration is propagated into JUL. This meant that an individual Boot app with custom log level configuration could change the log levels of Tomcat itself and of any other applications that had been deployed to Tomcat and use JUL. This commit updates both Slf4jLoggingSystem and LogbackLoggingSystem so that they only change JUL’s configuration if it hasn’t already been customized. The configuration is deemed to have not been customised if there’s a single root handler and its a console handler. Closes gh-13470
This commit is contained in:
@@ -48,7 +48,10 @@ public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
removeJdkLoggingBridgeHandler();
|
||||
if (isBridgeHandlerAvailable()) {
|
||||
removeJdkLoggingBridgeHandler();
|
||||
reinstateConsoleHandlerIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +65,7 @@ public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {
|
||||
|
||||
private void configureJdkLoggingBridgeHandler() {
|
||||
try {
|
||||
if (isBridgeHandlerAvailable()) {
|
||||
if (isBridgeJulIntoSlf4j()) {
|
||||
removeJdkLoggingBridgeHandler();
|
||||
SLF4JBridgeHandler.install();
|
||||
}
|
||||
@@ -72,16 +75,24 @@ public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {
|
||||
}
|
||||
}
|
||||
|
||||
protected final boolean isBridgeJulIntoSlf4j() {
|
||||
return isBridgeHandlerAvailable() && isJulUsingItsDefaultConfiguration();
|
||||
}
|
||||
|
||||
protected final boolean isBridgeHandlerAvailable() {
|
||||
return ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader());
|
||||
}
|
||||
|
||||
private boolean isJulUsingItsDefaultConfiguration() {
|
||||
Logger rootLogger = LogManager.getLogManager().getLogger("");
|
||||
Handler[] handlers = rootLogger.getHandlers();
|
||||
return handlers.length == 1 && handlers[0] instanceof ConsoleHandler;
|
||||
}
|
||||
|
||||
private void removeJdkLoggingBridgeHandler() {
|
||||
try {
|
||||
if (isBridgeHandlerAvailable()) {
|
||||
removeDefaultRootHandler();
|
||||
SLF4JBridgeHandler.uninstall();
|
||||
}
|
||||
removeDefaultRootHandler();
|
||||
SLF4JBridgeHandler.uninstall();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Ignore and continue
|
||||
@@ -101,4 +112,11 @@ public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {
|
||||
}
|
||||
}
|
||||
|
||||
private void reinstateConsoleHandlerIfNecessary() {
|
||||
Logger rootLogger = LogManager.getLogManager().getLogger("");
|
||||
if (rootLogger.getHandlers().length == 0) {
|
||||
rootLogger.addHandler(new ConsoleHandler());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogManager;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
@@ -35,6 +37,7 @@ import ch.qos.logback.core.status.Status;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.bridge.SLF4JBridgeHandler;
|
||||
import org.slf4j.impl.StaticLoggerBinder;
|
||||
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
@@ -184,11 +187,20 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||
private void stopAndReset(LoggerContext loggerContext) {
|
||||
loggerContext.stop();
|
||||
loggerContext.reset();
|
||||
if (isBridgeHandlerAvailable()) {
|
||||
if (isBridgeHandlerInstalled()) {
|
||||
addLevelChangePropagator(loggerContext);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBridgeHandlerInstalled() {
|
||||
if (!isBridgeHandlerAvailable()) {
|
||||
return false;
|
||||
}
|
||||
java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
|
||||
Handler[] handlers = rootLogger.getHandlers();
|
||||
return handlers.length == 1 && SLF4JBridgeHandler.class.isInstance(handlers[0]);
|
||||
}
|
||||
|
||||
private void addLevelChangePropagator(LoggerContext loggerContext) {
|
||||
LevelChangePropagator levelChangePropagator = new LevelChangePropagator();
|
||||
levelChangePropagator.setResetJUL(true);
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.config.Configuration;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -77,6 +78,13 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
this.logger = LogManager.getLogger(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
@After
|
||||
public void clear() {
|
||||
super.clear();
|
||||
this.loggingSystem.cleanUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFile() {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
|
||||
@@ -104,6 +104,7 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
@Override
|
||||
@After
|
||||
public void clear() {
|
||||
super.clear();
|
||||
this.loggingSystem.cleanUp();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user