Merge branch '3.2.x'

Closes gh-39802
This commit is contained in:
Andy Wilkinson 2024-02-29 15:55:33 +00:00
commit 83f9e45491
6 changed files with 230 additions and 17 deletions

View File

@ -0,0 +1,50 @@
/*
* Copyright 2012-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.logging.logback;
import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.pattern.PropertyConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.springframework.boot.logging.LoggingSystemProperty;
/**
* Logback {@link ClassicConverter} to convert the
* {@link LoggingSystemProperty#APPLICATION_NAME APPLICATION_NAME} into a value suitable
* for logging. Similar to Logback's {@link PropertyConverter} but a non-existent property
* is logged as an empty string rather than {@code null}.
*
* @author Andy Wilkinson
* @since 3.2.4
*/
public class ApplicationNameConverter extends ClassicConverter {
@Override
public String convert(ILoggingEvent event) {
String applicationName = event.getLoggerContextVO()
.getPropertyMap()
.get(LoggingSystemProperty.APPLICATION_NAME.getEnvironmentVariableName());
if (applicationName == null) {
applicationName = System.getProperty(LoggingSystemProperty.APPLICATION_NAME.getEnvironmentVariableName());
if (applicationName == null) {
applicationName = "";
}
}
return applicationName;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@ -68,6 +68,7 @@ class DefaultLogbackConfiguration {
}
private void defaults(LogbackConfigurator config) {
config.conversionRule("applicationName", ApplicationNameConverter.class);
config.conversionRule("clr", ColorConverter.class);
config.conversionRule("correlationId", CorrelationIdConverter.class);
config.conversionRule("wex", WhitespaceThrowableProxyConverter.class);
@ -75,7 +76,7 @@ class DefaultLogbackConfiguration {
config.getContext()
.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(${PID:- }){magenta} %clr(---){faint} %clr(${LOGGED_APPLICATION_NAME:-}[%15.15t]){faint} "
+ "%clr(${PID:- }){magenta} %clr(---){faint} %clr(%applicationName[%15.15t]){faint} "
+ "%clr(${LOG_CORRELATION_PATTERN:-}){faint}%clr(%-40.40logger{39}){cyan} "
+ "%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"));
String defaultCharset = Charset.defaultCharset().name();
@ -84,7 +85,7 @@ class DefaultLogbackConfiguration {
config.getContext().putProperty("CONSOLE_LOG_THRESHOLD", resolve(config, "${CONSOLE_LOG_THRESHOLD:-TRACE}"));
config.getContext()
.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:- } --- ${LOGGED_APPLICATION_NAME:-}[%t] "
+ "%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- %applicationName[%t] "
+ "${LOG_CORRELATION_PATTERN:-}"
+ "%-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"));
config.getContext()

View File

