Merge pull request #3405 from rob-baily/logback-pattern-properties

* pr/3405:
  Support log pattern properties with logback
pull/3363/merge
Phillip Webb 9 years ago
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…
Cancel
Save