Include the application name on each log line when it is available

Update Logback and Log4J2 so that they include the application name on
each log line. If `spring.application.name` had not been set, or if
`logging.include-application-name` is `false` then the name is not
logged.

Closes gh-35593
pull/36032/head
Phillip Webb 1 year ago
parent c1b295fd71
commit 493777d3c9

@ -293,7 +293,7 @@ task runSpringApplicationExample(type: org.springframework.boot.build.docs.Appli
task runLoggingFormatExample(type: org.springframework.boot.build.docs.ApplicationRunner) { task runLoggingFormatExample(type: org.springframework.boot.build.docs.ApplicationRunner) {
classpath = configurations.springApplicationExample + sourceSets.main.output classpath = configurations.springApplicationExample + sourceSets.main.output
mainClass = "org.springframework.boot.docs.features.springapplication.MyApplication" mainClass = "org.springframework.boot.docs.features.springapplication.MyApplication"
args = ["--spring.main.banner-mode=off", "--server.port=0"] args = ["--spring.main.banner-mode=off", "--server.port=0", "--spring.application.name=myapp"]
output = file("$buildDir/example-output/logging-format.txt") output = file("$buildDir/example-output/logging-format.txt")
expectedLogging = "Started MyApplication in " expectedLogging = "Started MyApplication in "
normalizeTomcatPort() normalizeTomcatPort()

@ -31,6 +31,7 @@ The following items are output:
* Log Level: `ERROR`, `WARN`, `INFO`, `DEBUG`, or `TRACE`. * Log Level: `ERROR`, `WARN`, `INFO`, `DEBUG`, or `TRACE`.
* Process ID. * Process ID.
* A `---` separator to distinguish the start of actual log messages. * A `---` separator to distinguish the start of actual log messages.
* Application name: Enclosed in square brackets (logged by default only if configprop:spring.application.name[] is set)
* Thread name: Enclosed in square brackets (may be truncated for console output). * Thread name: Enclosed in square brackets (may be truncated for console output).
* Correlation ID: If tracing is enabled (not shown in the sample above) * Correlation ID: If tracing is enabled (not shown in the sample above)
* Logger name: This is usually the source class name (often abbreviated). * Logger name: This is usually the source class name (often abbreviated).
@ -39,6 +40,7 @@ The following items are output:
NOTE: Logback does not have a `FATAL` level. NOTE: Logback does not have a `FATAL` level.
It is mapped to `ERROR`. It is mapped to `ERROR`.
TIP: If you have a configprop:spring.application.name[] property but don't want it logged you can set configprop:logging.include-application-name[] to `false`.
[[features.logging.console-output]] [[features.logging.console-output]]

@ -27,6 +27,7 @@ import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver; import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.PropertySourcesPropertyResolver; import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/** /**
* Utility to set system properties that can later be used by log configuration files. * Utility to set system properties that can later be used by log configuration files.
@ -227,6 +228,7 @@ public class LoggingSystemProperties {
protected void apply(LogFile logFile, PropertyResolver resolver) { protected void apply(LogFile logFile, PropertyResolver resolver) {
String defaultCharsetName = getDefaultCharset().name(); String defaultCharsetName = getDefaultCharset().name();
setApplicationNameSystemProperty(resolver);
setSystemProperty(LoggingSystemProperty.PID, new ApplicationPid().toString()); setSystemProperty(LoggingSystemProperty.PID, new ApplicationPid().toString());
setSystemProperty(LoggingSystemProperty.CONSOLE_CHARSET, resolver, defaultCharsetName); setSystemProperty(LoggingSystemProperty.CONSOLE_CHARSET, resolver, defaultCharsetName);
setSystemProperty(LoggingSystemProperty.FILE_CHARSET, resolver, defaultCharsetName); setSystemProperty(LoggingSystemProperty.FILE_CHARSET, resolver, defaultCharsetName);
@ -243,6 +245,16 @@ public class LoggingSystemProperties {
} }
} }
private void setApplicationNameSystemProperty(PropertyResolver resolver) {
if (resolver.getProperty("logging.include-application-name", Boolean.class, Boolean.TRUE)) {
String applicationName = resolver.getProperty("spring.application.name");
if (StringUtils.hasText(applicationName)) {
setSystemProperty(LoggingSystemProperty.APPLICATION_NAME.getEnvironmentVariableName(),
"[%s] ".formatted(applicationName));
}
}
}
private void setSystemProperty(LoggingSystemProperty property, PropertyResolver resolver) { private void setSystemProperty(LoggingSystemProperty property, PropertyResolver resolver) {
setSystemProperty(property, resolver, null); setSystemProperty(property, resolver, null);
} }

@ -25,6 +25,11 @@ package org.springframework.boot.logging;
*/ */
public enum LoggingSystemProperty { public enum LoggingSystemProperty {
/**
* Logging system property for the application name that should be logged.
*/
APPLICATION_NAME("LOGGED_APPLICATION_NAME"),
/** /**
* Logging system property for the process ID. * Logging system property for the process ID.
*/ */

@ -75,7 +75,7 @@ class DefaultLogbackConfiguration {
config.getContext() config.getContext()
.putProperty("CONSOLE_LOG_PATTERN", resolve(config, "${CONSOLE_LOG_PATTERN:-" .putProperty("CONSOLE_LOG_PATTERN", resolve(config, "${CONSOLE_LOG_PATTERN:-"
+ "%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) " + "%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) "
+ "%clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} " + "%clr(${PID:- }){magenta} %clr(---){faint} %clr(${LOGGED_APPLICATION_NAME:-}[%15.15t]){faint} "
+ "%clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}){cyan} " + "%clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}){cyan} "
+ "%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}")); + "%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"));
String defaultCharset = Charset.defaultCharset().name(); String defaultCharset = Charset.defaultCharset().name();
@ -84,7 +84,7 @@ class DefaultLogbackConfiguration {
config.getContext().putProperty("CONSOLE_LOG_THRESHOLD", resolve(config, "${CONSOLE_LOG_THRESHOLD:-TRACE}")); config.getContext().putProperty("CONSOLE_LOG_THRESHOLD", resolve(config, "${CONSOLE_LOG_THRESHOLD:-TRACE}"));
config.getContext() config.getContext()
.putProperty("FILE_LOG_PATTERN", resolve(config, "${FILE_LOG_PATTERN:-" .putProperty("FILE_LOG_PATTERN", resolve(config, "${FILE_LOG_PATTERN:-"
+ "%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] " + "%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- ${LOGGED_APPLICATION_NAME:-}[%t] "
+ "${LOG_CORRELATION_PATTERN:-}" + "${LOG_CORRELATION_PATTERN:-}"
+ "%-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}")); + "%-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"));
config.getContext() config.getContext()

@ -103,6 +103,13 @@
"description": "Log groups to quickly change multiple loggers at the same time. For instance, `logging.group.db=org.hibernate,org.springframework.jdbc`.", "description": "Log groups to quickly change multiple loggers at the same time. For instance, `logging.group.db=org.hibernate,org.springframework.jdbc`.",
"sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener" "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener"
}, },
{
"name": "logging.include-application-name",
"type": "java.lang.String>",
"description": "Whether to include the application name in the logs.",
"sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
"defaultValue": true
},
{ {
"name": "logging.level", "name": "logging.level",
"type": "java.util.Map<java.lang.String,java.lang.String>", "type": "java.util.Map<java.lang.String,java.lang.String>",

@ -4,8 +4,8 @@
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property> <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property> <Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd'T'HH:mm:ss.SSSXXX</Property> <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd'T'HH:mm:ss.SSSXXX</Property>
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${sys:LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${sys:LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{${sys:LOG_CORRELATION_PATTERN:-}}{faint}%clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> <Property name="CONSOLE_LOG_PATTERN">%clr{%d{${sys:LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${sys:LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{${sys:LOGGED_APPLICATION_NAME:-}[%15.15t]}{faint} %clr{${sys:LOG_CORRELATION_PATTERN:-}}{faint}%clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<Property name="FILE_LOG_PATTERN">%d{${sys:LOG_DATEFORMAT_PATTERN}} ${sys:LOG_LEVEL_PATTERN} %pid --- [%t] ${sys:LOG_CORRELATION_PATTERN:-}%-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> <Property name="FILE_LOG_PATTERN">%d{${sys:LOG_DATEFORMAT_PATTERN}} ${sys:LOG_LEVEL_PATTERN} %pid --- ${sys:LOGGED_APPLICATION_NAME}[%t] ${sys:LOG_CORRELATION_PATTERN:-}%-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties> </Properties>
<Appenders> <Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true"> <Console name="Console" target="SYSTEM_OUT" follow="true">

@ -4,8 +4,8 @@
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property> <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property> <Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd'T'HH:mm:ss.SSSXXX</Property> <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd'T'HH:mm:ss.SSSXXX</Property>
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${sys:LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${sys:LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{${sys:LOG_CORRELATION_PATTERN:-}}{faint}%clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> <Property name="CONSOLE_LOG_PATTERN">%clr{%d{${sys:LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${sys:LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{${sys:LOGGED_APPLICATION_NAME}[%15.15t]}{faint} %clr{${sys:LOG_CORRELATION_PATTERN:-}}{faint}%clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<Property name="FILE_LOG_PATTERN">%d{${sys:LOG_DATEFORMAT_PATTERN}} ${sys:LOG_LEVEL_PATTERN} %pid --- [%t] ${sys:LOG_CORRELATION_PATTERN:-}%-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> <Property name="FILE_LOG_PATTERN">%d{${sys:LOG_DATEFORMAT_PATTERN}} ${sys:LOG_LEVEL_PATTERN} %pid --- ${sys:LOGGED_APPLICATION_NAME}[%t] ${sys:LOG_CORRELATION_PATTERN:-}%-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties> </Properties>
<Appenders> <Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true"> <Console name="Console" target="SYSTEM_OUT" follow="true">

@ -10,10 +10,10 @@ Default logback configuration provided for import
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr(${LOGGED_APPLICATION_NAME:-}[%15.15t]){faint} %clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="CONSOLE_LOG_CHARSET" value="${CONSOLE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/> <property name="CONSOLE_LOG_CHARSET" value="${CONSOLE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/>
<property name="CONSOLE_LOG_THRESHOLD" value="${CONSOLE_LOG_THRESHOLD:-TRACE}"/> <property name="CONSOLE_LOG_THRESHOLD" value="${CONSOLE_LOG_THRESHOLD:-TRACE}"/>
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] ${LOG_CORRELATION_PATTERN:-}%-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- ${LOGGED_APPLICATION_NAME:-}[%t] ${LOG_CORRELATION_PATTERN:-}%-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="FILE_LOG_CHARSET" value="${FILE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/> <property name="FILE_LOG_CHARSET" value="${FILE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/>
<property name="FILE_LOG_THRESHOLD" value="${FILE_LOG_THRESHOLD:-TRACE}"/> <property name="FILE_LOG_THRESHOLD" value="${FILE_LOG_THRESHOLD:-TRACE}"/>

@ -136,6 +136,25 @@ class LoggingSystemPropertiesTests {
.isEqualTo("default correlation pattern"); .isEqualTo("default correlation pattern");
} }
@Test
void loggedApplicationNameWhenHasApplicationName() {
new LoggingSystemProperties(new MockEnvironment().withProperty("spring.application.name", "test")).apply(null);
assertThat(getSystemProperty(LoggingSystemProperty.APPLICATION_NAME)).isEqualTo("[test] ");
}
@Test
void loggedApplicationNameWhenHasNoApplicationName() {
new LoggingSystemProperties(new MockEnvironment()).apply(null);
assertThat(getSystemProperty(LoggingSystemProperty.APPLICATION_NAME)).isNull();
}
@Test
void loggedApplicationNameWhenApplicationNameLoggingDisabled() {
new LoggingSystemProperties(new MockEnvironment().withProperty("spring.application.name", "test")
.withProperty("logging.include-application-name", "false")).apply(null);
assertThat(getSystemProperty(LoggingSystemProperty.APPLICATION_NAME)).isNull();
}
private Environment environment(String key, Object value) { private Environment environment(String key, Object value) {
StandardEnvironment environment = new StandardEnvironment(); StandardEnvironment environment = new StandardEnvironment();
environment.getPropertySources().addLast(new MapPropertySource("test", Collections.singletonMap(key, value))); environment.getPropertySources().addLast(new MapPropertySource("test", Collections.singletonMap(key, value)));

@ -564,6 +564,27 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
.contains(" [0123456789012345-01234567890123456789012345678901] "); .contains(" [0123456789012345-01234567890123456789012345678901] ");
} }
@Test
void applicationNameLoggingWhenHasApplicationName(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp");
this.loggingSystem.setStandardConfigLocations(false);
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(this.initializationContext, null, null);
this.logger.info("Hello world");
assertThat(getLineWithText(output, "Hello world")).contains("[myapp] ");
}
@Test
void applicationNameLoggingWhenDisabled(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp");
this.environment.setProperty("logging.include-application-name", "false");
this.loggingSystem.setStandardConfigLocations(false);
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(this.initializationContext, null, null);
this.logger.info("Hello world");
assertThat(getLineWithText(output, "Hello world")).doesNotContain("myapp");
}
private String getRelativeClasspathLocation(String fileName) { private String getRelativeClasspathLocation(String fileName) {
String defaultPath = ClassUtils.getPackageName(getClass()); String defaultPath = ClassUtils.getPackageName(getClass());
defaultPath = defaultPath.replace('.', '/'); defaultPath = defaultPath.replace('.', '/');

@ -754,6 +754,23 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
.contains(" [01234567890123456789012345678901-0123456789012345] "); .contains(" [01234567890123456789012345678901-0123456789012345] ");
} }
@Test
void applicationNameLoggingWhenHasApplicationName(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp");
initialize(this.initializationContext, null, null);
this.logger.info("Hello world");
assertThat(getLineWithText(output, "Hello world")).contains("[myapp] ");
}
@Test
void applicationNameLoggingWhenDisabled(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp");
this.environment.setProperty("logging.include-application-name", "false");
initialize(this.initializationContext, null, null);
this.logger.info("Hello world");
assertThat(getLineWithText(output, "Hello world")).doesNotContain("myapp");
}
private void initialize(LoggingInitializationContext context, String configLocation, LogFile logFile) { private void initialize(LoggingInitializationContext context, String configLocation, LogFile logFile) {
this.loggingSystem.getSystemProperties((ConfigurableEnvironment) context.getEnvironment()).apply(logFile); this.loggingSystem.getSystemProperties((ConfigurableEnvironment) context.getEnvironment()).apply(logFile);
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();

@ -1,3 +1,4 @@
spring.application.name=sample
spring.security.user.name=user spring.security.user.name=user
spring.security.user.password=password spring.security.user.password=password
management.endpoint.shutdown.enabled=true management.endpoint.shutdown.enabled=true

@ -2,7 +2,7 @@
<Configuration status="WARN" monitorInterval="30"> <Configuration status="WARN" monitorInterval="30">
<Properties> <Properties>
<Property name="PID">????</Property> <Property name="PID">????</Property>
<Property name="LOG_PATTERN">%clr{%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx</Property> <Property name="LOG_PATTERN">%clr{%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{${sys:LOGGED_APPLICATION_NAME:-}[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx</Property>
</Properties> </Properties>
<Appenders> <Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true"> <Console name="Console" target="SYSTEM_OUT" follow="true">

@ -1,3 +1,4 @@
spring.application.name=sample
service.name=Phil service.name=Phil
spring.security.user.name=user spring.security.user.name=user

Loading…
Cancel
Save