@ -5,15 +5,16 @@ Default logback configuration provided for import
-->
<included>
<conversionRule conversionWord="applicationName" converterClass="org.springframework.boot.logging.logback.ApplicationNameConverter" />
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="correlationId" converterClass="org.springframework.boot.logging.logback.CorrelationIdConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<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(${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_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(%applicationName[%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_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:- } --- ${LOGGED_APPLICATION_NAME:-}[%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:- } --- %applicationName[%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_THRESHOLD" value="${FILE_LOG_THRESHOLD:-TRACE}"/>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@ -565,7 +565,7 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
}
@Test
void applicationNameLoggingWhenHasApplicationName(CapturedOutput output) {
void applicationNameLoggingToConsoleWhenHasApplicationName(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp");
this.loggingSystem.setStandardConfigLocations(false);
this.loggingSystem.beforeInitialize();
@ -575,25 +575,66 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
}
@Test
void applicationNamePlaceHolderNotShowingWhenDisabled(CapturedOutput output) {
void applicationNameLoggingToConsoleWhenHasApplicationNameWithParenthesis(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp (dev)");
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 (dev)] ");
}
@Test
void applicationNameLoggingToConsoleWhenDisabled(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "application-name");
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("${sys:LOGGED_APPLICATION_NAME}");
assertThat(getLineWithText(output, "Hello world")).doesNotContain("${sys:LOGGED_APPLICATION_NAME}")
.doesNotContain("myapp");
}
@Test
void applicationNameLoggingWhenDisabled(CapturedOutput output) {
void applicationNameLoggingToFileWhenHasApplicationName() {
this.environment.setProperty("spring.application.name", "myapp");
this.environment.setProperty("logging.include-application-name", "false");
new LoggingSystemProperties(this.environment).apply();
File file = new File(tmpDir(), "log4j2-test.log");
LogFile logFile = getLogFile(file.getPath(), null);
this.loggingSystem.setStandardConfigLocations(false);
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(this.initializationContext, null, null);
this.loggingSystem.initialize(this.initializationContext, null, logFile);
this.logger.info("Hello world");
assertThat(getLineWithText(output, "Hello world")).doesNotContain("myapp");
assertThat(getLineWithText(file, "Hello world")).contains("[myapp] ");
}
@Test
void applicationNameLoggingToFileWhenHasApplicationNameWithParenthesis() {
this.environment.setProperty("spring.application.name", "myapp (dev)");
new LoggingSystemProperties(this.environment).apply();
File file = new File(tmpDir(), "log4j2-test.log");
LogFile logFile = getLogFile(file.getPath(), null);
this.loggingSystem.setStandardConfigLocations(false);
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(this.initializationContext, null, logFile);
this.logger.info("Hello world");
assertThat(getLineWithText(file, "Hello world")).contains("[myapp (dev)] ");
}
@Test
void applicationNameLoggingToFileWhenDisabled() {
this.environment.setProperty("spring.application.name", "application-name");
this.environment.setProperty("logging.include-application-name", "false");
new LoggingSystemProperties(this.environment).apply();
File file = new File(tmpDir(), "log4j2-test.log");
LogFile logFile = getLogFile(file.getPath(), null);
this.loggingSystem.setStandardConfigLocations(false);
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(this.initializationContext, null, logFile);
this.logger.info("Hello world");
assertThat(getLineWithText(file, "Hello world")).doesNotContain("${sys:LOGGED_APPLICATION_NAME}")
.doesNotContain("myapp");
}
private String getRelativeClasspathLocation(String fileName) {

View File

@ -0,0 +1,81 @@
/*
* Copyright 2012-2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.logging.logback;
import java.util.Collections;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggerContextVO;
import ch.qos.logback.classic.spi.LoggingEvent;
import org.junit.jupiter.api.Test;
import org.springframework.boot.logging.LoggingSystemProperty;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ApplicationNameConverter}.
*
* @author Andy Wilkinson
*/
class ApplicationNameConverterTests {
private final ApplicationNameConverter converter;
private final LoggingEvent event = new LoggingEvent();
ApplicationNameConverterTests() {
this.converter = new ApplicationNameConverter();
this.converter.setContext(new LoggerContext());
this.event.setLoggerContextRemoteView(
new LoggerContextVO("test", Collections.emptyMap(), System.currentTimeMillis()));
}
@Test
void whenNoLoggedApplicationNameConvertReturnsEmptyString() {
withLoggedApplicationName(null, () -> {
this.converter.start();
String converted = this.converter.convert(this.event);
assertThat(converted).isEqualTo("");
});
}
@Test
void whenLoggedApplicationNameConvertReturnsIt() {
withLoggedApplicationName("my-application", () -> {
this.converter.start();
String converted = this.converter.convert(this.event);
assertThat(converted).isEqualTo("my-application");
});
}
private void withLoggedApplicationName(String name, Runnable action) {
if (name == null) {
System.clearProperty(LoggingSystemProperty.APPLICATION_NAME.getEnvironmentVariableName());
}
else {
System.setProperty(LoggingSystemProperty.APPLICATION_NAME.getEnvironmentVariableName(), name);
}
try {
action.run();
}
finally {
System.clearProperty(LoggingSystemProperty.APPLICATION_NAME.getEnvironmentVariableName());
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@ -761,7 +761,7 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
}
@Test
void applicationNameLoggingWhenHasApplicationName(CapturedOutput output) {
void applicationNameLoggingToConsoleWhenHasApplicationName(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp");
initialize(this.initializationContext, null, null);
this.logger.info("Hello world");
@ -769,12 +769,51 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
}
@Test
void applicationNameLoggingWhenDisabled(CapturedOutput output) {
void applicationNameLoggingToConsoleWhenHasApplicationNameWithParenthesis(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp (dev)");
initialize(this.initializationContext, null, null);
this.logger.info("Hello world");
assertThat(getLineWithText(output, "Hello world")).contains("[myapp (dev)] ");
}
@Test
void applicationNameLoggingToConsoleWhenDisabled(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");
assertThat(getLineWithText(output, "Hello world")).doesNotContain("myapp").doesNotContain("null");
}
@Test
void applicationNameLoggingToFileWhenHasApplicationName() {
this.environment.setProperty("spring.application.name", "myapp");
File file = new File(tmpDir(), "logback-test.log");
LogFile logFile = getLogFile(file.getPath(), null);
initialize(this.initializationContext, null, logFile);
this.logger.info("Hello world");
assertThat(getLineWithText(file, "Hello world")).contains("[myapp] ");
}
@Test
void applicationNameLoggingToFileWhenHasApplicationNameWithParenthesis() {
this.environment.setProperty("spring.application.name", "myapp (dev)");
File file = new File(tmpDir(), "logback-test.log");
LogFile logFile = getLogFile(file.getPath(), null);
initialize(this.initializationContext, null, logFile);
this.logger.info("Hello world");
assertThat(getLineWithText(file, "Hello world")).contains("[myapp (dev)] ");
}
@Test
void applicationNameLoggingToFileWhenDisabled(CapturedOutput output) {
this.environment.setProperty("spring.application.name", "myapp");
this.environment.setProperty("logging.include-application-name", "false");
File file = new File(tmpDir(), "logback-test.log");
LogFile logFile = getLogFile(file.getPath(), null);
initialize(this.initializationContext, null, logFile);
this.logger.info("Hello world");
assertThat(getLineWithText(file, "Hello world")).doesNotContain("myapp").doesNotContain("null");
}
@Test