From f807ecce1df51ccfd0b894c255baea6256f3c385 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Mon, 28 Feb 2022 09:03:42 +0100 Subject: [PATCH] [LOG4J2-3418] Fix Log4j2CloudConfigLoggingSystem registration This PR adds support for the `spring.factories` registration method of the `Log4j2CloudConfigLoggingSystem` to replace the old Java system properties injection method. A Log4j 2.x `log4j2.disableCloudConfigLoggingSystem` property is added to enable a choice between the `Log4j2CloudConfigLoggingSystem` and `Log4j2LoggingSystem`. --- .../boot/Log4j2CloudConfigLoggingSystem.java | 26 ++++++++++++++++- .../spring.factories} | 2 +- .../Log4j2CloudConfigLoggingSystemTest.java | 28 +++++++++++++++---- src/site/xdoc/manual/configuration.xml.vm | 6 ++++ 4 files changed, 55 insertions(+), 7 deletions(-) rename log4j-spring-boot/src/main/resources/{log4j2.system.properties => META-INF/spring.factories} (85%) diff --git a/log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystem.java b/log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystem.java index e8b7cf05d42..aaff3206e26 100644 --- a/log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystem.java +++ b/log4j-spring-boot/src/main/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystem.java @@ -49,7 +49,10 @@ import org.apache.logging.log4j.util.Strings; import org.springframework.boot.logging.LogFile; import org.springframework.boot.logging.LoggingInitializationContext; +import org.springframework.boot.logging.LoggingSystem; +import org.springframework.boot.logging.LoggingSystemFactory; import org.springframework.boot.logging.log4j2.Log4J2LoggingSystem; +import org.springframework.core.annotation.Order; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ResourceUtils; @@ -58,10 +61,17 @@ * Override Spring's implementation of the Log4j 2 Logging System to properly support Spring Cloud Config. */ public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem { - private static final String HTTPS = "https"; + + /** + * Property that disables the usage of this {@link LoggingSystem}. + */ + public static final String LOG4J2_DISABLE_CLOUD_CONFIG_LOGGING_SYSTEM = "log4j2.disableCloudConfigLoggingSystem"; + public static final String ENVIRONMENT_KEY = "SpringEnvironment"; + private static final String HTTPS = "https"; private static final String OVERRIDE_PARAM = "override"; private static Logger LOGGER = StatusLogger.getLogger(); + private static final int PRECEDENCE = 0; public Log4j2CloudConfigLoggingSystem(ClassLoader loader) { super(loader); @@ -213,4 +223,18 @@ private ConfigurationSource getConfigurationSource(URL url) throws IOException, private LoggerContext getLoggerContext() { return (LoggerContext) LogManager.getContext(false); } + + @Order(PRECEDENCE) + public static class Factory implements LoggingSystemFactory { + + @Override + public LoggingSystem getLoggingSystem(ClassLoader classLoader) { + if (PropertiesUtil.getProperties().getBooleanProperty(LOG4J2_DISABLE_CLOUD_CONFIG_LOGGING_SYSTEM)) { + return null; + } + return new Log4j2CloudConfigLoggingSystem(classLoader); + } + + } + } diff --git a/log4j-spring-boot/src/main/resources/log4j2.system.properties b/log4j-spring-boot/src/main/resources/META-INF/spring.factories similarity index 85% rename from log4j-spring-boot/src/main/resources/log4j2.system.properties rename to log4j-spring-boot/src/main/resources/META-INF/spring.factories index cc729f8605c..4ee15696392 100644 --- a/log4j-spring-boot/src/main/resources/log4j2.system.properties +++ b/log4j-spring-boot/src/main/resources/META-INF/spring.factories @@ -14,4 +14,4 @@ # See the license for the specific language governing permissions and # limitations under the license. # -org.springframework.boot.logging.LoggingSystem=org.apache.logging.log4j.spring.boot.Log4j2CloudConfigLoggingSystem \ No newline at end of file +org.springframework.boot.logging.LoggingSystemFactory=org.apache.logging.log4j.spring.boot.Log4j2CloudConfigLoggingSystem.Factory \ No newline at end of file diff --git a/log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystemTest.java b/log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystemTest.java index 37e1cde0cf9..3731f232c97 100644 --- a/log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystemTest.java +++ b/log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/Log4j2CloudConfigLoggingSystemTest.java @@ -19,23 +19,41 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.spi.LoggerContext; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetSystemProperty; +import org.springframework.boot.logging.LoggingSystem; +import org.springframework.boot.logging.log4j2.Log4J2LoggingSystem; + +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.List; -import static org.junit.Assert.assertTrue; - public class Log4j2CloudConfigLoggingSystemTest { @Test public void getStandardConfigLocations() { String customLog4j2Location = "classpath:my_custom_log4j2.properties"; - LoggerContext lc = LogManager.getContext(); // Initialize LogManager to here to prevent a failure trying to initialize it from StatusLogger. + LoggerContext lc = LogManager.getContext(); // Initialize LogManager to here to prevent a failure trying to + // initialize it from StatusLogger. System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, customLog4j2Location); - Log4j2CloudConfigLoggingSystem cloudLoggingSystem = new Log4j2CloudConfigLoggingSystem(this.getClass().getClassLoader()); + Log4j2CloudConfigLoggingSystem cloudLoggingSystem = new Log4j2CloudConfigLoggingSystem( + this.getClass().getClassLoader()); List standardConfigLocations = Arrays.asList(cloudLoggingSystem.getStandardConfigLocations()); assertTrue(standardConfigLocations.contains(customLog4j2Location)); } + + @Test + @SetSystemProperty(key = Log4j2CloudConfigLoggingSystem.LOG4J2_DISABLE_CLOUD_CONFIG_LOGGING_SYSTEM, value = "true") + public void testUseLog4j2LoggingSystem() { + LoggingSystem loggingSystem = LoggingSystem.get(getClass().getClassLoader()); + assertTrue(loggingSystem.getClass().equals(Log4J2LoggingSystem.class)); + } + + @Test + public void testLoggingSystemEnabled() { + LoggingSystem loggingSystem = LoggingSystem.get(getClass().getClassLoader()); + assertTrue(loggingSystem.getClass().equals(Log4j2CloudConfigLoggingSystem.class)); + } } diff --git a/src/site/xdoc/manual/configuration.xml.vm b/src/site/xdoc/manual/configuration.xml.vm index 5aa109ac802..f9a95d6cdf9 100644 --- a/src/site/xdoc/manual/configuration.xml.vm +++ b/src/site/xdoc/manual/configuration.xml.vm @@ -2878,6 +2878,12 @@ public class AwesomeTest { that advertises the same language(s) in order for scripting to be enabled. If no languages are specified, which is the default, the ScriptManager will not be installed. + + log4j2.disableCloudConfigLoggingSystem + + + Disables the usage of the Spring Boot Log4j2CloudConfigLoggingSystem. Defaults to false. +