Commit f3f562f3 authored by Phillip Webb's avatar Phillip Webb

Support <springProfile> in logback configurations

Include support for a new <springProfile> element which can be used in
`logback-spring.xml` files to selectively enable or disable parts of the
configuration. For example:

	<configuration>
		...
		<springProfile name="staging">
			<logger name="sample.logback" level="TRACE" />
		</springProfile>
		...
	</configuration>

Fixes gh-3338
parent 5bc8f0f7
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/> <include resource="org/springframework/boot/logging/logback/base.xml" />
<logger name="sample.logback" level="DEBUG"/> <logger name="sample.logback" level="DEBUG" />
<springProfile name="staging">
<logger name="sample.logback" level="TRACE" />
</springProfile>
</configuration> </configuration>
...@@ -35,4 +35,12 @@ public class SampleLogbackApplicationTests { ...@@ -35,4 +35,12 @@ public class SampleLogbackApplicationTests {
this.outputCapture.expect(not(containsString("Sample Trace Message"))); this.outputCapture.expect(not(containsString("Sample Trace Message")));
} }
@Test
public void testProfile() throws Exception {
SampleLogbackApplication
.main(new String[] { "--spring.profiles.active=staging" });
this.outputCapture.expect(containsString("Sample Debug Message"));
this.outputCapture.expect(containsString("Sample Trace Message"));
}
} }
...@@ -40,31 +40,35 @@ public abstract class AbstractLoggingSystem extends LoggingSystem { ...@@ -40,31 +40,35 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
} }
@Override @Override
public void initialize(String configLocation, LogFile logFile) { public void initialize(LoggingInitializationContext initializationContext,
String configLocation, LogFile logFile) {
if (StringUtils.hasLength(configLocation)) { if (StringUtils.hasLength(configLocation)) {
initializeWithSpecificConfig(configLocation, logFile); initializeWithSpecificConfig(initializationContext, configLocation, logFile);
return; return;
} }
initializeWithConventions(logFile); initializeWithConventions(initializationContext, logFile);
} }
private void initializeWithSpecificConfig(String configLocation, LogFile logFile) { private void initializeWithSpecificConfig(
LoggingInitializationContext initializationContext, String configLocation,
LogFile logFile) {
configLocation = SystemPropertyUtils.resolvePlaceholders(configLocation); configLocation = SystemPropertyUtils.resolvePlaceholders(configLocation);
loadConfiguration(configLocation, logFile); loadConfiguration(initializationContext, configLocation, logFile);
} }
private void initializeWithConventions(LogFile logFile) { private void initializeWithConventions(
LoggingInitializationContext initializationContext, LogFile logFile) {
String config = getSelfInitializationConfig(); String config = getSelfInitializationConfig();
if (config != null && logFile == null) { if (config != null && logFile == null) {
// self initialization has occurred, reinitialize in case of property changes // self initialization has occurred, reinitialize in case of property changes
reinitialize(); reinitialize(initializationContext);
return; return;
} }
if (config == null) { if (config == null) {
config = getSpringInitializationConfig(); config = getSpringInitializationConfig();
} }
if (config != null) { if (config != null) {
loadConfiguration(config, logFile); loadConfiguration(initializationContext, config, logFile);
return; return;
} }
loadDefaults(logFile); loadDefaults(logFile);
...@@ -131,18 +135,22 @@ public abstract class AbstractLoggingSystem extends LoggingSystem { ...@@ -131,18 +135,22 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
/** /**
* Load a specific configuration. * Load a specific configuration.
* @param initializationContext the logging initialization context
* @param location the location of the configuration to load (never {@code null}) * @param location the location of the configuration to load (never {@code null})
* @param logFile the file to load or {@code null} if no log file is to be written * @param logFile the file to load or {@code null} if no log file is to be written
*/ */
protected abstract void loadConfiguration(String location, LogFile logFile); protected abstract void loadConfiguration(
LoggingInitializationContext initializationContext, String location,
LogFile logFile);
/** /**
* Reinitialize the logging system if required. Called when * Reinitialize the logging system if required. Called when
* {@link #getSelfInitializationConfig()} is used and the log file hasn't changed. May * {@link #getSelfInitializationConfig()} is used and the log file hasn't changed. May
* be used to reload configuration (for example to pickup additional System * be used to reload configuration (for example to pickup additional System
* properties). * properties).
* @param initializationContext the logging initialization context
*/ */
protected void reinitialize() { protected void reinitialize(LoggingInitializationContext initializationContext) {
} }
protected final ClassLoader getClassLoader() { protected final ClassLoader getClassLoader() {
......
...@@ -198,12 +198,14 @@ public class LoggingApplicationListener implements GenericApplicationListener { ...@@ -198,12 +198,14 @@ public class LoggingApplicationListener implements GenericApplicationListener {
private void initializeSystem(ConfigurableEnvironment environment, private void initializeSystem(ConfigurableEnvironment environment,
LoggingSystem system) { LoggingSystem system) {
LoggingInitializationContext initializationContext = new LoggingInitializationContext(
environment);
LogFile logFile = LogFile.get(environment); LogFile logFile = LogFile.get(environment);
String logConfig = environment.getProperty(CONFIG_PROPERTY); String logConfig = environment.getProperty(CONFIG_PROPERTY);
if (StringUtils.hasLength(logConfig)) { if (StringUtils.hasLength(logConfig)) {
try { try {
ResourceUtils.getURL(logConfig).openStream().close(); ResourceUtils.getURL(logConfig).openStream().close();
system.initialize(logConfig, logFile); system.initialize(initializationContext, logConfig, logFile);
} }
catch (Exception ex) { catch (Exception ex) {
// NOTE: We can't use the logger here to report the problem // NOTE: We can't use the logger here to report the problem
...@@ -214,7 +216,7 @@ public class LoggingApplicationListener implements GenericApplicationListener { ...@@ -214,7 +216,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
} }
} }
else { else {
system.initialize(null, logFile); system.initialize(initializationContext, null, logFile);
} }
} }
......
/*
* Copyright 2012-2015 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
*
* http://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 org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* Context passed to the {@link LoggingSystem} during initialization.
*
* @author Phillip Webb
* @since 1.3.0
*/
public class LoggingInitializationContext {
private final ConfigurableEnvironment environment;
/**
* Create a new {@link LoggingInitializationContext} instance.
* @param environment the Spring environment.
*/
public LoggingInitializationContext(ConfigurableEnvironment environment) {
this.environment = environment;
}
/**
* Return the Spring environment if available.
* @return the {@link Environment} or {@code null}
*/
public Environment getEnvironment() {
return this.environment;
}
}
...@@ -53,19 +53,21 @@ public abstract class LoggingSystem { ...@@ -53,19 +53,21 @@ public abstract class LoggingSystem {
/** /**
* Reset the logging system to be limit output. This method may be called before * Reset the logging system to be limit output. This method may be called before
* {@link #initialize(String, LogFile)} to reduce logging noise until the system has * {@link #initialize(LoggingInitializationContext, String, LogFile)} to reduce
* been fully Initialized. * logging noise until the system has been fully Initialized.
*/ */
public abstract void beforeInitialize(); public abstract void beforeInitialize();
/** /**
* Fully initialize the logging system. * Fully initialize the logging system.
* @param initializationContext the logging initialization context
* @param configLocation a log configuration location or {@code null} if default * @param configLocation a log configuration location or {@code null} if default
* initialization is required * initialization is required
* @param logFile the log output file that should be written or {@code null} for * @param logFile the log output file that should be written or {@code null} for
* console only output * console only output
*/ */
public abstract void initialize(String configLocation, LogFile logFile); public abstract void initialize(LoggingInitializationContext initializationContext,
String configLocation, LogFile logFile);
/** /**
* Clean up the logging system. The default implementation does nothing. Subclasses * Clean up the logging system. The default implementation does nothing. Subclasses
......
...@@ -28,6 +28,7 @@ import java.util.logging.Logger; ...@@ -28,6 +28,7 @@ import java.util.logging.Logger;
import org.springframework.boot.logging.AbstractLoggingSystem; import org.springframework.boot.logging.AbstractLoggingSystem;
import org.springframework.boot.logging.LogFile; import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem; import org.springframework.boot.logging.LoggingSystem;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
...@@ -81,6 +82,11 @@ public class JavaLoggingSystem extends AbstractLoggingSystem { ...@@ -81,6 +82,11 @@ public class JavaLoggingSystem extends AbstractLoggingSystem {
} }
@Override @Override
protected void loadConfiguration(LoggingInitializationContext initializationContext,
String location, LogFile logFile) {
loadConfiguration(location, logFile);
}
protected void loadConfiguration(String location, LogFile logFile) { protected void loadConfiguration(String location, LogFile logFile) {
Assert.notNull(location, "Location must not be null"); Assert.notNull(location, "Location must not be null");
try { try {
......
...@@ -25,6 +25,7 @@ import org.apache.log4j.LogManager; ...@@ -25,6 +25,7 @@ import org.apache.log4j.LogManager;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.boot.logging.LogFile; import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem; import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.boot.logging.Slf4JLoggingSystem;
import org.springframework.util.Assert; import org.springframework.util.Assert;
...@@ -79,6 +80,11 @@ public class Log4JLoggingSystem extends Slf4JLoggingSystem { ...@@ -79,6 +80,11 @@ public class Log4JLoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
protected void loadConfiguration(LoggingInitializationContext initializationContext,
String location, LogFile logFile) {
loadConfiguration(location, logFile);
}
protected void loadConfiguration(String location, LogFile logFile) { protected void loadConfiguration(String location, LogFile logFile) {
Assert.notNull(location, "Location must not be null"); Assert.notNull(location, "Location must not be null");
if (logFile != null) { if (logFile != null) {
...@@ -94,7 +100,7 @@ public class Log4JLoggingSystem extends Slf4JLoggingSystem { ...@@ -94,7 +100,7 @@ public class Log4JLoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
protected void reinitialize() { protected void reinitialize(LoggingInitializationContext initializationContext) {
loadConfiguration(getSelfInitializationConfig(), null); loadConfiguration(getSelfInitializationConfig(), null);
} }
......
...@@ -39,6 +39,7 @@ import org.apache.logging.log4j.core.filter.AbstractFilter; ...@@ -39,6 +39,7 @@ import org.apache.logging.log4j.core.filter.AbstractFilter;
import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.Message;
import org.springframework.boot.logging.LogFile; import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem; import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.boot.logging.Slf4JLoggingSystem;
import org.springframework.util.Assert; import org.springframework.util.Assert;
...@@ -128,9 +129,10 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem { ...@@ -128,9 +129,10 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
public void initialize(String configLocation, LogFile logFile) { public void initialize(LoggingInitializationContext initializationContext,
String configLocation, LogFile logFile) {
getLoggerConfig(null).removeFilter(FILTER); getLoggerConfig(null).removeFilter(FILTER);
super.initialize(configLocation, logFile); super.initialize(initializationContext, configLocation, logFile);
} }
@Override @Override
...@@ -144,6 +146,11 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem { ...@@ -144,6 +146,11 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
protected void loadConfiguration(LoggingInitializationContext initializationContext,
String location, LogFile logFile) {
loadConfiguration(location, logFile);
}
protected void loadConfiguration(String location, LogFile logFile) { protected void loadConfiguration(String location, LogFile logFile) {
Assert.notNull(location, "Location must not be null"); Assert.notNull(location, "Location must not be null");
if (logFile != null) { if (logFile != null) {
...@@ -170,7 +177,7 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem { ...@@ -170,7 +177,7 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
protected void reinitialize() { protected void reinitialize(LoggingInitializationContext initializationContext) {
getLoggerContext().reconfigure(); getLoggerContext().reconfigure();
} }
......
...@@ -30,6 +30,7 @@ import org.slf4j.Marker; ...@@ -30,6 +30,7 @@ import org.slf4j.Marker;
import org.slf4j.impl.StaticLoggerBinder; import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.boot.logging.LogFile; import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem; import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.boot.logging.Slf4JLoggingSystem;
import org.springframework.util.Assert; import org.springframework.util.Assert;
...@@ -38,8 +39,10 @@ import org.springframework.util.StringUtils; ...@@ -38,8 +39,10 @@ import org.springframework.util.StringUtils;
import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.turbo.TurboFilter; import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.classic.util.ContextInitializer; import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.spi.FilterReply; import ch.qos.logback.core.spi.FilterReply;
import ch.qos.logback.core.status.Status; import ch.qos.logback.core.status.Status;
...@@ -93,9 +96,10 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem { ...@@ -93,9 +96,10 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
public void initialize(String configLocation, LogFile logFile) { public void initialize(LoggingInitializationContext initializationContext,
String configLocation, LogFile logFile) {
getLogger(null).getLoggerContext().getTurboFilterList().remove(FILTER); getLogger(null).getLoggerContext().getTurboFilterList().remove(FILTER);
super.initialize(configLocation, logFile); super.initialize(initializationContext, configLocation, logFile);
} }
@Override @Override
...@@ -108,23 +112,24 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem { ...@@ -108,23 +112,24 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
protected void loadConfiguration(String location, LogFile logFile) { protected void loadConfiguration(LoggingInitializationContext initializationContext,
String location, LogFile logFile) {
Assert.notNull(location, "Location must not be null"); Assert.notNull(location, "Location must not be null");
if (logFile != null) { if (logFile != null) {
logFile.applyToSystemProperties(); logFile.applyToSystemProperties();
} }
LoggerContext context = getLoggerContext(); LoggerContext loggerContext = getLoggerContext();
context.stop(); loggerContext.stop();
context.reset(); loggerContext.reset();
try { try {
URL url = ResourceUtils.getURL(location); configureByResourceUrl(initializationContext, loggerContext,
new ContextInitializer(context).configureByResource(url); ResourceUtils.getURL(location));
} }
catch (Exception ex) { catch (Exception ex) {
throw new IllegalStateException("Could not initialize Logback logging from " throw new IllegalStateException("Could not initialize Logback logging from "
+ location, ex); + location, ex);
} }
List<Status> statuses = context.getStatusManager().getCopyOfStatusList(); List<Status> statuses = loggerContext.getStatusManager().getCopyOfStatusList();
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
for (Status status : statuses) { for (Status status : statuses) {
if (status.getLevel() == Status.ERROR) { if (status.getLevel() == Status.ERROR) {
...@@ -138,6 +143,20 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem { ...@@ -138,6 +143,20 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
} }
} }
private void configureByResourceUrl(
LoggingInitializationContext initializationContext,
LoggerContext loggerContext, URL url) throws JoranException {
if (url.toString().endsWith("xml")) {
JoranConfigurator configurator = new SpringBootJoranConfigurator(
initializationContext);
configurator.setContext(loggerContext);
configurator.doConfigure(url);
}
else {
new ContextInitializer(loggerContext).configureByResource(url);
}
}
@Override @Override
public void cleanUp() { public void cleanUp() {
super.cleanUp(); super.cleanUp();
...@@ -145,9 +164,9 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem { ...@@ -145,9 +164,9 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
} }
@Override @Override
protected void reinitialize() { protected void reinitialize(LoggingInitializationContext initializationContext) {
getLoggerContext().reset(); getLoggerContext().reset();
loadConfiguration(getSelfInitializationConfig(), null); loadConfiguration(initializationContext, getSelfInitializationConfig(), null);
} }
private void configureJBossLoggingToUseSlf4j() { private void configureJBossLoggingToUseSlf4j() {
......
/*
* Copyright 2012-2015 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
*
* http://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.logback;
import org.springframework.boot.logging.LoggingInitializationContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.action.NOPAction;
import ch.qos.logback.core.joran.spi.ElementSelector;
import ch.qos.logback.core.joran.spi.RuleStore;
/**
* Extended version of the Logback {@link JoranConfigurator} that adds additional Spring
* Boot rules.
*
* @author Phillip Webb
*/
class SpringBootJoranConfigurator extends JoranConfigurator {
private LoggingInitializationContext initializationContext;
public SpringBootJoranConfigurator(LoggingInitializationContext initializationContext) {
this.initializationContext = initializationContext;
}
@Override
public void addInstanceRules(RuleStore rs) {
super.addInstanceRules(rs);
rs.addRule(new ElementSelector("*/springProfile"), new SpringProfileAction(
this.initializationContext.getEnvironment()));
rs.addRule(new ElementSelector("*/springProfile/*"), new NOPAction());
}
}
/*
* Copyright 2012-2015 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
*
* http://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.logback;
import java.util.ArrayList;
import java.util.List;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.xml.sax.Attributes;
import ch.qos.logback.core.joran.action.Action;
import ch.qos.logback.core.joran.event.InPlayListener;
import ch.qos.logback.core.joran.event.SaxEvent;
import ch.qos.logback.core.joran.spi.ActionException;
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.joran.spi.Interpreter;
import ch.qos.logback.core.util.OptionHelper;
/**
* Lockback {@link Action} to support {@code <springProfile>} tags. Allows section of a
* logback configuration to only be enabled when a specific profile is active.
*
* @author Phillip Webb
*/
class SpringProfileAction extends Action implements InPlayListener {
private final Environment environment;
private int depth = 0;
private boolean acceptsProfile;
private List<SaxEvent> events;
public SpringProfileAction(Environment environment) {
this.environment = environment;
}
@Override
public void begin(InterpretationContext ic, String name, Attributes attributes)
throws ActionException {
this.depth++;
if (this.depth != 1) {
return;
}
ic.pushObject(this);
this.acceptsProfile = acceptsProfiles(ic, attributes);
this.events = new ArrayList<SaxEvent>();
ic.addInPlayListener(this);
}
private boolean acceptsProfiles(InterpretationContext ic, Attributes attributes) {
String profileName = attributes.getValue(NAME_ATTRIBUTE);
if (!OptionHelper.isEmpty(profileName)) {
OptionHelper.substVars(profileName, ic, this.context);
return this.environment != null
&& this.environment.acceptsProfiles(profileName);
}
return false;
}
@Override
public void end(InterpretationContext ic, String name) throws ActionException {
this.depth--;
if (this.depth != 0) {
return;
}
ic.removeInPlayListener(this);
verifyAndPop(ic);
if (this.acceptsProfile) {
addEventsToPlayer(ic);
}
}
private void verifyAndPop(InterpretationContext ic) {
Object o = ic.peekObject();
Assert.state(o != null, "Unexpected null object on stack");
Assert.isInstanceOf(SpringProfileAction.class, o, "logback stack error");
Assert.state(o == this, "ProfileAction different than current one on stack");
ic.popObject();
}
private void addEventsToPlayer(InterpretationContext ic) {
Interpreter interpreter = ic.getJoranInterpreter();
this.events.remove(0);
this.events.remove(this.events.size() - 1);
interpreter.getEventPlayer().addEventsDynamically(this.events, 1);
}
@Override
public void inPlay(SaxEvent event) {
this.events.add(event);
}
}
...@@ -81,7 +81,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests { ...@@ -81,7 +81,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests {
public void noFile() throws Exception { public void noFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -98,7 +98,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests { ...@@ -98,7 +98,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests {
} }
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, getLogFile(null, tmpDir())); this.loggingSystem.initialize(null, null, getLogFile(null, tmpDir()));
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -109,7 +109,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests { ...@@ -109,7 +109,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests {
@Test @Test
public void testCustomFormatter() throws Exception { public void testCustomFormatter() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -121,6 +121,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests { ...@@ -121,6 +121,7 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests {
System.setProperty("PID", "1234"); System.setProperty("PID", "1234");
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize( this.loggingSystem.initialize(
null,
"classpath:" "classpath:"
+ ClassUtils.addResourcePathToPackagePath(getClass(), + ClassUtils.addResourcePathToPackagePath(getClass(),
"logging.properties"), null); "logging.properties"), null);
...@@ -134,7 +135,8 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests { ...@@ -134,7 +135,8 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests {
@Test @Test
public void testNonDefaultConfigLocation() throws Exception { public void testNonDefaultConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:logging-nondefault.properties", null); this.loggingSystem.initialize(null, "classpath:logging-nondefault.properties",
null);
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("INFO: Hello")); assertTrue("Wrong output:\n" + output, output.contains("INFO: Hello"));
...@@ -143,13 +145,14 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests { ...@@ -143,13 +145,14 @@ public class JavaLoggerSystemTests extends AbstractLoggingSystemTests {
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void testNonexistentConfigLocation() throws Exception { public void testNonexistentConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:logging-nonexistent.properties", null); this.loggingSystem.initialize(null, "classpath:logging-nonexistent.properties",
null);
} }
@Test @Test
public void setLevel() throws Exception { public void setLevel() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
this.logger.debug("Hello"); this.logger.debug("Hello");
this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG);
this.logger.debug("Hello"); this.logger.debug("Hello");
......
...@@ -68,7 +68,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -68,7 +68,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
public void noFile() throws Exception { public void noFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -80,7 +80,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -80,7 +80,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
public void withFile() throws Exception { public void withFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, getLogFile(null, tmpDir())); this.loggingSystem.initialize(null, null, getLogFile(null, tmpDir()));
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -91,7 +91,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -91,7 +91,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
@Test @Test
public void testNonDefaultConfigLocation() throws Exception { public void testNonDefaultConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:log4j-nondefault.properties", this.loggingSystem.initialize(null, "classpath:log4j-nondefault.properties",
getLogFile(null, tmpDir())); getLogFile(null, tmpDir()));
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
...@@ -103,13 +103,13 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -103,13 +103,13 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void testNonexistentConfigLocation() throws Exception { public void testNonexistentConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:log4j-nonexistent.xml", null); this.loggingSystem.initialize(null, "classpath:log4j-nonexistent.xml", null);
} }
@Test @Test
public void setLevel() throws Exception { public void setLevel() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
this.logger.debug("Hello"); this.logger.debug("Hello");
this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG);
this.logger.debug("Hello"); this.logger.debug("Hello");
...@@ -121,7 +121,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -121,7 +121,7 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
@Ignore("Fails on Bamboo") @Ignore("Fails on Bamboo")
public void loggingThatUsesJulIsCaptured() { public void loggingThatUsesJulIsCaptured() {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
java.util.logging.Logger julLogger = java.util.logging.Logger java.util.logging.Logger julLogger = java.util.logging.Logger
.getLogger(getClass().getName()); .getLogger(getClass().getName());
julLogger.severe("Hello world"); julLogger.severe("Hello world");
......
...@@ -71,7 +71,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -71,7 +71,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
public void noFile() throws Exception { public void noFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -85,7 +85,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -85,7 +85,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
public void withFile() throws Exception { public void withFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, getLogFile(null, tmpDir())); this.loggingSystem.initialize(null, null, getLogFile(null, tmpDir()));
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -98,7 +98,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -98,7 +98,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
@Test @Test
public void testNonDefaultConfigLocation() throws Exception { public void testNonDefaultConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:log4j2-nondefault.xml", this.loggingSystem.initialize(null, "classpath:log4j2-nondefault.xml",
getLogFile(tmpDir() + "/tmp.log", null)); getLogFile(tmpDir() + "/tmp.log", null));
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
...@@ -116,13 +116,13 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -116,13 +116,13 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void testNonexistentConfigLocation() throws Exception { public void testNonexistentConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:log4j2-nonexistent.xml", null); this.loggingSystem.initialize(null, "classpath:log4j2-nonexistent.xml", null);
} }
@Test @Test
public void setLevel() throws Exception { public void setLevel() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
this.logger.debug("Hello"); this.logger.debug("Hello");
this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG);
this.logger.debug("Hello"); this.logger.debug("Hello");
...@@ -134,7 +134,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -134,7 +134,7 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
@Ignore("Fails on Bamboo") @Ignore("Fails on Bamboo")
public void loggingThatUsesJulIsCaptured() { public void loggingThatUsesJulIsCaptured() {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(null, null, null);
java.util.logging.Logger julLogger = java.util.logging.Logger java.util.logging.Logger julLogger = java.util.logging.Logger
.getLogger(getClass().getName()); .getLogger(getClass().getName());
julLogger.severe("Hello world"); julLogger.severe("Hello world");
......
...@@ -31,7 +31,9 @@ import org.slf4j.bridge.SLF4JBridgeHandler; ...@@ -31,7 +31,9 @@ import org.slf4j.bridge.SLF4JBridgeHandler;
import org.slf4j.impl.StaticLoggerBinder; import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.boot.logging.AbstractLoggingSystemTests; import org.springframework.boot.logging.AbstractLoggingSystemTests;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.test.OutputCapture; import org.springframework.boot.test.OutputCapture;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
...@@ -61,9 +63,13 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -61,9 +63,13 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
private Log logger; private Log logger;
private LoggingInitializationContext initializationContext;
@Before @Before
public void setup() { public void setup() {
this.logger = new SLF4JLogFactory().getInstance(getClass().getName()); this.logger = new SLF4JLogFactory().getInstance(getClass().getName());
this.initializationContext = new LoggingInitializationContext(
new MockEnvironment());
} }
@Override @Override
...@@ -76,7 +82,7 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -76,7 +82,7 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
public void noFile() throws Exception { public void noFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(this.initializationContext, null, null);
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -88,7 +94,8 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -88,7 +94,8 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
public void withFile() throws Exception { public void withFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.logger.info("Hidden"); this.logger.info("Hidden");
this.loggingSystem.initialize(null, getLogFile(null, tmpDir())); this.loggingSystem.initialize(this.initializationContext, null,
getLogFile(null, tmpDir()));
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
...@@ -108,7 +115,8 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -108,7 +115,8 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
@Test @Test
public void testNonDefaultConfigLocation() throws Exception { public void testNonDefaultConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:logback-nondefault.xml", this.loggingSystem.initialize(this.initializationContext,
"classpath:logback-nondefault.xml",
getLogFile(tmpDir() + "/tmp.log", null)); getLogFile(tmpDir() + "/tmp.log", null));
this.logger.info("Hello world"); this.logger.info("Hello world");
String output = this.output.toString().trim(); String output = this.output.toString().trim();
...@@ -121,13 +129,14 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -121,13 +129,14 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void testNonexistentConfigLocation() throws Exception { public void testNonexistentConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:logback-nonexistent.xml", null); this.loggingSystem.initialize(this.initializationContext,
"classpath:logback-nonexistent.xml", null);
} }
@Test @Test
public void setLevel() throws Exception { public void setLevel() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(this.initializationContext, null, null);
this.logger.debug("Hello"); this.logger.debug("Hello");
this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG);
this.logger.debug("Hello"); this.logger.debug("Hello");
...@@ -138,7 +147,7 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -138,7 +147,7 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
@Test @Test
public void loggingThatUsesJulIsCaptured() { public void loggingThatUsesJulIsCaptured() {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null, null); this.loggingSystem.initialize(this.initializationContext, null, null);
java.util.logging.Logger julLogger = java.util.logging.Logger java.util.logging.Logger julLogger = java.util.logging.Logger
.getLogger(getClass().getName()); .getLogger(getClass().getName());
julLogger.info("Hello world"); julLogger.info("Hello world");
......
/*
* Copyright 2012-2015 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
*
* http://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.logback;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.test.OutputCapture;
import org.springframework.mock.env.MockEnvironment;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
/**
* Tests for {@link SpringBootJoranConfigurator}.
*
* @author Phillip Webb
*/
public class SpringBootJoranConfiguratorTests {
@Rule
public OutputCapture out = new OutputCapture();
private MockEnvironment environment;
private LoggingInitializationContext initializationContext;
private JoranConfigurator configurator;
private LoggerContext context;
private Logger logger;
@Before
public void setup() {
this.environment = new MockEnvironment();
this.initializationContext = new LoggingInitializationContext(this.environment);
this.configurator = new SpringBootJoranConfigurator(this.initializationContext);
StaticLoggerBinder binder = StaticLoggerBinder.getSingleton();
this.context = (LoggerContext) binder.getLoggerFactory();
this.logger = this.context.getLogger(getClass());
}
@After
public void reset() {
this.context.reset();
}
@Test
public void profileActive() throws Exception {
this.environment.setActiveProfiles("production");
initialize("production-profile.xml");
this.logger.trace("Hello");
this.out.expect(containsString("Hello"));
}
@Test
public void profileNotActive() throws Exception {
initialize("production-profile.xml");
this.logger.trace("Hello");
this.out.expect(not(containsString("Hello")));
}
@Test
public void profileNestedActiveActive() throws Exception {
doTestNestedProfile(true, "outer", "inner");
}
@Test
public void profileNestedActiveNotActive() throws Exception {
doTestNestedProfile(false, "outer");
}
@Test
public void profileNestedNotActiveActive() throws Exception {
doTestNestedProfile(false, "inner");
}
@Test
public void profileNestedNotActiveNotActive() throws Exception {
doTestNestedProfile(false);
}
private void doTestNestedProfile(boolean expected, String... profiles)
throws JoranException {
this.environment.setActiveProfiles(profiles);
initialize("nested.xml");
this.logger.trace("Hello");
if (expected) {
this.out.expect(containsString("Hello"));
}
else {
this.out.expect(not(containsString("Hello")));
}
}
private void initialize(String config) throws JoranException {
this.configurator.setContext(this.context);
this.configurator.doConfigure(getClass().getResourceAsStream(config));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProfile name="outer">
<springProfile name="inner">
<logger name="org.springframework.boot.logging.logback" level="TRACE" />
</springProfile>
</springProfile>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProfile name="production">
<logger name="org.springframework.boot.logging.logback" level="TRACE" />
</springProfile>
</configuration>
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