Support log pattern properties with logback
Update AbstractLoggingSystem to pass LoggingInitializationContext to loadDefaults() method to enable access to the environment. DefaultLogbackConfiguration now uses this to find log pattern overrides. Fixes gh-3367 Closes gh-3405
This commit is contained in:
@@ -57,6 +57,8 @@ content into your application; rather pick only the properties that you need.
|
||||
logging.file=myapp.log
|
||||
logging.config= # location of config file (default classpath:logback.xml for logback)
|
||||
logging.level.*= # levels for loggers, e.g. "logging.level.org.springframework=DEBUG" (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)
|
||||
logging.pattern.console= # appender pattern for output to the console (only supported with the default logback setup)
|
||||
logging.pattern.file= # appender pattern for output to the file (only supported with the default logback setup)
|
||||
|
||||
# IDENTITY ({sc-spring-boot}/context/ContextIdApplicationContextInitializer.{sc-ext}[ContextIdApplicationContextInitializer])
|
||||
spring.application.name=
|
||||
|
||||
@@ -71,7 +71,7 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
|
||||
loadConfiguration(initializationContext, config, logFile);
|
||||
return;
|
||||
}
|
||||
loadDefaults(logFile);
|
||||
loadDefaults(initializationContext, logFile);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,9 +129,11 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
|
||||
|
||||
/**
|
||||
* Load sensible defaults for the logging system.
|
||||
* @param initializationContext the logging initialization context
|
||||
* @param logFile the file to load or {@code null} if no log file is to be written
|
||||
*/
|
||||
protected abstract void loadDefaults(LogFile logFile);
|
||||
protected abstract void loadDefaults(
|
||||
LoggingInitializationContext initializationContext, LogFile logFile);
|
||||
|
||||
/**
|
||||
* Load a specific configuration.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* 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.
|
||||
@@ -72,7 +72,8 @@ public class JavaLoggingSystem extends AbstractLoggingSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadDefaults(LogFile logFile) {
|
||||
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||
LogFile logFile) {
|
||||
if (logFile != null) {
|
||||
loadConfiguration(getPackagedConfigFile("logging-file.properties"), logFile);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ public class Log4JLoggingSystem extends Slf4JLoggingSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadDefaults(LogFile logFile) {
|
||||
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||
LogFile logFile) {
|
||||
if (logFile != null) {
|
||||
loadConfiguration(getPackagedConfigFile("log4j-file.properties"), logFile);
|
||||
}
|
||||
|
||||
@@ -136,7 +136,8 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadDefaults(LogFile logFile) {
|
||||
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||
LogFile logFile) {
|
||||
if (logFile != null) {
|
||||
loadConfiguration(getPackagedConfigFile("log4j2-file.xml"), logFile);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,7 +18,12 @@ package org.springframework.boot.logging.logback;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertyResolver;
|
||||
import org.springframework.core.env.PropertySourcesPropertyResolver;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||
@@ -50,12 +55,23 @@ class DefaultLogbackConfiguration {
|
||||
|
||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
private final PropertyResolver patterns;
|
||||
|
||||
private final LogFile logFile;
|
||||
|
||||
public DefaultLogbackConfiguration(LogFile logFile) {
|
||||
public DefaultLogbackConfiguration(
|
||||
LoggingInitializationContext initializationContext, LogFile logFile) {
|
||||
this.patterns = getPatternsResolver(initializationContext.getEnvironment());
|
||||
this.logFile = logFile;
|
||||
}
|
||||
|
||||
private PropertyResolver getPatternsResolver(Environment environment) {
|
||||
if (environment == null) {
|
||||
return new PropertySourcesPropertyResolver(null);
|
||||
}
|
||||
return new RelaxedPropertyResolver(environment, "logging.pattern.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void apply(LogbackConfigurator config) {
|
||||
synchronized (config.getConfigurationLock()) {
|
||||
@@ -99,8 +115,8 @@ class DefaultLogbackConfiguration {
|
||||
private Appender<ILoggingEvent> consoleAppender(LogbackConfigurator config) {
|
||||
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
|
||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||
encoder.setPattern(OptionHelper.substVars(CONSOLE_LOG_PATTERN,
|
||||
config.getContext()));
|
||||
String logPattern = this.patterns.getProperty("console", CONSOLE_LOG_PATTERN);
|
||||
encoder.setPattern(OptionHelper.substVars(logPattern, config.getContext()));
|
||||
encoder.setCharset(UTF8);
|
||||
config.start(encoder);
|
||||
appender.setEncoder(encoder);
|
||||
@@ -112,7 +128,8 @@ class DefaultLogbackConfiguration {
|
||||
String logFile) {
|
||||
RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<ILoggingEvent>();
|
||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||
encoder.setPattern(OptionHelper.substVars(FILE_LOG_PATTERN, config.getContext()));
|
||||
String logPattern = this.patterns.getProperty("file", FILE_LOG_PATTERN);
|
||||
encoder.setPattern(OptionHelper.substVars(logPattern, config.getContext()));
|
||||
appender.setEncoder(encoder);
|
||||
config.start(encoder);
|
||||
|
||||
|
||||
@@ -103,12 +103,14 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadDefaults(LogFile logFile) {
|
||||
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||
LogFile logFile) {
|
||||
LoggerContext context = getLoggerContext();
|
||||
context.stop();
|
||||
context.reset();
|
||||
LogbackConfigurator configurator = new LogbackConfigurator(context);
|
||||
new DefaultLogbackConfiguration(logFile).apply(configurator);
|
||||
new DefaultLogbackConfiguration(initializationContext, logFile)
|
||||
.apply(configurator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -210,4 +212,5 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||
}
|
||||
return "unknown location";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.logging.logback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogManager;
|
||||
|
||||
@@ -30,10 +31,12 @@ import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.bridge.SLF4JBridgeHandler;
|
||||
import org.slf4j.impl.StaticLoggerBinder;
|
||||
import org.springframework.boot.logging.AbstractLoggingSystemTests;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.boot.test.OutputCapture;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
@@ -87,6 +90,8 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
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("Wrong output pattern:\n" + output,
|
||||
getLineWithText(output, "Hello world").contains("INFO"));
|
||||
assertFalse(new File(tmpDir() + "/spring.log").exists());
|
||||
}
|
||||
|
||||
@@ -98,9 +103,14 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
getLogFile(null, tmpDir()));
|
||||
this.logger.info("Hello world");
|
||||
String output = this.output.toString().trim();
|
||||
File file = new File(tmpDir() + "/spring.log");
|
||||
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());
|
||||
assertTrue("Wrong console output pattern:\n" + output,
|
||||
getLineWithText(output, "Hello world").contains("INFO"));
|
||||
assertTrue(file.exists());
|
||||
assertTrue("Wrong file output pattern:\n" + output,
|
||||
getLineWithText(file, "Hello world").contains("INFO"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -197,4 +207,49 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsolePatternProperty() {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("logging.pattern.console", "%logger %msg");
|
||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(
|
||||
environment);
|
||||
this.loggingSystem.initialize(loggingInitializationContext, null, null);
|
||||
this.logger.info("Hello world");
|
||||
String output = this.output.toString().trim();
|
||||
assertFalse("Wrong output pattern:\n" + output,
|
||||
getLineWithText(output, "Hello world").contains("INFO"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilePatternProperty() throws Exception {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("logging.pattern.file", "%logger %msg");
|
||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(
|
||||
environment);
|
||||
File file = new File(tmpDir(), "logback-test.log");
|
||||
LogFile logFile = getLogFile(file.getPath(), null);
|
||||
this.loggingSystem.initialize(loggingInitializationContext, null, logFile);
|
||||
this.logger.info("Hello world");
|
||||
String output = this.output.toString().trim();
|
||||
assertTrue("Wrong console output pattern:\n" + output,
|
||||
getLineWithText(output, "Hello world").contains("INFO"));
|
||||
assertFalse("Wrong file output pattern:\n" + output,
|
||||
getLineWithText(file, "Hello world").contains("INFO"));
|
||||
}
|
||||
|
||||
private String getLineWithText(File file, String outputSearch) throws Exception {
|
||||
return getLineWithText(FileCopyUtils.copyToString(new FileReader(file)),
|
||||
outputSearch);
|
||||
}
|
||||
|
||||
private String getLineWithText(String output, String outputSearch) {
|
||||
String[] lines = output.split("\\r?\\n");
|
||||
for (String line : lines) {
|
||||
if (line.contains(outputSearch)) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user