Polish "Use Log4jBridgeHandler to route JUL-based logging into Log4j 2"

See gh-30003
pull/30890/head
Andy Wilkinson 3 years ago
parent 728e27d193
commit 3980c5af48

@ -1,119 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.logging;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Abstract base class for {@link LoggingSystem} implementations that utilize SLF4J.
*
* @author Andy Wilkinson
* @since 1.2.0
*/
public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {
private static final String BRIDGE_HANDLER = "org.slf4j.bridge.SLF4JBridgeHandler";
public Slf4JLoggingSystem(ClassLoader classLoader) {
super(classLoader);
}
@Override
public void beforeInitialize() {
super.beforeInitialize();
configureJdkLoggingBridgeHandler();
}
@Override
public void cleanUp() {
if (isBridgeHandlerAvailable()) {
removeJdkLoggingBridgeHandler();
}
}
@Override
protected void loadConfiguration(LoggingInitializationContext initializationContext, String location,
LogFile logFile) {
Assert.notNull(location, "Location must not be null");
if (initializationContext != null) {
applySystemProperties(initializationContext.getEnvironment(), logFile);
}
}
private void configureJdkLoggingBridgeHandler() {
try {
if (isBridgeJulIntoSlf4j()) {
removeJdkLoggingBridgeHandler();
SLF4JBridgeHandler.install();
}
}
catch (Throwable ex) {
// Ignore. No java.util.logging bridge is installed.
}
}
/**
* Return whether bridging JUL into SLF4J or not.
* @return whether bridging JUL into SLF4J or not
* @since 2.0.4
*/
protected final boolean isBridgeJulIntoSlf4j() {
return isBridgeHandlerAvailable() && isJulUsingASingleConsoleHandlerAtMost();
}
protected final boolean isBridgeHandlerAvailable() {
return ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader());
}
protected boolean isJulUsingASingleConsoleHandlerAtMost() {
Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
return handlers.length == 0 || (handlers.length == 1 && handlers[0] instanceof ConsoleHandler);
}
private void removeJdkLoggingBridgeHandler() {
try {
removeDefaultRootHandler();
SLF4JBridgeHandler.uninstall();
}
catch (Throwable ex) {
// Ignore and continue
}
}
protected void removeDefaultRootHandler() {
try {
Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
if (handlers.length == 1 && handlers[0] instanceof ConsoleHandler) {
rootLogger.removeHandler(handlers[0]);
}
}
catch (Throwable ex) {
// Ignore and continue
}
}
}

