Commit 169373c0 authored by Phillip Webb's avatar Phillip Webb

Support --debug and --trace increased logging

Update LoggingApplicationContextInitializer to detect the presence of
'--debug' and '--trace' arguments to increase log output.

Using '--debug' will set 'org.springframework.boot' loggers to DEBUG.

Using '--trace' will set 'org.springframework', 'org.apache.tomcat' and
'org.eclipse.jetty' loggers to TRACE.

Issue: #55202588
parent 13444611
......@@ -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<LogLevel, String> LOG_LEVEL_LOGGERS;
static {
LOG_LEVEL_LOGGERS = new LinkedMultiValueMap<LogLevel, String>();
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<String> 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;
}
}
......@@ -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<String>("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<String>("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<String>("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<String>("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")));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment