Skip to content

Commit c0aef4c

Browse files
committed
Apply SystemProperties to LoggerContext
Update `LoggingSystemProperties` so that system environment properties are also applied to the `LoggerContext`. This is required when multiple applications are deployed to the same Servlet container. In such setups there's only a single JVM and the System Environment can be changed when multiple applications start at the same time. Fixes gh-24835
1 parent 68fc232 commit c0aef4c

File tree

3 files changed

+48
-13
lines changed

3 files changed

+48
-13
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystemProperties.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.nio.charset.Charset;
2020
import java.nio.charset.StandardCharsets;
21+
import java.util.function.BiConsumer;
2122

2223
import org.springframework.boot.system.ApplicationPid;
2324
import org.springframework.core.env.ConfigurableEnvironment;
@@ -130,15 +131,35 @@ public class LoggingSystemProperties {
130131
*/
131132
public static final String LOG_DATEFORMAT_PATTERN = "LOG_DATEFORMAT_PATTERN";
132133

134+
private static final BiConsumer<String, String> systemPropertySetter = (name, value) -> {
135+
if (System.getProperty(name) == null && value != null) {
136+
System.setProperty(name, value);
137+
}
138+
};
139+
133140
private final Environment environment;
134141

142+
private final BiConsumer<String, String> setter;
143+
135144
/**
136145
* Create a new {@link LoggingSystemProperties} instance.
137146
* @param environment the source environment
138147
*/
139148
public LoggingSystemProperties(Environment environment) {
149+
this(environment, systemPropertySetter);
150+
}
151+
152+
/**
153+
* Create a new {@link LoggingSystemProperties} instance.
154+
* @param environment the source environment
155+
* @param setter setter used to apply the property
156+
* @since 2.4.2
157+
*/
158+
public LoggingSystemProperties(Environment environment, BiConsumer<String, String> setter) {
140159
Assert.notNull(environment, "Environment must not be null");
160+
Assert.notNull(setter, "Setter must not be null");
141161
this.environment = environment;
162+
this.setter = setter;
142163
}
143164

144165
protected Charset getDefaultCharset() {
@@ -200,9 +221,7 @@ protected final void setSystemProperty(PropertyResolver resolver, String systemP
200221
}
201222

202223
protected final void setSystemProperty(String name, String value) {
203-
if (System.getProperty(name) == null && value != null) {
204-
System.setProperty(name, value);
205-
}
224+
this.setter.accept(name, value);
206225
}
207226

208227
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -146,15 +146,11 @@ protected void loadDefaults(LoggingInitializationContext initializationContext,
146146
if (debug) {
147147
StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
148148
}
149+
Environment environment = initializationContext.getEnvironment();
150+
// Apply system properties directly in case the same JVM runs multiple apps
151+
new LoggingSystemProperties(environment, context::putProperty).apply(logFile);
149152
LogbackConfigurator configurator = debug ? new DebugLogbackConfigurator(context)
150153
: new LogbackConfigurator(context);
151-
Environment environment = initializationContext.getEnvironment();
152-
context.putProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN,
153-
environment.resolvePlaceholders("${logging.pattern.level:${LOG_LEVEL_PATTERN:%5p}}"));
154-
context.putProperty(LoggingSystemProperties.LOG_DATEFORMAT_PATTERN, environment.resolvePlaceholders(
155-
"${logging.pattern.dateformat:${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}"));
156-
context.putProperty(LoggingSystemProperties.ROLLING_FILE_NAME_PATTERN, environment
157-
.resolvePlaceholders("${logging.pattern.rolling-file-name:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}"));
158154
new DefaultLogbackConfiguration(initializationContext, logFile).apply(configurator);
159155
context.setPackagingDataEnabled(true);
160156
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,7 +20,9 @@
2020
import java.nio.charset.StandardCharsets;
2121
import java.util.Arrays;
2222
import java.util.EnumSet;
23+
import java.util.HashSet;
2324
import java.util.List;
25+
import java.util.Set;
2426
import java.util.logging.Handler;
2527
import java.util.logging.LogManager;
2628

@@ -87,10 +89,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
8789

8890
private LoggingInitializationContext initializationContext;
8991

92+
private Set<Object> systemPropertyNames;
93+
9094
@BeforeEach
9195
void setup() {
9296
System.getProperties().remove(LoggingSystemProperties.CONSOLE_LOG_CHARSET);
9397
System.getProperties().remove(LoggingSystemProperties.FILE_LOG_CHARSET);
98+
this.systemPropertyNames = new HashSet<>(System.getProperties().keySet());
9499
this.loggingSystem.cleanUp();
95100
this.logger = ((LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory()).getLogger(getClass());
96101
this.environment = new MockEnvironment();
@@ -101,6 +106,7 @@ void setup() {
101106

102107
@AfterEach
103108
void cleanUp() {
109+
System.getProperties().keySet().retainAll(this.systemPropertyNames);
104110
this.loggingSystem.cleanUp();
105111
((LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory()).stop();
106112
}
@@ -312,6 +318,7 @@ void testConsolePatternProperty(CapturedOutput output) {
312318
@Test
313319
void testLevelPatternProperty(CapturedOutput output) {
314320
this.environment.setProperty("logging.pattern.level", "X%clr(%p)X");
321+
new LoggingSystemProperties(this.environment).apply();
315322
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
316323
initialize(loggingInitializationContext, null, null);
317324
this.logger.info("Hello world");
@@ -513,6 +520,19 @@ void initializationIsOnlyPerformedOnceUntilCleanedUp() {
513520

514521
@Test
515522
void testDateformatPatternProperty(CapturedOutput output) {
523+
this.environment.setProperty("logging.pattern.dateformat", "yyyy-MM-dd'T'hh:mm:ss.SSSZ");
524+
new LoggingSystemProperties(this.environment).apply();
525+
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
526+
initialize(loggingInitializationContext, null, null);
527+
this.logger.info("Hello world");
528+
assertThat(getLineWithText(output, "Hello world"))
529+
.containsPattern("\\d{4}-\\d{2}\\-\\d{2}T\\d{2}:\\d{2}:\\d{2}");
530+
}
531+
532+
@Test // gh-24835
533+
void testDateformatPatternPropertyDirect(CapturedOutput output) {
534+
this.environment.setProperty("logging.pattern.dateformat", "yyyy'T'hh:mm:ss.SSSZ");
535+
new LoggingSystemProperties(this.environment).apply();
516536
this.environment.setProperty("logging.pattern.dateformat", "yyyy-MM-dd'T'hh:mm:ss.SSSZ");
517537
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
518538
initialize(loggingInitializationContext, null, null);

0 commit comments

Comments
 (0)