@ -25,6 +25,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.stream.Collectors;
@ -49,13 +50,13 @@ import org.apache.logging.log4j.message.Message;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.logging.AbstractLoggingSystem;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.LoggingSystemFactory;
import org.springframework.boot.logging.Slf4JLoggingSystem;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.Assert;
@ -73,7 +74,7 @@ import org.springframework.util.StringUtils;
* @author Ben Hale
* @since 1.2.0
*/
public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
public class Log4J2LoggingSystem extends AbstractLoggingSystem {
private static final String FILE_PROTOCOL = "file";
@ -169,12 +170,11 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
private boolean configureJdkLoggingBridgeHandler() {
try {
if (isJulUsingASingleConsoleHandlerAtMost() && !isLog4jLogManagerInstalled()) {
if (isLog4jBridgeHandlerAvailable()) {
removeDefaultRootHandler();
installLog4jBridgeHandler();
return true;
}
if (isJulUsingASingleConsoleHandlerAtMost() && !isLog4jLogManagerInstalled()
&& isLog4jBridgeHandlerAvailable()) {
removeDefaultRootHandler();
Log4jBridgeHandler.install(false, null, true);
return true;
}
}
catch (Throwable ex) {
@ -183,6 +183,12 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
return false;
}
private boolean isJulUsingASingleConsoleHandlerAtMost() {
java.util.logging.Logger rootLogger = java.util.logging.LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
return handlers.length == 0 || (handlers.length == 1 && handlers[0] instanceof ConsoleHandler);
}
private boolean isLog4jLogManagerInstalled() {
final String logManagerClassName = java.util.logging.LogManager.getLogManager().getClass().getName();
return LOG4J_LOG_MANAGER.equals(logManagerClassName);
@ -192,11 +198,8 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
return ClassUtils.isPresent(LOG4J_BRIDGE_HANDLER, getClassLoader());
}
private void installLog4jBridgeHandler() {
Log4jBridgeHandler.install(false, null, true);
}
private void removeLog4jBridgeHandler() {
removeDefaultRootHandler();
java.util.logging.Logger rootLogger = java.util.logging.LogManager.getLogManager().getLogger("");
for (final Handler handler : rootLogger.getHandlers()) {
if (handler instanceof Log4jBridgeHandler) {
@ -206,6 +209,19 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
}
}
private void removeDefaultRootHandler() {
try {
java.util.logging.Logger rootLogger = java.util.logging.LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
if (handlers.length == 1 && handlers[0] instanceof ConsoleHandler) {
rootLogger.removeHandler(handlers[0]);
}
}
catch (Throwable ex) {
// Ignore and continue
}
}
@Override
public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
LoggerContext loggerContext = getLoggerContext();
@ -236,7 +252,9 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
@Override
protected void loadConfiguration(LoggingInitializationContext initializationContext, String location,
LogFile logFile) {
super.loadConfiguration(initializationContext, location, logFile);
if (initializationContext != null) {
applySystemProperties(initializationContext.getEnvironment(), logFile);
}
loadConfiguration(location, logFile, getOverrides(initializationContext));
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,6 +22,7 @@ import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.LogManager;
@ -42,6 +43,7 @@ import org.slf4j.Marker;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.boot.logging.AbstractLoggingSystem;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
@ -49,7 +51,6 @@ import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.LoggingSystemFactory;
import org.springframework.boot.logging.LoggingSystemProperties;
import org.springframework.boot.logging.Slf4JLoggingSystem;
import org.springframework.core.Ordered;
import org.springframework.core.SpringProperties;
import org.springframework.core.annotation.Order;
@ -69,7 +70,9 @@ import org.springframework.util.StringUtils;
* @author Ben Hale
* @since 1.0.0
*/
public class LogbackLoggingSystem extends Slf4JLoggingSystem {
public class LogbackLoggingSystem extends AbstractLoggingSystem {
private static final String BRIDGE_HANDLER = "org.slf4j.bridge.SLF4JBridgeHandler";
// Static final field to facilitate code removal by Graal
private static final boolean XML_ENABLED = !SpringProperties.getFlag("spring.xml.ignore");
@ -120,9 +123,59 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
return;
}
super.beforeInitialize();
configureJdkLoggingBridgeHandler();
loggerContext.getTurboFilterList().add(FILTER);
}
private void configureJdkLoggingBridgeHandler() {
try {
if (isBridgeJulIntoSlf4j()) {
removeJdkLoggingBridgeHandler();
SLF4JBridgeHandler.install();
}
}
catch (Throwable ex) {
// Ignore. No java.util.logging bridge is installed.
}
}
private boolean isBridgeJulIntoSlf4j() {
return isBridgeHandlerAvailable() && isJulUsingASingleConsoleHandlerAtMost();
}
private boolean isBridgeHandlerAvailable() {
return ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader());
}
private boolean isJulUsingASingleConsoleHandlerAtMost() {
java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
return handlers.length == 0 || (handlers.length == 1 && handlers[0] instanceof ConsoleHandler);
}
private void removeJdkLoggingBridgeHandler() {
try {
removeDefaultRootHandler();
SLF4JBridgeHandler.uninstall();
}
catch (Throwable ex) {
// Ignore and continue
}
}
private void removeDefaultRootHandler() {
try {
java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
if (handlers.length == 1 && handlers[0] instanceof ConsoleHandler) {
rootLogger.removeHandler(handlers[0]);
}
}
catch (Throwable ex) {
// Ignore and continue
}
}
@Override
public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
LoggerContext loggerContext = getLoggerContext();
@ -158,7 +211,9 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
@Override
protected void loadConfiguration(LoggingInitializationContext initializationContext, String location,
LogFile logFile) {
super.loadConfiguration(initializationContext, location, logFile);
if (initializationContext != null) {
applySystemProperties(initializationContext.getEnvironment(), logFile);
}
LoggerContext loggerContext = getLoggerContext();
stopAndReset(loggerContext);
try {
@ -221,6 +276,9 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
LoggerContext context = getLoggerContext();
markAsUninitialized(context);
super.cleanUp();
if (isBridgeHandlerAvailable()) {
removeJdkLoggingBridgeHandler();
}
context.getStatusManager().clear();
context.getTurboFilterList().remove(FILTER);
}

Loading…
Cancel
Save