Add support for LOG_LEVEL_PATTERN replacing the default level pattern

For logback we also support logging.pattern.level as a synonym.

Fixes gh-4062
pull/4069/head
Dave Syer 9 years ago
parent eeaa1df1dd
commit cad2666522

@ -63,6 +63,7 @@ content into your application; rather pick only the properties that you need.
logging.path=/var/log
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)
logging.pattern.level= # appender pattern for the log level (default %5p, only supported with the default logback setup)
# IDENTITY ({sc-spring-boot}/context/ContextIdApplicationContextInitializer.{sc-ext}[ContextIdApplicationContextInitializer])
spring.application.name=

@ -1085,6 +1085,18 @@ To help with the customization some other properties are transferred from the Sp
|`LOG_PATH`
|Used in default log configuration if defined.
|`logging.pattern.console`
|`CONSOLE_LOG_PATTERN`
|The log pattern to use on the console (stdout). (Not supported with JDK logger.)
|`logging.pattern.file`
|`FILE_LOG_PATTERN`
|The log pattern to use in a file (if LOG_FILE enabled). (Not supported with JDK logger.)
|`logging.pattern.level`
|`LOG_LEVEL_PATTERN`
|The format to use to render the log level (default `%5p`). (The `logging.pattern.level` form is only supported by Logback.)
|`PID`
|`PID`
|The current process ID (discovered if possible and when not already defined as an OS
@ -1095,6 +1107,20 @@ To help with the customization some other properties are transferred from the Sp
All the logging systems supported can consult System properties when parsing their
configuration files. See the default configurations in `spring-boot.jar` for examples.
[TIP]
====
You can add MDC and other ad-hoc content to log lines by overriding
only the `LOG_LEVEL_PATTERN` (or `logging.pattern.level` with
Logback). For example, if you use `logging.pattern.level=user:%X{user}
%5p` then the default log format will contain an MDC entry for "user"
if it exists, e.g.
----
2015-09-30 12:30:04.031 user:juergen INFO 22174 --- [ nio-8080-exec-0] demo.Controller Handling authenticated request
----
====
[[boot-features-logback-extensions]]

@ -46,12 +46,12 @@ import ch.qos.logback.core.util.OptionHelper;
class DefaultLogbackConfiguration {
private static final String CONSOLE_LOG_PATTERN = "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} "
+ "%clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint} "
+ "%clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} "
+ "%clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} "
+ "%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}";
private static final String FILE_LOG_PATTERN = "%d{yyyy-MM-dd HH:mm:ss.SSS} %5p "
+ "${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}";
private static final String FILE_LOG_PATTERN = "%d{yyyy-MM-dd HH:mm:ss.SSS} "
+ "${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}";
private static final Charset UTF8 = Charset.forName("UTF-8");

@ -57,6 +57,7 @@ import ch.qos.logback.core.status.Status;
public class LogbackLoggingSystem extends Slf4JLoggingSystem {
private static final Map<LogLevel, Level> LEVELS;
static {
Map<LogLevel, Level> levels = new HashMap<LogLevel, Level>();
levels.put(LogLevel.TRACE, Level.TRACE);
@ -85,8 +86,8 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
@Override
protected String[] getStandardConfigLocations() {
return new String[] { "logback-test.groovy", "logback-test.xml",
"logback.groovy", "logback.xml" };
return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy",
"logback.xml" };
}
@Override
@ -109,6 +110,9 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
LoggerContext context = getLoggerContext();
stopAndReset(context);
LogbackConfigurator configurator = new LogbackConfigurator(context);
context.putProperty("LOG_LEVEL_PATTERN",
initializationContext.getEnvironment().resolvePlaceholders(
"${logging.pattern.level:${LOG_LEVEL_PATTERN:%5p}}"));
new DefaultLogbackConfiguration(initializationContext, logFile)
.apply(configurator);
}
@ -127,8 +131,8 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
ResourceUtils.getURL(location));
}
catch (Exception ex) {
throw new IllegalStateException("Could not initialize Logback logging from "
+ location, ex);
throw new IllegalStateException(
"Could not initialize Logback logging from " + location, ex);
}
List<Status> statuses = loggerContext.getStatusManager().getCopyOfStatusList();
StringBuilder errors = new StringBuilder();
@ -139,8 +143,8 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
}
}
if (errors.length() > 0) {
throw new IllegalStateException("Logback configuration error "
+ "detected: \n" + errors);
throw new IllegalStateException(
"Logback configuration error " + "detected: \n" + errors);
}
}
@ -197,20 +201,21 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
private ch.qos.logback.classic.Logger getLogger(String name) {
LoggerContext factory = getLoggerContext();
return factory.getLogger(StringUtils.isEmpty(name) ? Logger.ROOT_LOGGER_NAME
: name);
return factory
.getLogger(StringUtils.isEmpty(name) ? Logger.ROOT_LOGGER_NAME : name);
}
private LoggerContext getLoggerContext() {
ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
Assert.isInstanceOf(LoggerContext.class, factory, String.format(
"LoggerFactory is not a Logback LoggerContext but Logback is on "
+ "the classpath. Either remove Logback or the competing "
+ "implementation (%s loaded from %s). If you are using "
+ "Weblogic you will need to add 'org.slf4j' to "
+ "prefer-application-packages in WEB-INF/weblogic.xml",
factory.getClass(), getLocation(factory)));
Assert.isInstanceOf(LoggerContext.class, factory,
String.format(
"LoggerFactory is not a Logback LoggerContext but Logback is on "
+ "the classpath. Either remove Logback or the competing "
+ "implementation (%s loaded from %s). If you are using "
+ "Weblogic you will need to add 'org.slf4j' to "
+ "prefer-application-packages in WEB-INF/weblogic.xml",
factory.getClass(), getLocation(factory)));
return (LoggerContext) factory;
}

