diff --git a/spring-boot/src/main/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializer.java index 3790823a20..9b63762df3 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializer.java @@ -18,18 +18,24 @@ package org.springframework.boot.context.initializer; import java.lang.management.ManagementFactory; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplicationInitializer; +import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; +import org.springframework.core.env.SimpleCommandLinePropertySource; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.ObjectUtils; import org.springframework.util.ResourceUtils; /** @@ -76,17 +82,42 @@ public class LoggingApplicationContextInitializer implements ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.put("PID", "PID"); } + private static MultiValueMap LOG_LEVEL_LOGGERS; + static { + LOG_LEVEL_LOGGERS = new LinkedMultiValueMap(); + LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.springframework.boot"); + LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.springframework"); + LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.apache.tomcat"); + LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.eclipse.jetty"); + } + private final Log logger = LogFactory.getLog(getClass()); private int order = Integer.MIN_VALUE + 11; + private boolean parseArgs = true; + + private LogLevel springBootLogging = null; + @Override public void initialize(SpringApplication springApplication, String[] args) { if (System.getProperty("PID") == null) { System.setProperty("PID", getPid()); } - LoggingSystem.get(springApplication.getClass().getClassLoader()) - .beforeInitialize(); + LoggingSystem loggingSystem = LoggingSystem.get(springApplication.getClass() + .getClassLoader()); + loggingSystem.beforeInitialize(); + if (this.parseArgs && this.springBootLogging == null + && !ObjectUtils.isEmpty(args)) { + SimpleCommandLinePropertySource parsedArgs = new SimpleCommandLinePropertySource( + args); + if (parsedArgs.containsProperty("debug")) { + this.springBootLogging = LogLevel.DEBUG; + } + if (parsedArgs.containsProperty("trace")) { + this.springBootLogging = LogLevel.TRACE; + } + } } /** @@ -124,6 +155,18 @@ public class LoggingApplicationContextInitializer implements } system.initialize(); + if (this.springBootLogging != null) { + initializeLogLeve(system, this.springBootLogging); + } + } + + protected void initializeLogLeve(LoggingSystem system, LogLevel level) { + List loggers = LOG_LEVEL_LOGGERS.get(level); + if (loggers != null) { + for (String logger : loggers) { + system.setLogLevel(logger, level); + } + } } private String getPid() { @@ -143,4 +186,20 @@ public class LoggingApplicationContextInitializer implements return this.order; } + /** + * Sets a custom logging level to be used for Spring Boot and related libraries. + * @param springBootLogging the logging level + */ + public void setSpringBootLogging(LogLevel springBootLogging) { + this.springBootLogging = springBootLogging; + } + + /** + * Sets if initialization arguments should be parsed for {@literal --debug} and + * {@literal --trace} options. Defaults to {@code true}. + * @param parseArgs if arguments should be parsed + */ + public void setParseArgs(boolean parseArgs) { + this.parseArgs = parseArgs; + } } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializerTests.java b/spring-boot/src/test/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializerTests.java index 10f08cc6ae..b689476cda 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/initializer/LoggingApplicationContextInitializerTests.java @@ -29,20 +29,27 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.springframework.boot.OutputCapture; import org.springframework.boot.SpringApplication; +import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.java.JavaLoggingSystem; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.env.PropertySource; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** * Tests for {@link LoggingApplicationContextInitializer}. * * @author Dave Syer + * @author Phillip Webb */ public class LoggingApplicationContextInitializerTests { + private static final String[] NO_ARGS = {}; + @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @@ -53,11 +60,15 @@ public class LoggingApplicationContextInitializerTests { private Log logger = new SLF4JLogFactory().getInstance(getClass()); + private SpringApplication springApplication = new SpringApplication(); + + private GenericApplicationContext context = new GenericApplicationContext(); + @Before public void init() throws SecurityException, IOException { LogManager.getLogManager().readConfiguration( JavaLoggingSystem.class.getResourceAsStream("logging.properties")); - this.initializer.initialize(new SpringApplication()); + this.initializer.initialize(new SpringApplication(), NO_ARGS); } @After @@ -79,8 +90,7 @@ public class LoggingApplicationContextInitializerTests { @Test public void testOverrideConfigLocation() { - GenericApplicationContext context = new GenericApplicationContext(); - context.getEnvironment().getPropertySources() + this.context.getEnvironment().getPropertySources() .addFirst(new PropertySource("manual") { @Override public Object getProperty(String name) { @@ -90,7 +100,7 @@ public class LoggingApplicationContextInitializerTests { return null; } }); - this.initializer.initialize(context); + this.initializer.initialize(this.context); this.logger.info("Hello world"); String output = this.outputCapture.toString().trim(); assertTrue("Wrong output:\n" + output, output.contains("Hello world")); @@ -100,8 +110,7 @@ public class LoggingApplicationContextInitializerTests { @Test public void testOverrideConfigDoesNotExist() throws Exception { - GenericApplicationContext context = new GenericApplicationContext(); - context.getEnvironment().getPropertySources() + this.context.getEnvironment().getPropertySources() .addFirst(new PropertySource("manual") { @Override public Object getProperty(String name) { @@ -111,14 +120,13 @@ public class LoggingApplicationContextInitializerTests { return null; } }); - this.initializer.initialize(context); + this.initializer.initialize(this.context); // Should not throw } @Test public void testAddLogFileProperty() { - GenericApplicationContext context = new GenericApplicationContext(); - context.getEnvironment().getPropertySources() + this.context.getEnvironment().getPropertySources() .addFirst(new PropertySource("manual") { @Override public Object getProperty(String name) { @@ -131,7 +139,7 @@ public class LoggingApplicationContextInitializerTests { return null; } }); - this.initializer.initialize(context); + this.initializer.initialize(this.context); Log logger = LogFactory.getLog(LoggingApplicationContextInitializerTests.class); logger.info("Hello world"); String output = this.outputCapture.toString().trim(); @@ -140,8 +148,7 @@ public class LoggingApplicationContextInitializerTests { @Test public void testAddLogPathProperty() { - GenericApplicationContext context = new GenericApplicationContext(); - context.getEnvironment().getPropertySources() + this.context.getEnvironment().getPropertySources() .addFirst(new PropertySource("manual") { @Override public Object getProperty(String name) { @@ -154,11 +161,50 @@ public class LoggingApplicationContextInitializerTests { return null; } }); - this.initializer.initialize(context); + this.initializer.initialize(this.context); Log logger = LogFactory.getLog(LoggingApplicationContextInitializerTests.class); logger.info("Hello world"); String output = this.outputCapture.toString().trim(); assertTrue("Wrong output:\n" + output, output.startsWith("foo/spring.log")); } + @Test + public void parseDebugArg() throws Exception { + this.initializer.initialize(this.springApplication, new String[] { "--debug" }); + this.initializer.initialize(this.context); + this.logger.debug("testatdebug"); + this.logger.trace("testattrace"); + assertThat(this.outputCapture.toString(), containsString("testatdebug")); + assertThat(this.outputCapture.toString(), not(containsString("testattrace"))); + } + + @Test + public void parseTraceArg() throws Exception { + this.context = new GenericApplicationContext(); + this.initializer.initialize(this.springApplication, new String[] { "--trace" }); + this.initializer.initialize(this.context); + this.logger.debug("testatdebug"); + this.logger.trace("testattrace"); + assertThat(this.outputCapture.toString(), containsString("testatdebug")); + assertThat(this.outputCapture.toString(), containsString("testattrace")); + } + + @Test + public void parseArgsDisabled() throws Exception { + this.initializer.setParseArgs(false); + this.initializer.initialize(this.springApplication, new String[] { "--debug" }); + this.initializer.initialize(this.context); + this.logger.debug("testatdebug"); + assertThat(this.outputCapture.toString(), not(containsString("testatdebug"))); + } + + @Test + public void parseArgsDoesntReplace() throws Exception { + this.initializer.setSpringBootLogging(LogLevel.ERROR); + this.initializer.setParseArgs(false); + this.initializer.initialize(this.springApplication, new String[] { "--debug" }); + this.initializer.initialize(this.context); + this.logger.debug("testatdebug"); + assertThat(this.outputCapture.toString(), not(containsString("testatdebug"))); + } }