Commit c0aef4c3 authored by Phillip Webb's avatar Phillip Webb

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
parent 68fc2329
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 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,6 +18,7 @@ package org.springframework.boot.logging; ...@@ -18,6 +18,7 @@ package org.springframework.boot.logging;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.function.BiConsumer;
import org.springframework.boot.system.ApplicationPid; import org.springframework.boot.system.ApplicationPid;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
...@@ -130,15 +131,35 @@ public class LoggingSystemProperties { ...@@ -130,15 +131,35 @@ public class LoggingSystemProperties {
*/ */
public static final String LOG_DATEFORMAT_PATTERN = "LOG_DATEFORMAT_PATTERN"; public static final String LOG_DATEFORMAT_PATTERN = "LOG_DATEFORMAT_PATTERN";
private static final BiConsumer<String, String> systemPropertySetter = (name, value) -> {
if (System.getProperty(name) == null && value != null) {
System.setProperty(name, value);
}
};
private final Environment environment; private final Environment environment;
private final BiConsumer<String, String> setter;
/** /**
* Create a new {@link LoggingSystemProperties} instance. * Create a new {@link LoggingSystemProperties} instance.
* @param environment the source environment * @param environment the source environment
*/ */
public LoggingSystemProperties(Environment environment) { public LoggingSystemProperties(Environment environment) {
this(environment, systemPropertySetter);
}
/**
* Create a new {@link LoggingSystemProperties} instance.
* @param environment the source environment
* @param setter setter used to apply the property
* @since 2.4.2
*/
public LoggingSystemProperties(Environment environment, BiConsumer<String, String> setter) {
Assert.notNull(environment, "Environment must not be null"); Assert.notNull(environment, "Environment must not be null");
Assert.notNull(setter, "Setter must not be null");
this.environment = environment; this.environment = environment;
this.setter = setter;
} }
protected Charset getDefaultCharset() { protected Charset getDefaultCharset() {
...@@ -200,9 +221,7 @@ public class LoggingSystemProperties { ...@@ -200,9 +221,7 @@ public class LoggingSystemProperties {
} }
protected final void setSystemProperty(String name, String value) { protected final void setSystemProperty(String name, String value) {
if (System.getProperty(name) == null && value != null) { this.setter.accept(name, value);
System.setProperty(name, value);
}
} }
} }
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 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.
...@@ -146,15 +146,11 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem { ...@@ -146,15 +146,11 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
if (debug) { if (debug) {
StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener()); StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
} }
Environment environment = initializationContext.getEnvironment();
// Apply system properties directly in case the same JVM runs multiple apps
new LoggingSystemProperties(environment, context::putProperty).apply(logFile);
LogbackConfigurator configurator = debug ? new DebugLogbackConfigurator(context) LogbackConfigurator configurator = debug ? new DebugLogbackConfigurator(context)
: new LogbackConfigurator(context); : new LogbackConfigurator(context);
Environment environment = initializationContext.getEnvironment();
context.putProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN,
environment.resolvePlaceholders("${logging.pattern.level:${LOG_LEVEL_PATTERN:%5p}}"));
context.putProperty(LoggingSystemProperties.LOG_DATEFORMAT_PATTERN, environment.resolvePlaceholders(
"${logging.pattern.dateformat:${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}"));
context.putProperty(LoggingSystemProperties.ROLLING_FILE_NAME_PATTERN, environment
.resolvePlaceholders("${logging.pattern.rolling-file-name:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}"));
new DefaultLogbackConfiguration(initializationContext, logFile).apply(configurator); new DefaultLogbackConfiguration(initializationContext, logFile).apply(configurator);
context.setPackagingDataEnabled(true); context.setPackagingDataEnabled(true);
} }
......
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 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.
...@@ -20,7 +20,9 @@ import java.io.File; ...@@ -20,7 +20,9 @@ import java.io.File;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.logging.Handler; import java.util.logging.Handler;
import java.util.logging.LogManager; import java.util.logging.LogManager;
...@@ -87,10 +89,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -87,10 +89,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
private LoggingInitializationContext initializationContext; private LoggingInitializationContext initializationContext;
private Set<Object> systemPropertyNames;
@BeforeEach @BeforeEach
void setup() { void setup() {
System.getProperties().remove(LoggingSystemProperties.CONSOLE_LOG_CHARSET); System.getProperties().remove(LoggingSystemProperties.CONSOLE_LOG_CHARSET);
System.getProperties().remove(LoggingSystemProperties.FILE_LOG_CHARSET); System.getProperties().remove(LoggingSystemProperties.FILE_LOG_CHARSET);
this.systemPropertyNames = new HashSet<>(System.getProperties().keySet());
this.loggingSystem.cleanUp(); this.loggingSystem.cleanUp();
this.logger = ((LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory()).getLogger(getClass()); this.logger = ((LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory()).getLogger(getClass());
this.environment = new MockEnvironment(); this.environment = new MockEnvironment();
...@@ -101,6 +106,7 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -101,6 +106,7 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
@AfterEach @AfterEach
void cleanUp() { void cleanUp() {
System.getProperties().keySet().retainAll(this.systemPropertyNames);
this.loggingSystem.cleanUp(); this.loggingSystem.cleanUp();
((LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory()).stop(); ((LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory()).stop();
} }
...@@ -312,6 +318,7 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -312,6 +318,7 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
@Test @Test
void testLevelPatternProperty(CapturedOutput output) { void testLevelPatternProperty(CapturedOutput output) {
this.environment.setProperty("logging.pattern.level", "X%clr(%p)X"); this.environment.setProperty("logging.pattern.level", "X%clr(%p)X");
new LoggingSystemProperties(this.environment).apply();
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment); LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
initialize(loggingInitializationContext, null, null); initialize(loggingInitializationContext, null, null);
this.logger.info("Hello world"); this.logger.info("Hello world");
...@@ -513,6 +520,19 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { ...@@ -513,6 +520,19 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
@Test @Test
void testDateformatPatternProperty(CapturedOutput output) { void testDateformatPatternProperty(CapturedOutput output) {
this.environment.setProperty("logging.pattern.dateformat", "yyyy-MM-dd'T'hh:mm:ss.SSSZ");
new LoggingSystemProperties(this.environment).apply();
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
initialize(loggingInitializationContext, null, null);
this.logger.info("Hello world");
assertThat(getLineWithText(output, "Hello world"))
.containsPattern("\\d{4}-\\d{2}\\-\\d{2}T\\d{2}:\\d{2}:\\d{2}");
}
@Test // gh-24835
void testDateformatPatternPropertyDirect(CapturedOutput output) {
this.environment.setProperty("logging.pattern.dateformat", "yyyy'T'hh:mm:ss.SSSZ");
new LoggingSystemProperties(this.environment).apply();
this.environment.setProperty("logging.pattern.dateformat", "yyyy-MM-dd'T'hh:mm:ss.SSSZ"); this.environment.setProperty("logging.pattern.dateformat", "yyyy-MM-dd'T'hh:mm:ss.SSSZ");
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment); LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
initialize(loggingInitializationContext, null, null); initialize(loggingInitializationContext, null, null);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment