Merge pull request #3405 from rob-baily/logback-pattern-properties
* pr/3405: Support log pattern properties with logback
This commit is contained in:
commit
5e243b28db
|
|
@ -57,6 +57,8 @@ content into your application; rather pick only the properties that you need.
|
||||||
logging.file=myapp.log
|
logging.file=myapp.log
|
||||||
logging.config= # location of config file (default classpath:logback.xml for logback)
|
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.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])
|
# IDENTITY ({sc-spring-boot}/context/ContextIdApplicationContextInitializer.{sc-ext}[ContextIdApplicationContextInitializer])
|
||||||
spring.application.name=
|
spring.application.name=
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
|
||||||
loadConfiguration(initializationContext, config, logFile);
|
loadConfiguration(initializationContext, config, logFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadDefaults(logFile);
|
loadDefaults(initializationContext, logFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -129,9 +129,11 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load sensible defaults for the logging system.
|
* 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
|
* @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.
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -72,7 +72,8 @@ public class JavaLoggingSystem extends AbstractLoggingSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadDefaults(LogFile logFile) {
|
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||||
|
LogFile logFile) {
|
||||||
if (logFile != null) {
|
if (logFile != null) {
|
||||||
loadConfiguration(getPackagedConfigFile("logging-file.properties"), logFile);
|
loadConfiguration(getPackagedConfigFile("logging-file.properties"), logFile);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,8 @@ public class Log4JLoggingSystem extends Slf4JLoggingSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadDefaults(LogFile logFile) {
|
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||||
|
LogFile logFile) {
|
||||||
if (logFile != null) {
|
if (logFile != null) {
|
||||||
loadConfiguration(getPackagedConfigFile("log4j-file.properties"), logFile);
|
loadConfiguration(getPackagedConfigFile("log4j-file.properties"), logFile);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,8 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadDefaults(LogFile logFile) {
|
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||||
|
LogFile logFile) {
|
||||||
if (logFile != null) {
|
if (logFile != null) {
|
||||||
loadConfiguration(getPackagedConfigFile("log4j2-file.xml"), logFile);
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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 java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||||
import org.springframework.boot.logging.LogFile;
|
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.Level;
|
||||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||||
|
|
@ -50,12 +55,23 @@ class DefaultLogbackConfiguration {
|
||||||
|
|
||||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
private final PropertyResolver patterns;
|
||||||
|
|
||||||
private final LogFile logFile;
|
private final LogFile logFile;
|
||||||
|
|
||||||
public DefaultLogbackConfiguration(LogFile logFile) {
|
public DefaultLogbackConfiguration(
|
||||||
|
LoggingInitializationContext initializationContext, LogFile logFile) {
|
||||||
|
this.patterns = getPatternsResolver(initializationContext.getEnvironment());
|
||||||
this.logFile = logFile;
|
this.logFile = logFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PropertyResolver getPatternsResolver(Environment environment) {
|
||||||
|
if (environment == null) {
|
||||||
|
return new PropertySourcesPropertyResolver(null);
|
||||||
|
}
|
||||||
|
return new RelaxedPropertyResolver(environment, "logging.pattern.");
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void apply(LogbackConfigurator config) {
|
public void apply(LogbackConfigurator config) {
|
||||||
synchronized (config.getConfigurationLock()) {
|
synchronized (config.getConfigurationLock()) {
|
||||||
|
|
@ -99,8 +115,8 @@ class DefaultLogbackConfiguration {
|
||||||
private Appender<ILoggingEvent> consoleAppender(LogbackConfigurator config) {
|
private Appender<ILoggingEvent> consoleAppender(LogbackConfigurator config) {
|
||||||
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
|
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
|
||||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||||
encoder.setPattern(OptionHelper.substVars(CONSOLE_LOG_PATTERN,
|
String logPattern = this.patterns.getProperty("console", CONSOLE_LOG_PATTERN);
|
||||||
config.getContext()));
|
encoder.setPattern(OptionHelper.substVars(logPattern, config.getContext()));
|
||||||
encoder.setCharset(UTF8);
|
encoder.setCharset(UTF8);
|
||||||
config.start(encoder);
|
config.start(encoder);
|
||||||
appender.setEncoder(encoder);
|
appender.setEncoder(encoder);
|
||||||
|
|
@ -112,7 +128,8 @@ class DefaultLogbackConfiguration {
|
||||||
String logFile) {
|
String logFile) {
|
||||||
RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<ILoggingEvent>();
|
RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<ILoggingEvent>();
|
||||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
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);
|
appender.setEncoder(encoder);
|
||||||
config.start(encoder);
|
config.start(encoder);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,12 +103,14 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadDefaults(LogFile logFile) {
|
protected void loadDefaults(LoggingInitializationContext initializationContext,
|
||||||
|
LogFile logFile) {
|
||||||
LoggerContext context = getLoggerContext();
|
LoggerContext context = getLoggerContext();
|
||||||
context.stop();
|
context.stop();
|
||||||
context.reset();
|
context.reset();
|
||||||
LogbackConfigurator configurator = new LogbackConfigurator(context);
|
LogbackConfigurator configurator = new LogbackConfigurator(context);
|
||||||
new DefaultLogbackConfiguration(logFile).apply(configurator);
|
new DefaultLogbackConfiguration(initializationContext, logFile)
|
||||||
|
.apply(configurator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -210,4 +212,5 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||||
}
|
}
|
||||||
return "unknown location";
|
return "unknown location";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.logging.logback;
|
package org.springframework.boot.logging.logback;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.util.logging.Handler;
|
import java.util.logging.Handler;
|
||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
|
|
||||||
|
|
@ -30,10 +31,12 @@ import org.slf4j.ILoggerFactory;
|
||||||
import org.slf4j.bridge.SLF4JBridgeHandler;
|
import org.slf4j.bridge.SLF4JBridgeHandler;
|
||||||
import org.slf4j.impl.StaticLoggerBinder;
|
import org.slf4j.impl.StaticLoggerBinder;
|
||||||
import org.springframework.boot.logging.AbstractLoggingSystemTests;
|
import org.springframework.boot.logging.AbstractLoggingSystemTests;
|
||||||
|
import org.springframework.boot.logging.LogFile;
|
||||||
import org.springframework.boot.logging.LogLevel;
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||||
import org.springframework.boot.test.OutputCapture;
|
import org.springframework.boot.test.OutputCapture;
|
||||||
import org.springframework.mock.env.MockEnvironment;
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import ch.qos.logback.classic.Logger;
|
import ch.qos.logback.classic.Logger;
|
||||||
|
|
@ -87,6 +90,8 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||||
String output = this.output.toString().trim();
|
String output = this.output.toString().trim();
|
||||||
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
|
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
|
||||||
assertFalse("Output not hidden:\n" + output, output.contains("Hidden"));
|
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());
|
assertFalse(new File(tmpDir() + "/spring.log").exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,9 +103,14 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||||
getLogFile(null, tmpDir()));
|
getLogFile(null, tmpDir()));
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
String output = this.output.toString().trim();
|
String output = this.output.toString().trim();
|
||||||
|
File file = new File(tmpDir() + "/spring.log");
|
||||||
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
|
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
|
||||||
assertFalse("Output not hidden:\n" + output, output.contains("Hidden"));
|
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
|
@Test
|
||||||
|
|
@ -197,4 +207,49 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue