From cf24af0bfbfdd778bfb076947ea6f012a88f372d Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 29 Oct 2014 22:05:05 -0700 Subject: [PATCH] Rework logging to prevent double initialization Prior to this commit LoggingSystem initialization would happen multiple times. Once to configure "quiet" logging, and again to configure correct settings once the Application was initialized. This could cause problems if `logging.groovy` logback files were used. The logging system is now only initialized once (when possible) by following these steps: - Standard logging initialization occurs via the actual logging implementation used (e.g. logback will load a logback.xml file if it exists) - beforeInitization() is called to prevent early log output. Implementations now either use a Filter or simply set the root logging level. - initialize() is called with an optional log configuration file (e.g a custom logback.xml location) and an optional log output file (the default is null indicating console only output). The initialize() method will attempt to prevent double initialization by checking if a standard configuration file exists. Double initialization now only occurs in the following situations: - The user has a standard configuration file (e.g. classpath:logback.xml) but also specifies a logging.config property. Double initialization is required since the specified configuration file supersedes the default. - The user has a standard configuration file (e.g. classpath:logback.xml) and specifies a logging.file property. Double initialization is required since the standard configuration may use a ${LOG_FILE} reference. In addition this commit removes the `logging.console` option and now assumes that logging either occurs only to console or to both the console and a file. This restriction helps simplify the LoggingSystem implementations. If file only logging is required a custom logback.xml can be used. Fixes gh-1091 See gh-1612, gh-1770 --- .../endpoint/jmx/EndpointMBeanExporter.java | 2 +- .../src/test/resources/logback.xml | 7 - ...va => SampleActuatorLog4JApplication.java} | 4 +- .../log4j/SampleActuatorApplicationTests.java | 2 +- ...a => SampleActuatorLog4J2Application.java} | 4 +- .../SampleActuatorApplicationTests.java | 2 +- .../boot/SpringApplication.java | 7 +- .../boot/logging/AbstractLoggingSystem.java | 93 +++++----- .../logging/LoggingApplicationListener.java | 170 +++++++----------- .../boot/logging/LoggingSystem.java | 44 +++-- .../boot/logging/Slf4JLoggingSystem.java | 9 +- .../boot/logging/java/JavaLoggingSystem.java | 47 +++-- .../logging/log4j/Log4JLoggingSystem.java | 38 ++-- .../logging/log4j2/Log4J2LoggingSystem.java | 58 +++--- .../logging/logback/LogbackLoggingSystem.java | 70 ++++++-- .../logging/java/basic-logging.properties | 13 -- .../java/logging-file-console.properties | 20 --- .../boot/logging/java/logging-file.properties | 7 +- .../boot/logging/java/logging-none.properties | 10 -- .../boot/logging/log4j/basic-log4j.properties | 17 -- .../log4j/log4j-file-console.properties | 25 --- .../boot/logging/log4j/log4j-file.properties | 21 ++- .../boot/logging/log4j/log4j-none.properties | 15 -- .../boot/logging/log4j/log4j.properties | 16 +- .../boot/logging/log4j2/basic-log4j2.xml | 25 --- .../logging/log4j2/log4j2-file-console.xml | 37 ---- .../boot/logging/log4j2/log4j2-file.xml | 65 +++---- .../boot/logging/log4j2/log4j2-none.xml | 21 --- .../boot/logging/log4j2/log4j2.xml | 50 +++--- .../boot/logging/logback/base.xml | 32 ++-- .../boot/logging/logback/basic-logback.xml | 4 - .../boot/logging/logback/console-appender.xml | 9 + .../{base-file.xml => file-appender.xml} | 6 - .../logging/logback/logback-file-console.xml | 5 - .../boot/logging/logback/logback-file.xml | 10 +- .../boot/logging/logback/logback-none.xml | 5 - .../boot/logging/logback/logback.xml | 4 + .../logging/AbstractLoggingSystemTests.java | 51 ++++++ .../LoggingApplicationListenerTests.java | 16 +- .../logging/java/JavaLoggerSystemTests.java | 72 ++++++-- .../log4j/Log4JLoggingSystemTests.java | 52 ++++-- .../log4j2/Log4J2LoggingSystemTests.java | 53 ++++-- .../logback/LogbackLoggingSystemTests.java | 56 +++--- .../resources/log4j-nondefault.properties | 2 - .../src/test/resources/log4j2-nondefault.xml | 32 ++-- .../src/test/resources/logback-nondefault.xml | 3 +- 46 files changed, 653 insertions(+), 658 deletions(-) delete mode 100644 spring-boot-cli/src/test/resources/logback.xml rename spring-boot-samples/spring-boot-sample-actuator-log4j/src/main/java/sample/actuator/log4j/{SampleActuatorApplication.java => SampleActuatorLog4JApplication.java} (90%) rename spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/java/sample/actuator/log4j2/{SampleActuatorApplication.java => SampleActuatorLog4J2Application.java} (90%) delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/java/basic-logging.properties delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file-console.properties delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-none.properties delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/log4j/basic-log4j.properties delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file-console.properties delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-none.properties delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/basic-log4j2.xml delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file-console.xml delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-none.xml delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/logback/basic-logback.xml create mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/logback/console-appender.xml rename spring-boot/src/main/resources/org/springframework/boot/logging/logback/{base-file.xml => file-appender.xml} (55%) delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file-console.xml delete mode 100644 spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-none.xml create mode 100644 spring-boot/src/test/java/org/springframework/boot/logging/AbstractLoggingSystemTests.java diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java index 7a3076e93e..cdcceca3af 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporter.java @@ -111,7 +111,7 @@ public class EndpointMBeanExporter extends MBeanExporter implements SmartLifecyc this.beanFactory = (ListableBeanFactory) beanFactory; } else { - logger.info("EndpointMBeanExporter not running in a ListableBeanFactory: " + logger.warn("EndpointMBeanExporter not running in a ListableBeanFactory: " + "autodetection of Endpoints not available."); } } diff --git a/spring-boot-cli/src/test/resources/logback.xml b/spring-boot-cli/src/test/resources/logback.xml deleted file mode 100644 index 566ec197ec..0000000000 --- a/spring-boot-cli/src/test/resources/logback.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-boot-samples/spring-boot-sample-actuator-log4j/src/main/java/sample/actuator/log4j/SampleActuatorApplication.java b/spring-boot-samples/spring-boot-sample-actuator-log4j/src/main/java/sample/actuator/log4j/SampleActuatorLog4JApplication.java similarity index 90% rename from spring-boot-samples/spring-boot-sample-actuator-log4j/src/main/java/sample/actuator/log4j/SampleActuatorApplication.java rename to spring-boot-samples/spring-boot-sample-actuator-log4j/src/main/java/sample/actuator/log4j/SampleActuatorLog4JApplication.java index 510ff7307c..d75731aceb 100644 --- a/spring-boot-samples/spring-boot-sample-actuator-log4j/src/main/java/sample/actuator/log4j/SampleActuatorApplication.java +++ b/spring-boot-samples/spring-boot-sample-actuator-log4j/src/main/java/sample/actuator/log4j/SampleActuatorLog4JApplication.java @@ -26,10 +26,10 @@ import org.springframework.context.annotation.Configuration; @EnableAutoConfiguration @EnableConfigurationProperties @ComponentScan -public class SampleActuatorApplication { +public class SampleActuatorLog4JApplication { public static void main(String[] args) throws Exception { - SpringApplication.run(SampleActuatorApplication.class, args); + SpringApplication.run(SampleActuatorLog4JApplication.class, args); } } diff --git a/spring-boot-samples/spring-boot-sample-actuator-log4j/src/test/java/sample/actuator/log4j/SampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator-log4j/src/test/java/sample/actuator/log4j/SampleActuatorApplicationTests.java index f3b37bca4b..1137113d76 100644 --- a/spring-boot-samples/spring-boot-sample-actuator-log4j/src/test/java/sample/actuator/log4j/SampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator-log4j/src/test/java/sample/actuator/log4j/SampleActuatorApplicationTests.java @@ -38,7 +38,7 @@ import static org.junit.Assert.assertEquals; * @author Dave Syer */ @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SampleActuatorApplication.class) +@SpringApplicationConfiguration(classes = SampleActuatorLog4JApplication.class) @WebAppConfiguration @IntegrationTest("server.port=0") @DirtiesContext diff --git a/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/java/sample/actuator/log4j2/SampleActuatorApplication.java b/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/java/sample/actuator/log4j2/SampleActuatorLog4J2Application.java similarity index 90% rename from spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/java/sample/actuator/log4j2/SampleActuatorApplication.java rename to spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/java/sample/actuator/log4j2/SampleActuatorLog4J2Application.java index 9d2cc38678..a7b840a4d2 100644 --- a/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/java/sample/actuator/log4j2/SampleActuatorApplication.java +++ b/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/main/java/sample/actuator/log4j2/SampleActuatorLog4J2Application.java @@ -26,10 +26,10 @@ import org.springframework.context.annotation.Configuration; @EnableAutoConfiguration @EnableConfigurationProperties @ComponentScan -public class SampleActuatorApplication { +public class SampleActuatorLog4J2Application { public static void main(String[] args) throws Exception { - SpringApplication.run(SampleActuatorApplication.class, args); + SpringApplication.run(SampleActuatorLog4J2Application.class, args); } } diff --git a/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/test/java/sample/actuator/log4j2/SampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/test/java/sample/actuator/log4j2/SampleActuatorApplicationTests.java index ad5c29a82c..f9a8c2b6cd 100644 --- a/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/test/java/sample/actuator/log4j2/SampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator-log4j2/src/test/java/sample/actuator/log4j2/SampleActuatorApplicationTests.java @@ -38,7 +38,7 @@ import static org.junit.Assert.assertEquals; * @author Dave Syer */ @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SampleActuatorApplication.class) +@SpringApplicationConfiguration(classes = SampleActuatorLog4J2Application.class) @WebAppConfiguration @IntegrationTest("server.port=0") @DirtiesContext diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 27c9d1d858..552e9df024 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -282,13 +282,12 @@ public class SpringApplication { // Create and configure the environment ConfigurableEnvironment environment = getOrCreateEnvironment(); configureEnvironment(environment, args); - for (SpringApplicationRunListener runListener : runListeners) { - runListener.environmentPrepared(environment); - } - if (this.showBanner) { printBanner(environment); } + for (SpringApplicationRunListener runListener : runListeners) { + runListener.environmentPrepared(environment); + } // Create, load, refresh and run the ApplicationContext context = createApplicationContext(); diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/AbstractLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/AbstractLoggingSystem.java index 04e164ed53..fc4f9c3fbf 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/AbstractLoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/AbstractLoggingSystem.java @@ -19,6 +19,7 @@ package org.springframework.boot.logging; import org.springframework.core.io.ClassPathResource; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import org.springframework.util.SystemPropertyUtils; /** * Abstract base class for {@link LoggingSystem} implementations. @@ -30,50 +31,70 @@ public abstract class AbstractLoggingSystem extends LoggingSystem { private final ClassLoader classLoader; - private final String[] paths; - - private boolean fileOutput; - - private boolean consoleOutput; - public AbstractLoggingSystem(ClassLoader classLoader) { - this(classLoader, false, true); - } - - public AbstractLoggingSystem(ClassLoader classLoader, boolean fileOutput, - boolean consoleOutput) { this.classLoader = classLoader; - this.fileOutput = fileOutput; - this.consoleOutput = consoleOutput; - this.paths = getLogFileNames(); - } - - protected abstract String[] getLogFileNames(); - - protected final ClassLoader getClassLoader() { - return this.classLoader; } @Override public void beforeInitialize() { - initializeWithSensibleDefaults(); } @Override - public void initialize() { - for (String path : this.paths) { - ClassPathResource resource = new ClassPathResource(path, this.classLoader); - if (resource.exists()) { - initialize("classpath:" + path); - return; + public void initialize(String configLocation, String logFile) { + if (StringUtils.hasLength(configLocation)) { + // Load a specific configuration + configLocation = SystemPropertyUtils.resolvePlaceholders(configLocation); + loadConfiguration(configLocation, logFile); + } + else { + String selfInitializationConfig = getSelfInitializationConfig(); + if (selfInitializationConfig == null) { + // No self initialization has occurred, use defaults + loadDefaults(logFile); + } + else if (StringUtils.hasLength(logFile)) { + // Self initialization has occurred but the file has changed, reload + loadConfiguration(selfInitializationConfig, logFile); } } - // Fallback to the non-prefixed value taking into account file and console preferences - initialize(getPackagedConfigFile(addChannels(this.paths[this.paths.length - 1]))); } - protected void initializeWithSensibleDefaults() { - initialize(getPackagedConfigFile("basic-" + this.paths[this.paths.length - 1])); + /** + * Return any self initialization config that has been applied. By default this method + * checks {@link #getStandardConfigLocations()} and assumes that any file that exists + * will have been applied. + */ + protected String getSelfInitializationConfig() { + for (String location : getStandardConfigLocations()) { + ClassPathResource resource = new ClassPathResource(location, this.classLoader); + if (resource.exists()) { + return "classpath:" + location; + } + } + return null; + } + + /** + * Return the standard config locations for this system. + * @see #getSelfInitializationConfig() + */ + protected abstract String[] getStandardConfigLocations(); + + /** + * Load sensible defaults for the logging system. + * @param logFile the file to load or {@code null} if no log file is to be written + */ + protected abstract void loadDefaults(String logFile); + + /** + * Load a specific configuration. + * @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 + */ + protected abstract void loadConfiguration(String location, String logFile); + + protected final ClassLoader getClassLoader() { + return this.classLoader; } protected final String getPackagedConfigFile(String fileName) { @@ -84,14 +105,4 @@ public abstract class AbstractLoggingSystem extends LoggingSystem { return defaultPath; } - private String addChannels(String fileName) { - String extension = "." + StringUtils.getFilenameExtension(fileName); - return fileName.replace(extension, getChannel() + extension); - } - - private String getChannel() { - return (fileOutput && consoleOutput) ? "-file-console" : (fileOutput ? "-file" - : (consoleOutput ? "" : "-none")); - } - } diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java b/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java index ef8671ddde..745aaa1899 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java @@ -16,7 +16,6 @@ package org.springframework.boot.logging; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -41,49 +40,27 @@ import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; /** - * An {@link ApplicationListener} that configures a logging framework depending on what it - * finds on the classpath and in the {@link Environment}. If the environment contains a - * property logging.config then that will be used to initialize the logging - * system, otherwise a default location is used. The classpath is probed for log4j and - * logback and if those are present they will be reconfigured, otherwise vanilla - * java.util.logging will be used.

+ * An {@link ApplicationListener} that configures the {@link LoggingSystem}. If the + * environment contains a {@code logging.config} property a then that will be used to + * initialize the logging system, otherwise a default configuration is used. *

- * The default config locations are classpath:log4j.properties or - * classpath:log4j.xml for log4j; classpath:logback.xml for - * logback; and classpath:logging.properties for - * java.util.logging. If the correct one of those files is not found then - * some sensible defaults are adopted from files of the same name but in the package - * containing {@link LoggingApplicationListener}. + * By default, log output is only written to the console. If a log file is required the + * {@code logging.path} and {@code logging.file} properties can be used. *

* Some system properties may be set as side effects, and these can be useful if the * logging configuration supports placeholders (i.e. log4j or logback): *

* * @author Dave Syer * @author Phillip Webb + * @see LoggingSystem#get(ClassLoader) */ public class LoggingApplicationListener implements SmartApplicationListener { - private static final Map ENVIRONMENT_SYSTEM_PROPERTY_MAPPING; - - public static final String PID_KEY = "PID"; - - public static final String LOG_FILE = "LOG_FILE"; - - static { - ENVIRONMENT_SYSTEM_PROPERTY_MAPPING = new HashMap(); - ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.put("logging.file", "LOG_FILE"); - ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.put("logging.path", "LOG_PATH"); - ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.put(PID_KEY, PID_KEY); - } - private static MultiValueMap LOG_LEVEL_LOGGERS; static { LOG_LEVEL_LOGGERS = new LinkedMultiValueMap(); @@ -96,9 +73,6 @@ public class LoggingApplicationListener implements SmartApplicationListener { LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.hibernate.SQL"); } - private static Class[] EVENT_TYPES = { ApplicationStartedEvent.class, - ApplicationEnvironmentPreparedEvent.class }; - private final Log logger = LogFactory.getLog(getClass()); private int order = Ordered.HIGHEST_PRECEDENCE + 11; @@ -109,12 +83,8 @@ public class LoggingApplicationListener implements SmartApplicationListener { @Override public boolean supportsEventType(Class eventType) { - for (Class type : EVENT_TYPES) { - if (type.isAssignableFrom(eventType)) { - return true; - } - } - return false; + return ApplicationStartedEvent.class.isAssignableFrom(eventType) + || ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType); } @Override @@ -124,39 +94,32 @@ public class LoggingApplicationListener implements SmartApplicationListener { @Override public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof ApplicationEnvironmentPreparedEvent) { - ApplicationEnvironmentPreparedEvent available = (ApplicationEnvironmentPreparedEvent) event; - initialize(available.getEnvironment(), available.getSpringApplication() - .getClassLoader()); + if (event instanceof ApplicationStartedEvent) { + onApplicationStartedEvent((ApplicationStartedEvent) event); } - else { - if (System.getProperty(PID_KEY) == null) { - System.setProperty(PID_KEY, new ApplicationPid().toString()); - } - LoggingSystem loggingSystem = LoggingSystem.get(ClassUtils.getDefaultClassLoader(), false, false); - loggingSystem.beforeInitialize(); + else if (event instanceof ApplicationEnvironmentPreparedEvent) { + onApplicationPreparedEvent((ApplicationEnvironmentPreparedEvent) event); } } + private void onApplicationStartedEvent(ApplicationStartedEvent event) { + LoggingSystem.get(ClassUtils.getDefaultClassLoader()).beforeInitialize(); + } + + private void onApplicationPreparedEvent(ApplicationEnvironmentPreparedEvent event) { + initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader()); + } + /** * Initialize the logging system according to preferences expressed through the * {@link Environment} and the classpath. */ protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) { + if (System.getProperty("PID") == null) { + System.setProperty("PID", new ApplicationPid().toString()); + } initializeEarlyLoggingLevel(environment); - cleanLogTempProperty(); - boolean fileOutput = !StringUtils.isEmpty(environment.getProperty("logging.file")); - boolean consoleOutput = true; - if (!StringUtils.isEmpty(environment.getProperty("logging.console")) - && environment.getProperty("logging.console").equalsIgnoreCase("false")) { - consoleOutput = false; - } - LoggingSystem system = LoggingSystem.get(classLoader, fileOutput, consoleOutput); - boolean systemEnvironmentChanged = mapSystemPropertiesFromSpring(environment); - if (systemEnvironmentChanged) { - // Re-initialize the defaults in case the system Environment changed - system.beforeInitialize(); - } + LoggingSystem system = LoggingSystem.get(classLoader); initializeSystem(environment, system); initializeFinalLoggingLevels(environment, system); } @@ -172,52 +135,45 @@ public class LoggingApplicationListener implements SmartApplicationListener { } } - private void cleanLogTempProperty() { - // Logback won't read backslashes so add a clean path for it to use - if (!StringUtils.hasLength(System.getProperty("LOG_TEMP"))) { - String path = System.getProperty("java.io.tmpdir"); - path = StringUtils.cleanPath(path); - if (path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - System.setProperty("LOG_TEMP", path); - } - } - - private boolean mapSystemPropertiesFromSpring(Environment environment) { - boolean changed = false; - for (Map.Entry mapping : ENVIRONMENT_SYSTEM_PROPERTY_MAPPING - .entrySet()) { - String springName = mapping.getKey(); - String systemName = mapping.getValue(); - if (environment.containsProperty(springName)) { - System.setProperty(systemName, environment.getProperty(springName)); - changed = true; - } - } - return changed; - } - private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system) { - if (environment.containsProperty("logging.config")) { - String value = environment.getProperty("logging.config"); + String logFile = getLogFile(environment); + String logConfig = environment.getProperty("logging.config"); + if (StringUtils.hasLength(logConfig)) { try { - ResourceUtils.getURL(value).openStream().close(); - system.initialize(value); + ResourceUtils.getURL(logConfig).openStream().close(); + system.initialize(logConfig, logFile); } catch (Exception ex) { - this.logger.warn("Logging environment value '" + value + this.logger.warn("Logging environment value '" + logConfig + "' cannot be opened and will be ignored " + "(using default location instead)"); - system.initialize(); + system.initialize(null, logFile); } } else { - system.initialize(); + system.initialize(null, logFile); } } + private String getLogFile(ConfigurableEnvironment environment) { + String file = environment.getProperty("logging.file"); + String path = environment.getProperty("logging.path"); + if (StringUtils.hasLength(path) || StringUtils.hasLength(file)) { + if (!StringUtils.hasLength(file)) { + file = "spring.log"; + } + if (!StringUtils.hasLength(path) && !file.contains("/")) { + path = StringUtils.cleanPath(System.getProperty("java.io.tmpdir")); + } + if (StringUtils.hasLength(path)) { + return StringUtils.applyRelativePath(path, file); + } + return file; + } + return null; + } + private void initializeFinalLoggingLevels(ConfigurableEnvironment environment, LoggingSystem system) { if (this.springBootLogging != null) { @@ -226,7 +182,16 @@ public class LoggingApplicationListener implements SmartApplicationListener { setLogLevels(system, environment); } - public void setLogLevels(LoggingSystem system, Environment environment) { + protected void initializeLogLevel(LoggingSystem system, LogLevel level) { + List loggers = LOG_LEVEL_LOGGERS.get(level); + if (loggers != null) { + for (String logger : loggers) { + system.setLogLevel(logger, level); + } + } + } + + protected void setLogLevels(LoggingSystem system, Environment environment) { Map levels = new RelaxedPropertyResolver(environment) .getSubProperties("logging.level."); for (Entry entry : levels.entrySet()) { @@ -248,15 +213,6 @@ public class LoggingApplicationListener implements SmartApplicationListener { } } - protected void initializeLogLevel(LoggingSystem system, LogLevel level) { - List loggers = LOG_LEVEL_LOGGERS.get(level); - if (loggers != null) { - for (String logger : loggers) { - system.setLogLevel(logger, level); - } - } - } - public void setOrder(int order) { this.order = order; } diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystem.java index 168b0460d5..38099c1a83 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystem.java @@ -33,35 +33,32 @@ public abstract class LoggingSystem { private static final Map SYSTEMS; static { Map systems = new LinkedHashMap(); - String pkg = LoggingSystem.class.getPackage().getName(); - systems.put("ch.qos.logback.core.Appender", pkg + ".logback.LogbackLoggingSystem"); - systems.put("org.apache.log4j.PropertyConfigurator", pkg - + ".log4j.Log4JLoggingSystem"); - systems.put("org.apache.logging.log4j.LogManager", pkg - + ".log4j2.Log4J2LoggingSystem"); - systems.put("java.util.logging.LogManager", pkg + ".java.JavaLoggingSystem"); + systems.put("ch.qos.logback.core.Appender", + "org.springframework.boot.logging.logback.LogbackLoggingSystem"); + systems.put("org.apache.log4j.PropertyConfigurator", + "org.springframework.boot.logging.log4j.Log4JLoggingSystem"); + systems.put("org.apache.logging.log4j.LogManager", + "org.springframework.boot.logging.log4j2.Log4J2LoggingSystem"); + systems.put("java.util.logging.LogManager", + "org.springframework.boot.logging.java.JavaLoggingSystem"); SYSTEMS = Collections.unmodifiableMap(systems); } /** * Reset the logging system to be limit output. This method may be called before - * {@link #initialize()} to reduce logging noise until the systems has been full - * Initialized. + * {@link #initialize(String, String)} to reduce logging noise until the systems has + * been fully Initialized. */ public abstract void beforeInitialize(); /** - * Initialize the logging system using sensible defaults. This method should generally - * try to find system specific configuration on classpath before falling back to - * sensible defaults. + * Fully initialize the logging system. + * @param configLocation a log configuration location or {@code null} if default + * initialization is required + * @param logFile the log output file that should be written or {@code null} for + * console only output */ - public abstract void initialize(); - - /** - * Initialize the logging system from a logging configuration location. - * @param configLocation a log configuration location - */ - public abstract void initialize(String configLocation); + public abstract void initialize(String configLocation, String logFile); /** * Sets the logging level for a given logger. @@ -71,17 +68,18 @@ public abstract class LoggingSystem { public abstract void setLogLevel(String loggerName, LogLevel level); /** - * Detect and return the logging system in use. + * Detect and return the logging system in use. Supports Logback, Log4J, Log4J2 and + * Java Logging. * @return The logging system */ - public static LoggingSystem get(ClassLoader classLoader, boolean fileOutput, boolean consoleOutput) { + public static LoggingSystem get(ClassLoader classLoader) { for (Map.Entry entry : SYSTEMS.entrySet()) { if (ClassUtils.isPresent(entry.getKey(), classLoader)) { try { Class systemClass = ClassUtils.forName(entry.getValue(), classLoader); - return (LoggingSystem) systemClass.getConstructor(ClassLoader.class, boolean.class, boolean.class) - .newInstance(classLoader, fileOutput, consoleOutput); + return (LoggingSystem) systemClass.getConstructor(ClassLoader.class) + .newInstance(classLoader); } catch (Exception ex) { throw new IllegalStateException(ex); diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java index 254b94b209..d3f4545371 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java @@ -27,16 +27,17 @@ import org.springframework.util.ClassUtils; */ public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem { - public Slf4JLoggingSystem(ClassLoader classLoader, boolean fileOutput, boolean consoleOutput) { - super(classLoader, fileOutput, consoleOutput); + private static final String BRIDGE_HANDLER = "org.slf4j.bridge.SLF4JBridgeHandler"; + + public Slf4JLoggingSystem(ClassLoader classLoader) { + super(classLoader); } @Override public void beforeInitialize() { super.beforeInitialize(); try { - if (ClassUtils.isPresent("org.slf4j.bridge.SLF4JBridgeHandler", - getClassLoader())) { + if (ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader())) { try { SLF4JBridgeHandler.removeHandlersForRootLogger(); } diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java index edb36db470..51cd358cd7 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java @@ -16,6 +16,8 @@ package org.springframework.boot.logging.java; +import java.io.ByteArrayInputStream; +import java.io.InputStreamReader; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -27,8 +29,9 @@ import org.springframework.boot.logging.AbstractLoggingSystem; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; import org.springframework.util.Assert; +import org.springframework.util.FileCopyUtils; import org.springframework.util.ResourceUtils; -import org.springframework.util.SystemPropertyUtils; +import org.springframework.util.StringUtils; /** * {@link LoggingSystem} for {@link Logger java.util.logging}. @@ -52,30 +55,46 @@ public class JavaLoggingSystem extends AbstractLoggingSystem { } public JavaLoggingSystem(ClassLoader classLoader) { - this(classLoader, false, true); - } - - public JavaLoggingSystem(ClassLoader classLoader, boolean fileOutput, - boolean consoleOutput) { - super(classLoader, fileOutput, consoleOutput); + super(classLoader); } @Override - protected String[] getLogFileNames() { + protected String[] getStandardConfigLocations() { return new String[] { "logging.properties" }; } @Override - public void initialize(String configLocation) { - Assert.notNull(configLocation, "ConfigLocation must not be null"); - String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(configLocation); + public void beforeInitialize() { + super.beforeInitialize(); + Logger.getLogger("").setLevel(Level.SEVERE); + } + + @Override + protected void loadDefaults(String logFile) { + if (StringUtils.hasLength(logFile)) { + loadConfiguration(getPackagedConfigFile("logging-file.properties"), logFile); + } + else { + loadConfiguration(getPackagedConfigFile("logging.properties"), logFile); + } + } + + @Override + protected void loadConfiguration(String location, String logFile) { + Assert.notNull(location, "Location must not be null"); try { + String configuration = FileCopyUtils.copyToString(new InputStreamReader( + ResourceUtils.getURL(location).openStream())); + if (StringUtils.hasLength(logFile)) { + configuration = configuration.replace("${LOG_FILE}", + StringUtils.cleanPath(logFile)); + } LogManager.getLogManager().readConfiguration( - ResourceUtils.getURL(resolvedLocation).openStream()); + new ByteArrayInputStream(configuration.getBytes())); } catch (Exception ex) { - throw new IllegalStateException("Could not initialize logging from " - + configLocation, ex); + throw new IllegalStateException("Could not initialize Java logging from " + + location, ex); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java index 43a76ed820..9b234188c8 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java @@ -52,28 +52,42 @@ public class Log4JLoggingSystem extends Slf4JLoggingSystem { } public Log4JLoggingSystem(ClassLoader classLoader) { - this(classLoader, false, true); - } - - public Log4JLoggingSystem(ClassLoader classLoader, boolean fileOutput, - boolean consoleOutput) { - super(classLoader, fileOutput, consoleOutput); + super(classLoader); } @Override - protected String[] getLogFileNames() { + protected String[] getStandardConfigLocations() { return new String[] { "log4j.xml", "log4j.properties" }; } @Override - public void initialize(String configLocation) { - Assert.notNull(configLocation, "ConfigLocation must not be null"); + public void beforeInitialize() { + super.beforeInitialize(); + LogManager.getRootLogger().setLevel(Level.FATAL); + } + + @Override + protected void loadDefaults(String logFile) { + if (StringUtils.hasLength(logFile)) { + loadConfiguration(getPackagedConfigFile("log4j-file.properties"), logFile); + } + else { + loadConfiguration(getPackagedConfigFile("log4j.properties"), logFile); + } + } + + @Override + protected void loadConfiguration(String location, String logFile) { + Assert.notNull(location, "Location must not be null"); + if (StringUtils.hasLength(logFile)) { + System.setProperty("LOG_FILE", logFile); + } try { - Log4jConfigurer.initLogging(configLocation); + Log4jConfigurer.initLogging(location); } catch (Exception ex) { - throw new IllegalStateException("Could not initialize logging from " - + configLocation, ex); + throw new IllegalStateException("Could not initialize Log4J logging from " + + location, ex); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java index 8142f8f8cf..aee678ec09 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java @@ -24,7 +24,6 @@ import java.util.Map; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.springframework.boot.logging.LogLevel; @@ -32,7 +31,7 @@ import org.springframework.boot.logging.LoggingSystem; import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.util.Assert; import org.springframework.util.ResourceUtils; -import org.springframework.util.SystemPropertyUtils; +import org.springframework.util.StringUtils; /** * {@link LoggingSystem} for Log4j 2. @@ -57,44 +56,53 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem { } public Log4J2LoggingSystem(ClassLoader classLoader) { - this(classLoader, false, true); + super(classLoader); } - - public Log4J2LoggingSystem(ClassLoader classLoader, boolean fileOutput, boolean consoleOutput) { - super(classLoader, fileOutput, consoleOutput); - } - + @Override - protected String[] getLogFileNames() { + protected String[] getStandardConfigLocations() { return new String[] { "log4j2.json", "log4j2.jsn", "log4j2.xml" }; } @Override - public void initialize(String configLocation) { - Assert.notNull(configLocation, "ConfigLocation must not be null"); - String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(configLocation); - try { - initializeAndStart(resolvedLocation); + public void beforeInitialize() { + super.beforeInitialize(); + setLogLevel("", LogLevel.FATAL); + } + + @Override + protected void loadDefaults(String logFile) { + if (StringUtils.hasLength(logFile)) { + loadConfiguration(getPackagedConfigFile("log4j2-file.xml"), logFile); } - catch (Exception ex) { - throw new IllegalStateException("Could not initialize logging from " - + configLocation, ex); + else { + loadConfiguration(getPackagedConfigFile("log4j2.xml"), logFile); } } - private void initializeAndStart(String resolvedLocation) throws Exception { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - URL url = ResourceUtils.getURL(resolvedLocation); - ConfigurationSource configSource = new ConfigurationSource(url.openStream(), url); - Configuration config = ConfigurationFactory.getInstance().getConfiguration( - configSource); - ctx.start(config); + @Override + protected void loadConfiguration(String location, String logFile) { + Assert.notNull(location, "Location must not be null"); + if (StringUtils.hasLength(logFile)) { + System.setProperty("LOG_FILE", logFile); + } + try { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + URL url = ResourceUtils.getURL(location); + ConfigurationSource source = new ConfigurationSource(url.openStream(), url); + ctx.start(ConfigurationFactory.getInstance().getConfiguration(source)); + } + catch (Exception ex) { + throw new IllegalStateException("Could not initialize Log4J2 logging from " + + location, ex); + } } @Override public void setLogLevel(String loggerName, LogLevel level) { LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - ctx.getConfiguration().getLoggerConfig(loggerName).setLevel(LEVELS.get(level)); + ctx.getConfiguration().getLoggerConfig(loggerName == null ? "" : loggerName) + .setLevel(LEVELS.get(level)); ctx.updateLoggers(); } diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java index a0daefef40..fc48dec557 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java @@ -23,6 +23,7 @@ import java.util.Map; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; +import org.slf4j.Marker; import org.slf4j.impl.StaticLoggerBinder; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; @@ -30,11 +31,12 @@ import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.util.Assert; import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; -import org.springframework.util.SystemPropertyUtils; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.turbo.TurboFilter; import ch.qos.logback.classic.util.ContextInitializer; +import ch.qos.logback.core.spi.FilterReply; /** * {@link LoggingSystem} for for logback. @@ -58,25 +60,54 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem { LEVELS = Collections.unmodifiableMap(levels); } + private static final TurboFilter FILTER = new TurboFilter() { + + @Override + public FilterReply decide(Marker marker, ch.qos.logback.classic.Logger logger, + Level level, String format, Object[] params, Throwable t) { + return FilterReply.DENY; + } + + }; + public LogbackLoggingSystem(ClassLoader classLoader) { - this(classLoader, false, true); - } - - public LogbackLoggingSystem(ClassLoader classLoader, boolean fileOutput, - boolean consoleOutput) { - super(classLoader, fileOutput, consoleOutput); + super(classLoader); } @Override - protected String[] getLogFileNames() { + protected String[] getStandardConfigLocations() { return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml" }; } @Override - public void initialize(String configLocation) { - Assert.notNull(configLocation, "ConfigLocation must not be null"); - String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(configLocation); + public void beforeInitialize() { + super.beforeInitialize(); + getLogger(null).getLoggerContext().getTurboFilterList().add(FILTER); + } + + @Override + public void initialize(String configLocation, String logFile) { + getLogger(null).getLoggerContext().getTurboFilterList().remove(FILTER); + super.initialize(configLocation, logFile); + } + + @Override + protected void loadDefaults(String logFile) { + if (StringUtils.hasLength(logFile)) { + loadConfiguration(getPackagedConfigFile("logback-file.xml"), logFile); + } + else { + loadConfiguration(getPackagedConfigFile("logback.xml"), logFile); + } + } + + @Override + protected void loadConfiguration(String location, String logFile) { + Assert.notNull(location, "Location must not be null"); + if (StringUtils.hasLength(logFile)) { + System.setProperty("LOG_FILE", logFile); + } ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory(); Assert.isInstanceOf( LoggerContext.class, @@ -92,22 +123,25 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem { context.stop(); context.reset(); try { - URL url = ResourceUtils.getURL(resolvedLocation); + URL url = ResourceUtils.getURL(location); new ContextInitializer(context).configureByResource(url); } catch (Exception ex) { - throw new IllegalStateException("Could not initialize logging from " - + configLocation, ex); + throw new IllegalStateException("Could not initialize Logback logging from " + + location, ex); } } @Override public void setLogLevel(String loggerName, LogLevel level) { + getLogger(loggerName).setLevel(LEVELS.get(level)); + } + + private ch.qos.logback.classic.Logger getLogger(String name) { ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory(); - Logger logger = factory - .getLogger(StringUtils.isEmpty(loggerName) ? Logger.ROOT_LOGGER_NAME - : loggerName); - ((ch.qos.logback.classic.Logger) logger).setLevel(LEVELS.get(level)); + return (ch.qos.logback.classic.Logger) factory.getLogger(StringUtils + .isEmpty(name) ? Logger.ROOT_LOGGER_NAME : name); + } } diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/java/basic-logging.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/java/basic-logging.properties deleted file mode 100644 index 73c81a46ed..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/java/basic-logging.properties +++ /dev/null @@ -1,13 +0,0 @@ -handlers = java.util.logging.ConsoleHandler -.level = INFO - -java.util.logging.ConsoleHandler.formatter = org.springframework.boot.logging.java.SimpleFormatter -java.util.logging.ConsoleHandler.level = ALL - -org.hibernate.validator.internal.util.Version.level = WARNING -org.apache.coyote.http11.Http11NioProtocol.level = WARNING -org.crsh.plugin.level = WARNING -org.apache.tomcat.util.net.NioSelectorPool.level = WARNING -org.apache.catalina.startup.DigesterFactory.level = SEVERE -org.apache.catalina.util.LifecycleBase.level = SEVERE -org.eclipse.jetty.util.component.AbstractLifeCycle.level = SEVERE diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file-console.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file-console.properties deleted file mode 100644 index 0316feebab..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file-console.properties +++ /dev/null @@ -1,20 +0,0 @@ -handlers =java.util.logging.FileHandler,java.util.logging.ConsoleHandler -.level = INFO - -# File Logging -java.util.logging.FileHandler.pattern = %t/spring.log -java.util.logging.FileHandler.formatter = org.springframework.boot.logging.java.SimpleFormatter -java.util.logging.FileHandler.level = ALL -java.util.logging.FileHandler.limit = 10485760 -java.util.logging.FileHandler.count = 10 - -java.util.logging.ConsoleHandler.formatter = org.springframework.boot.logging.java.SimpleFormatter -java.util.logging.ConsoleHandler.level = ALL - -org.hibernate.validator.internal.util.Version.level = WARNING -org.apache.coyote.http11.Http11NioProtocol.level = WARNING -org.crsh.plugin.level = WARNING -org.apache.tomcat.util.net.NioSelectorPool.level = WARNING -org.apache.catalina.startup.DigesterFactory.level = SEVERE -org.apache.catalina.util.LifecycleBase.level = SEVERE -org.eclipse.jetty.util.component.AbstractLifeCycle.level = SEVERE diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file.properties index 314d49eaf3..f37a4a153d 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file.properties +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-file.properties @@ -1,13 +1,16 @@ -handlers =java.util.logging.FileHandler +handlers =java.util.logging.FileHandler,java.util.logging.ConsoleHandler .level = INFO # File Logging -java.util.logging.FileHandler.pattern = %t/spring.log +java.util.logging.FileHandler.pattern = ${LOG_FILE} java.util.logging.FileHandler.formatter = org.springframework.boot.logging.java.SimpleFormatter java.util.logging.FileHandler.level = ALL java.util.logging.FileHandler.limit = 10485760 java.util.logging.FileHandler.count = 10 +java.util.logging.ConsoleHandler.formatter = org.springframework.boot.logging.java.SimpleFormatter +java.util.logging.ConsoleHandler.level = ALL + org.hibernate.validator.internal.util.Version.level = WARNING org.apache.coyote.http11.Http11NioProtocol.level = WARNING org.crsh.plugin.level = WARNING diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-none.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-none.properties deleted file mode 100644 index fa027f53ab..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/java/logging-none.properties +++ /dev/null @@ -1,10 +0,0 @@ -handlers = -.level = INFO - -org.hibernate.validator.internal.util.Version.level = WARNING -org.apache.coyote.http11.Http11NioProtocol.level = WARNING -org.crsh.plugin.level = WARNING -org.apache.tomcat.util.net.NioSelectorPool.level = WARNING -org.apache.catalina.startup.DigesterFactory.level = SEVERE -org.apache.catalina.util.LifecycleBase.level = SEVERE -org.eclipse.jetty.util.component.AbstractLifeCycle.level = SEVERE diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/basic-log4j.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/basic-log4j.properties deleted file mode 100644 index 28b637638f..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/basic-log4j.properties +++ /dev/null @@ -1,17 +0,0 @@ -log4j.rootCategory=INFO, CONSOLE - -PID=???? -LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} %5p [%t] --- %c{1}: %m%n - -# CONSOLE is set to be a ConsoleAppender using a PatternLayout. -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -log4j.appender.CONSOLE.layout.ConversionPattern=${LOG_PATTERN} - -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN -log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR -log4j.category.org.apache.catalina.util.LifecycleBase=ERROR -log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file-console.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file-console.properties deleted file mode 100644 index 58baefaced..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file-console.properties +++ /dev/null @@ -1,25 +0,0 @@ -log4j.rootCategory=INFO, CONSOLE, FILE - -PID=???? -LOG_PATH=${java.io.tmpdir} -LOG_FILE=${LOG_PATH}/spring.log -LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} %5p [%t] --- %c{1}: %m%n - -# CONSOLE is set to be a ConsoleAppender using a PatternLayout. -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -log4j.appender.CONSOLE.layout.ConversionPattern=${LOG_PATTERN} - -log4j.appender.FILE=org.apache.log4j.RollingFileAppender -log4j.appender.FILE.File=${LOG_FILE} -log4j.appender.FILE.MaxFileSize=10MB -log4j.appender.FILE.layout = org.apache.log4j.PatternLayout -log4j.appender.FILE.layout.ConversionPattern=${LOG_PATTERN} - -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN -log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR -log4j.category.org.apache.catalina.util.LifecycleBase=ERROR -log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file.properties index 949ec6de23..ca1f0ec327 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file.properties +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-file.properties @@ -1,20 +1,31 @@ -log4j.rootCategory=INFO,FILE +log4j.rootCategory=INFO, CONSOLE, FILE PID=???? LOG_PATH=${java.io.tmpdir} LOG_FILE=${LOG_PATH}/spring.log LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} %5p [%t] --- %c{1}: %m%n +# CONSOLE is set to be a ConsoleAppender using a PatternLayout. +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=${LOG_PATTERN} + log4j.appender.FILE=org.apache.log4j.RollingFileAppender log4j.appender.FILE.File=${LOG_FILE} log4j.appender.FILE.MaxFileSize=10MB log4j.appender.FILE.layout = org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern=${LOG_PATTERN} -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR log4j.category.org.apache.catalina.util.LifecycleBase=ERROR +log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN +log4j.category.org.apache.sshd.common.util.SecurityUtils +log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN +log4j.category.org.crsh.plugin=WARN +log4j.category.org.crsh.ssh=WARN log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR +log4j.category.org.hibernate.validator.internal.util.Version=WARN +log4j.category.org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration=WARN +log4j.category.org.springframework.boot.actuate.endpoint.jmx=WARN +log4j.category.org.thymeleaf=WARN + diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-none.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-none.properties deleted file mode 100644 index f8a630ca8d..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j-none.properties +++ /dev/null @@ -1,15 +0,0 @@ -log4j.rootCategory=INFO - -PID=???? -LOG_PATH=${java.io.tmpdir} -LOG_FILE=${LOG_PATH}/spring.log -LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} %5p [%t] --- %c{1}: %m%n - - -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN -log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR -log4j.category.org.apache.catalina.util.LifecycleBase=ERROR -log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j.properties b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j.properties index e0885761df..4b4d9f291e 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j.properties +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j/log4j.properties @@ -1,8 +1,6 @@ log4j.rootCategory=INFO, CONSOLE PID=???? -LOG_PATH=${java.io.tmpdir} -LOG_FILE=${LOG_PATH}/spring.log LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} %5p [%t] --- %c{1}: %m%n # CONSOLE is set to be a ConsoleAppender using a PatternLayout. @@ -10,11 +8,15 @@ log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=${LOG_PATTERN} - -log4j.category.org.hibernate.validator.internal.util.Version=WARN -log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN -log4j.category.org.crsh.plugin=WARN -log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN log4j.category.org.apache.catalina.startup.DigesterFactory=ERROR log4j.category.org.apache.catalina.util.LifecycleBase=ERROR +log4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN +log4j.category.org.apache.sshd.common.util.SecurityUtils +log4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN +log4j.category.org.crsh.plugin=WARN +log4j.category.org.crsh.ssh=WARN log4j.category.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR +log4j.category.org.hibernate.validator.internal.util.Version=WARN +log4j.category.org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration=WARN +log4j.category.org.springframework.boot.actuate.endpoint.jmx=WARN +log4j.category.org.thymeleaf=WARN diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/basic-log4j2.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/basic-log4j2.xml deleted file mode 100644 index d8e113eac3..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/basic-log4j2.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - ???? - [%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n - - - - - - - - - - - - - - - - - - - - diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file-console.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file-console.xml deleted file mode 100644 index e2f1bb78a7..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file-console.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - ???? - /tmp - ${sys:LOG_PATH}/spring.log - [%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n - - - - - - - - ${LOG_PATTERN} - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file.xml index b1bc0235c0..9171b146c2 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file.xml +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-file.xml @@ -1,33 +1,38 @@ - - ???? - /tmp - ${sys:LOG_PATH}/spring.log - [%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n - - - - - ${LOG_PATTERN} - - - - - - - - - - - - - - - - - - - + + ???? + [%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n + + + + + + + + ${LOG_PATTERN} + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-none.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-none.xml deleted file mode 100644 index eed5a2c784..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2-none.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - ???? - /tmp - ${sys:LOG_PATH}/spring.log - [%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n - - - - - - - - - - - - - - diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2.xml index 2374d828ef..45e09bc402 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2.xml +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/log4j2/log4j2.xml @@ -1,27 +1,29 @@ - - ???? - /tmp - ${sys:LOG_PATH}/spring.log - [%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n - - - - - - - - - - - - - - - - - - - + + ???? + [%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/base.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/base.xml index dc572d9583..71d33621a6 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/base.xml +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/base.xml @@ -2,16 +2,28 @@ - + - - - ${CONSOLE_LOG_PATTERN} - utf8 - + + + + org.springframework.boot - - - - + + + + + + + + + + + + + + + + + diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/basic-logback.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/basic-logback.xml deleted file mode 100644 index a5c5515b84..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/basic-logback.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/console-appender.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/console-appender.xml new file mode 100644 index 0000000000..a08abd194d --- /dev/null +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/console-appender.xml @@ -0,0 +1,9 @@ + + + + + ${CONSOLE_LOG_PATTERN} + utf8 + + + diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/base-file.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/file-appender.xml similarity index 55% rename from spring-boot/src/main/resources/org/springframework/boot/logging/logback/base-file.xml rename to spring-boot/src/main/resources/org/springframework/boot/logging/logback/file-appender.xml index a7ed15fc0d..f6dd783564 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/base-file.xml +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/file-appender.xml @@ -1,8 +1,5 @@ - - - @@ -17,7 +14,4 @@ 10MB - - - diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file-console.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file-console.xml deleted file mode 100644 index 38e7fe99c4..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file-console.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file.xml index 6d0ccd3537..0d5c8a3c42 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file.xml +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-file.xml @@ -1,4 +1,12 @@ - + + + + + + + + + diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-none.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-none.xml deleted file mode 100644 index eb91e909b9..0000000000 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback-none.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback.xml b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback.xml index b8a41480d7..5b372d2331 100644 --- a/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback.xml +++ b/spring-boot/src/main/resources/org/springframework/boot/logging/logback/logback.xml @@ -1,4 +1,8 @@ + + + + diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/AbstractLoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/AbstractLoggingSystemTests.java new file mode 100644 index 0000000000..81457f7c26 --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/logging/AbstractLoggingSystemTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2014 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 java.io.File; + +import org.junit.After; +import org.junit.Before; +import org.springframework.util.StringUtils; + +/** + * Base for {@link LoggingSystem} tests. + * + * @author Phillip Webb + */ +public abstract class AbstractLoggingSystemTests { + + @Before + public void deleteTempLog() { + new File(tmpDir() + "/spring.log").delete(); + } + + @After + public void clear() { + System.clearProperty("LOG_FILE"); + System.clearProperty("PID"); + } + + protected final String tmpDir() { + String path = StringUtils.cleanPath(System.getProperty("java.io.tmpdir")); + if (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + return path; + } + +} diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java index a0d9de3ae0..077cd1dab1 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java @@ -106,17 +106,6 @@ public class LoggingApplicationListenerTests { assertFalse(new File(tmpDir() + "/spring.log").exists()); } - @Test - public void noConsole() { - EnvironmentTestUtils.addEnvironment(this.context, "logging.console: false"); - this.initializer.initialize(this.context.getEnvironment(), - this.context.getClassLoader()); - this.logger.info("Hello world"); - String output = this.outputCapture.toString().trim(); - assertFalse("Wrong output:\n" + output, output.contains("Hello world")); - assertFalse(new File(tmpDir() + "/spring.log").exists()); - } - @Test public void overrideConfigLocation() { EnvironmentTestUtils.addEnvironment(this.context, @@ -127,7 +116,8 @@ public class LoggingApplicationListenerTests { String output = this.outputCapture.toString().trim(); assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertFalse("Wrong output:\n" + output, output.contains("???")); - assertTrue("Wrong output:\n" + output, output.startsWith(tmpDir() + "/tmp.log")); + assertTrue("Wrong output:\n" + output, output.startsWith("LOG_FILE_IS_UNDEFINED")); + assertTrue("Wrong output:\n" + output, output.endsWith("BOOTBOOT")); } @Test @@ -178,7 +168,7 @@ public class LoggingApplicationListenerTests { Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class); logger.info("Hello world"); String output = this.outputCapture.toString().trim(); - assertTrue("Wrong output:\n" + output, output.startsWith("target/foo/tmp.log")); + assertTrue("Wrong output:\n" + output, output.startsWith("target/foo/spring.log")); } @Test diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/java/JavaLoggerSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/java/JavaLoggerSystemTests.java index 8c3f9ff617..5645112bd3 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/java/JavaLoggerSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/java/JavaLoggerSystemTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.logging.java; +import java.io.File; +import java.io.FileFilter; import java.io.IOException; import java.util.Locale; @@ -24,12 +26,15 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.springframework.boot.logging.AbstractLoggingSystemTests; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.test.OutputCapture; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -37,8 +42,18 @@ import static org.junit.Assert.assertTrue; * Tests for {@link JavaLoggingSystem}. * * @author Dave Syer + * @author Phillip Webb */ -public class JavaLoggerSystemTests { +public class JavaLoggerSystemTests extends AbstractLoggingSystemTests { + + private static final FileFilter SPRING_LOG_FILTER = new FileFilter() { + + @Override + public boolean accept(File pathname) { + return pathname.getName().startsWith("spring.log"); + } + + }; private final JavaLoggingSystem loggingSystem = new JavaLoggingSystem(getClass() .getClassLoader()); @@ -58,17 +73,43 @@ public class JavaLoggerSystemTests { } @After - public void clear() { - System.clearProperty("LOG_FILE"); - System.clearProperty("LOG_PATH"); - System.clearProperty("PID"); + public void clearLocale() { Locale.setDefault(this.defaultLocale); } + @Test + public void noFile() throws Exception { + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, null); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertFalse(new File(tmpDir() + "/spring.log").exists()); + } + + @Test + public void withFile() throws Exception { + File temp = new File(tmpDir()); + File[] logFiles = temp.listFiles(SPRING_LOG_FILTER); + for (File file : logFiles) { + file.delete(); + } + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, tmpDir() + "/spring.log"); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertThat(temp.listFiles(SPRING_LOG_FILTER).length, greaterThan(0)); + } + @Test public void testCustomFormatter() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); this.logger.info("Hello world"); String output = this.output.toString().trim(); assertTrue("Wrong output:\n" + output, output.contains("Hello world")); @@ -79,9 +120,10 @@ public class JavaLoggerSystemTests { public void testSystemPropertyInitializesFormat() throws Exception { System.setProperty("PID", "1234"); this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:" - + ClassUtils.addResourcePathToPackagePath(getClass(), - "logging.properties")); + this.loggingSystem.initialize( + "classpath:" + + ClassUtils.addResourcePathToPackagePath(getClass(), + "logging.properties"), null); this.logger.info("Hello world"); this.logger.info("Hello world"); String output = this.output.toString().trim(); @@ -92,7 +134,7 @@ public class JavaLoggerSystemTests { @Test public void testNonDefaultConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:logging-nondefault.properties"); + this.loggingSystem.initialize("classpath:logging-nondefault.properties", null); this.logger.info("Hello world"); String output = this.output.toString().trim(); assertTrue("Wrong output:\n" + output, output.contains("INFO: Hello")); @@ -101,19 +143,13 @@ public class JavaLoggerSystemTests { @Test(expected = IllegalStateException.class) public void testNonexistentConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:logging-nonexistent.properties"); - } - - @Test(expected = IllegalArgumentException.class) - public void testNullConfigLocation() throws Exception { - this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(null); + this.loggingSystem.initialize("classpath:logging-nonexistent.properties", null); } @Test public void setLevel() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); this.logger.debug("Hello"); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.logger.debug("Hello"); diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java index b5cebfec9a..f700dd4274 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java @@ -16,17 +16,20 @@ package org.springframework.boot.logging.log4j; +import java.io.File; + import org.apache.commons.logging.impl.Log4JLogger; -import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; +import org.springframework.boot.logging.AbstractLoggingSystemTests; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.test.OutputCapture; import org.springframework.util.StringUtils; import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -35,7 +38,7 @@ import static org.junit.Assert.assertTrue; * * @author Phillip Webb */ -public class Log4JLoggingSystemTests { +public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests { @Rule public OutputCapture output = new OutputCapture(); @@ -50,39 +53,52 @@ public class Log4JLoggingSystemTests { this.logger = new Log4JLogger(getClass().getName()); } - @After - public void clear() { - System.clearProperty("LOG_FILE"); - System.clearProperty("LOG_PATH"); - System.clearProperty("PID"); + @Test + public void noFile() throws Exception { + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, null); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertFalse(new File(tmpDir() + "/spring.log").exists()); + } + + @Test + public void withFile() throws Exception { + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, tmpDir() + "/spring.log"); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertTrue(new File(tmpDir() + "/spring.log").exists()); } @Test public void testNonDefaultConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:log4j-nondefault.properties"); + this.loggingSystem.initialize("classpath:log4j-nondefault.properties", tmpDir() + + "/spring.log"); this.logger.info("Hello world"); String output = this.output.toString().trim(); assertTrue("Wrong output:\n" + output, output.contains("Hello world")); - assertTrue("Wrong output:\n" + output, output.contains("/tmp/spring.log")); + assertTrue("Wrong output:\n" + output, output.contains(tmpDir() + "/spring.log")); + assertFalse(new File(tmpDir() + "/tmp.log").exists()); } @Test(expected = IllegalStateException.class) public void testNonexistentConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:log4j-nonexistent.xml"); - } - - @Test(expected = IllegalArgumentException.class) - public void testNullConfigLocation() throws Exception { - this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(null); + this.loggingSystem.initialize("classpath:log4j-nonexistent.xml", null); } @Test public void setLevel() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); this.logger.debug("Hello"); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.logger.debug("Hello"); @@ -94,7 +110,7 @@ public class Log4JLoggingSystemTests { @Ignore("Fails on Bamboo") public void loggingThatUsesJulIsCaptured() { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); java.util.logging.Logger julLogger = java.util.logging.Logger .getLogger(getClass().getName()); julLogger.severe("Hello world"); diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java index b08aa01143..bf9305b1e9 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java @@ -16,18 +16,21 @@ package org.springframework.boot.logging.log4j2; +import java.io.File; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; +import org.springframework.boot.logging.AbstractLoggingSystemTests; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.test.OutputCapture; import org.springframework.util.StringUtils; import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -35,8 +38,9 @@ import static org.junit.Assert.assertTrue; * Tests for {@link Log4J2LoggingSystem}. * * @author Daniel Fullarton + * @author Phillip Webb */ -public class Log4J2LoggingSystemTests { +public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { @Rule public OutputCapture output = new OutputCapture(); @@ -51,39 +55,52 @@ public class Log4J2LoggingSystemTests { this.logger = LogManager.getLogger(getClass()); } - @After - public void clear() { - System.clearProperty("LOG_FILE"); - System.clearProperty("LOG_PATH"); - System.clearProperty("PID"); + @Test + public void noFile() throws Exception { + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, null); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertFalse(new File(tmpDir() + "/spring.log").exists()); + } + + @Test + public void withFile() throws Exception { + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, tmpDir() + "/spring.log"); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertTrue(new File(tmpDir() + "/spring.log").exists()); } @Test public void testNonDefaultConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:log4j2-nondefault.xml"); + this.loggingSystem.initialize("classpath:log4j2-nondefault.xml", tmpDir() + + "/tmp.log"); this.logger.info("Hello world"); String output = this.output.toString().trim(); assertTrue("Wrong output:\n" + output, output.contains("Hello world")); - assertTrue("Wrong output:\n" + output, output.contains("/tmp/spring.log")); + assertTrue("Wrong output:\n" + output, output.contains(tmpDir() + "/tmp.log")); + assertFalse(new File(tmpDir() + "/tmp.log").exists()); } @Test(expected = IllegalStateException.class) public void testNonexistentConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:log4j2-nonexistent.xml"); - } - - @Test(expected = IllegalArgumentException.class) - public void testNullConfigLocation() throws Exception { - this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(null); + this.loggingSystem.initialize("classpath:log4j2-nonexistent.xml", null); } @Test public void setLevel() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); this.logger.debug("Hello"); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.logger.debug("Hello"); @@ -95,7 +112,7 @@ public class Log4J2LoggingSystemTests { @Ignore("Fails on Bamboo") public void loggingThatUsesJulIsCaptured() { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); java.util.logging.Logger julLogger = java.util.logging.Logger .getLogger(getClass().getName()); julLogger.severe("Hello world"); diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java index e752491c17..e0eb506388 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java @@ -20,12 +20,12 @@ import java.io.File; import org.apache.commons.logging.Log; import org.apache.commons.logging.impl.SLF4JLogFactory; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.slf4j.ILoggerFactory; import org.slf4j.impl.StaticLoggerBinder; +import org.springframework.boot.logging.AbstractLoggingSystemTests; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.test.OutputCapture; import org.springframework.util.StringUtils; @@ -43,8 +43,9 @@ import static org.junit.Assert.assertTrue; * Tests for {@link LogbackLoggingSystem}. * * @author Dave Syer + * @author Phillip Webb */ -public class LogbackLoggingSystemTests { +public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { @Rule public OutputCapture output = new OutputCapture(); @@ -57,22 +58,30 @@ public class LogbackLoggingSystemTests { @Before public void setup() { this.logger = new SLF4JLogFactory().getInstance(getClass().getName()); - new File(tmpDir() + "/spring.log").delete(); } - private String tmpDir() { - String path = StringUtils.cleanPath(System.getProperty("java.io.tmpdir")); - if (path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - return path; + @Test + public void noFile() throws Exception { + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, null); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertFalse(new File(tmpDir() + "/spring.log").exists()); } - @After - public void clear() { - System.clearProperty("LOG_FILE"); - System.clearProperty("LOG_PATH"); - System.clearProperty("PID"); + @Test + public void withFile() throws Exception { + this.loggingSystem.beforeInitialize(); + this.logger.info("Hidden"); + this.loggingSystem.initialize(null, tmpDir() + "/spring.log"); + this.logger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + assertFalse("Output not hidden:\n" + output, output.contains("Hidden")); + assertTrue(new File(tmpDir() + "/spring.log").exists()); } @Test @@ -87,31 +96,26 @@ public class LogbackLoggingSystemTests { @Test public void testNonDefaultConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:logback-nondefault.xml"); + this.loggingSystem.initialize("classpath:logback-nondefault.xml", tmpDir() + + "/tmp.log"); this.logger.info("Hello world"); String output = this.output.toString().trim(); assertTrue("Wrong output:\n" + output, output.contains("Hello world")); - assertTrue("Wrong output (not " + tmpDir() + " :\n" + output, - output.contains(tmpDir() + "/tmp.log")); + assertTrue("Wrong output:\n" + output, output.contains(tmpDir() + "/tmp.log")); + assertTrue("Wrong output:\n" + output, output.endsWith("BOOTBOOT")); assertFalse(new File(tmpDir() + "/tmp.log").exists()); } @Test(expected = IllegalStateException.class) public void testNonexistentConfigLocation() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize("classpath:logback-nonexistent.xml"); - } - - @Test(expected = IllegalArgumentException.class) - public void testNullConfigLocation() throws Exception { - this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(null); + this.loggingSystem.initialize("classpath:logback-nonexistent.xml", null); } @Test public void setLevel() throws Exception { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); this.logger.debug("Hello"); this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG); this.logger.debug("Hello"); @@ -122,7 +126,7 @@ public class LogbackLoggingSystemTests { @Test public void loggingThatUsesJulIsCaptured() { this.loggingSystem.beforeInitialize(); - this.loggingSystem.initialize(); + this.loggingSystem.initialize(null, null); java.util.logging.Logger julLogger = java.util.logging.Logger .getLogger(getClass().getName()); julLogger.info("Hello world"); diff --git a/spring-boot/src/test/resources/log4j-nondefault.properties b/spring-boot/src/test/resources/log4j-nondefault.properties index 544139af91..d852ca65d8 100644 --- a/spring-boot/src/test/resources/log4j-nondefault.properties +++ b/spring-boot/src/test/resources/log4j-nondefault.properties @@ -2,8 +2,6 @@ log4j.reset=true log4j.rootCategory=INFO, CONSOLE PID=???? -LOG_PATH=/tmp -LOG_FILE=${LOG_PATH}/spring.log LOG_PATTERN=${LOG_FILE} %d{yyyy-MM-dd HH:mm:ss.SSS}] service%X{context} - ${PID} %5p [%t] --- %c{1}: %m%n # CONSOLE is set to be a ConsoleAppender using a PatternLayout. diff --git a/spring-boot/src/test/resources/log4j2-nondefault.xml b/spring-boot/src/test/resources/log4j2-nondefault.xml index 53bf99dd3c..9ab4cd276b 100644 --- a/spring-boot/src/test/resources/log4j2-nondefault.xml +++ b/spring-boot/src/test/resources/log4j2-nondefault.xml @@ -1,19 +1,17 @@ - - ???? - /tmp - ${sys:LOG_PATH}/spring.log - ${sys:LOG_FILE} %d{yyyy-MM-dd HH:mm:ss.SSS}] service%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n - - - - - - - - - - - - \ No newline at end of file + + ???? + ${sys:LOG_FILE} %d{yyyy-MM-dd HH:mm:ss.SSS}] service%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n + + + + + + + + + + + + diff --git a/spring-boot/src/test/resources/logback-nondefault.xml b/spring-boot/src/test/resources/logback-nondefault.xml index 5044712267..4224068672 100644 --- a/spring-boot/src/test/resources/logback-nondefault.xml +++ b/spring-boot/src/test/resources/logback-nondefault.xml @@ -1,9 +1,8 @@ - - ${LOG_FILE} [%t] ${PID:-????} %c{1}: %m%n + ${LOG_FILE} [%t] ${PID:-????} %c{1}: %m%n BOOTBOOT