@ -3,7 +3,8 @@ 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
LOG_LEVEL_PATTERN=%5p
LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} ${LOG_LEVEL_PATTERN} [%t] --- %c{1}: %m%n
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

@ -1,7 +1,8 @@
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
LOG_LEVEL_PATTERN=%5p
LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${PID} ${LOG_LEVEL_PATTERN} [%t] --- %c{1}: %m%n
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

@ -3,7 +3,8 @@
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%rEx</Property>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">

@ -3,7 +3,8 @@
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%rEx</Property>
<Property name="LOG_PATTERN">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_PATTERN">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">

@ -9,8 +9,8 @@ initialization performed by Boot
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}"/>
<property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}"/>
<property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}"/>
<property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%rEx}"/>
<appender name="DEBUG_LEVEL_REMAPPER" class="org.springframework.boot.logging.logback.LevelRemappingAppender">
<destinationLogger>org.springframework.boot</destinationLogger>

@ -16,6 +16,16 @@
package org.springframework.boot.logging.logback;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileReader;
import java.util.logging.Handler;
@ -44,16 +54,6 @@ import org.springframework.util.StringUtils;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Tests for {@link LogbackLoggingSystem}.
*
@ -237,6 +237,19 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
getLineWithText(output, "Hello world").contains("INFO"));
}
@Test
public void testLevelPatternProperty() {
MockEnvironment environment = new MockEnvironment();
environment.setProperty("logging.pattern.level", "X%clr(%p)X");
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(
environment);
this.loggingSystem.initialize(loggingInitializationContext, null, null);
this.logger.info("Hello world");
String output = this.output.toString().trim();
assertTrue("Wrong output pattern:\n" + output,
getLineWithText(output, "Hello world").contains("XINFOX"));
}
@Test
public void testFilePatternProperty() throws Exception {
MockEnvironment environment = new MockEnvironment();

Loading…
Cancel
Save