Add properties for logging charsets
Add `logging.charset.console` and `logging.charset.file` properties that can be used to configure charsets for Logback/Log4J2. Closes gh-23827
This commit is contained in:
@@ -2204,10 +2204,18 @@ To help with the customization, some other properties are transferred from the S
|
||||
| `LOG_DATEFORMAT_PATTERN`
|
||||
| Appender pattern for log date format.
|
||||
|
||||
| configprop:logging.charset.console[]
|
||||
| `CONSOLE_LOG_CHARSET`
|
||||
| The charset to use for console logging.
|
||||
|
||||
| configprop:logging.pattern.file[]
|
||||
| `FILE_LOG_PATTERN`
|
||||
| The log pattern to use in a file (if `LOG_FILE` is enabled).
|
||||
|
||||
| configprop:logging.charset.file[]
|
||||
| `FILE_LOG_CHARSET`
|
||||
| The charset to use for file logging (if `LOG_FILE` is enabled).
|
||||
|
||||
| configprop:logging.pattern.level[]
|
||||
| `LOG_LEVEL_PATTERN`
|
||||
| The format to use when rendering the log level (default `%5p`).
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.boot.logging;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.springframework.boot.system.ApplicationPid;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -61,11 +64,21 @@ public class LoggingSystemProperties {
|
||||
*/
|
||||
public static final String CONSOLE_LOG_PATTERN = "CONSOLE_LOG_PATTERN";
|
||||
|
||||
/**
|
||||
* The name of the System property that contains the console log charset.
|
||||
*/
|
||||
public static final String CONSOLE_LOG_CHARSET = "CONSOLE_LOG_CHARSET";
|
||||
|
||||
/**
|
||||
* The name of the System property that contains the file log pattern.
|
||||
*/
|
||||
public static final String FILE_LOG_PATTERN = "FILE_LOG_PATTERN";
|
||||
|
||||
/**
|
||||
* The name of the System property that contains the file log charset.
|
||||
*/
|
||||
public static final String FILE_LOG_CHARSET = "FILE_LOG_CHARSET";
|
||||
|
||||
/**
|
||||
* The name of the System property that contains the rolled-over log file name
|
||||
* pattern.
|
||||
@@ -128,6 +141,10 @@ public class LoggingSystemProperties {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
protected Charset getDefaultCharset() {
|
||||
return StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
public final void apply() {
|
||||
apply(null);
|
||||
}
|
||||
@@ -141,8 +158,10 @@ public class LoggingSystemProperties {
|
||||
setSystemProperty(resolver, EXCEPTION_CONVERSION_WORD, "logging.exception-conversion-word");
|
||||
setSystemProperty(PID_KEY, new ApplicationPid().toString());
|
||||
setSystemProperty(resolver, CONSOLE_LOG_PATTERN, "logging.pattern.console");
|
||||
setSystemProperty(resolver, CONSOLE_LOG_CHARSET, "logging.charset.console", getDefaultCharset().name());
|
||||
setSystemProperty(resolver, LOG_DATEFORMAT_PATTERN, "logging.pattern.dateformat");
|
||||
setSystemProperty(resolver, FILE_LOG_PATTERN, "logging.pattern.file");
|
||||
setSystemProperty(resolver, FILE_LOG_CHARSET, "logging.charset.file", getDefaultCharset().name());
|
||||
setSystemProperty(resolver, LOG_LEVEL_PATTERN, "logging.pattern.level");
|
||||
applyDeprecated(resolver);
|
||||
if (logFile != null) {
|
||||
@@ -170,7 +189,14 @@ public class LoggingSystemProperties {
|
||||
}
|
||||
|
||||
protected final void setSystemProperty(PropertyResolver resolver, String systemPropertyName, String propertyName) {
|
||||
setSystemProperty(systemPropertyName, resolver.getProperty(propertyName));
|
||||
setSystemProperty(resolver, systemPropertyName, propertyName, null);
|
||||
}
|
||||
|
||||
protected final void setSystemProperty(PropertyResolver resolver, String systemPropertyName, String propertyName,
|
||||
String defaultValue) {
|
||||
String value = resolver.getProperty(propertyName);
|
||||
value = (value != null) ? value : defaultValue;
|
||||
setSystemProperty(systemPropertyName, value);
|
||||
}
|
||||
|
||||
protected final void setSystemProperty(String name, String value) {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.logging.logback;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
@@ -87,6 +89,7 @@ class DefaultLogbackConfiguration {
|
||||
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<>();
|
||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||
encoder.setPattern(resolve(config, "${CONSOLE_LOG_PATTERN}"));
|
||||
encoder.setCharset(resolveCharset(config, "${CONSOLE_LOG_CHARSET}"));
|
||||
config.start(encoder);
|
||||
appender.setEncoder(encoder);
|
||||
config.appender("CONSOLE", appender);
|
||||
@@ -97,6 +100,7 @@ class DefaultLogbackConfiguration {
|
||||
RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<>();
|
||||
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
|
||||
encoder.setPattern(resolve(config, "${FILE_LOG_PATTERN}"));
|
||||
encoder.setCharset(resolveCharset(config, "${FILE_LOG_CHARSET}"));
|
||||
appender.setEncoder(encoder);
|
||||
config.start(encoder);
|
||||
appender.setFile(logFile);
|
||||
@@ -133,6 +137,10 @@ class DefaultLogbackConfiguration {
|
||||
return FileSize.valueOf(resolve(config, val));
|
||||
}
|
||||
|
||||
private Charset resolveCharset(LogbackConfigurator config, String val) {
|
||||
return Charset.forName(resolve(config, val));
|
||||
}
|
||||
|
||||
private String resolve(LogbackConfigurator config, String val) {
|
||||
return OptionHelper.substVars(val, config.getContext());
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.logging.logback;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import ch.qos.logback.core.util.FileSize;
|
||||
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
@@ -64,6 +66,11 @@ public class LogbackLoggingSystemProperties extends LoggingSystemProperties {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Charset getDefaultCharset() {
|
||||
return Charset.defaultCharset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(LogFile logFile, PropertyResolver resolver) {
|
||||
super.apply(logFile, resolver);
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
"description": "Location of the logging configuration file. For instance, `classpath:logback.xml` for Logback.",
|
||||
"sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener"
|
||||
},
|
||||
{
|
||||
"name": "logging.charset.console",
|
||||
"type": "java.nio.Charset",
|
||||
"description": "The charset to use for console output"
|
||||
},
|
||||
{
|
||||
"name": "logging.charset.file",
|
||||
"type": "java.nio.Charset",
|
||||
"description": "The charset to use for file output"
|
||||
},
|
||||
{
|
||||
"name": "logging.exception-conversion-word",
|
||||
"type": "java.lang.String",
|
||||
|
||||
@@ -9,12 +9,10 @@
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT" follow="true">
|
||||
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
|
||||
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" charset="${sys:CONSOLE_LOG_CHARSET}" />
|
||||
</Console>
|
||||
<RollingFile name="File" fileName="${sys:LOG_FILE}" filePattern="${sys:LOG_PATH}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
|
||||
<PatternLayout>
|
||||
<Pattern>${sys:FILE_LOG_PATTERN}</Pattern>
|
||||
</PatternLayout>
|
||||
<PatternLayout pattern="${sys:FILE_LOG_PATTERN}" charset="${sys:FILE_LOG_CHARSET}"/>
|
||||
<Policies>
|
||||
<SizeBasedTriggeringPolicy size="10 MB" />
|
||||
</Policies>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</Properties>
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT" follow="true">
|
||||
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
|
||||
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" charset="${sys:CONSOLE_LOG_CHARSET}"/>
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
|
||||
@@ -9,6 +9,7 @@ initialization performed by Boot
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>${CONSOLE_LOG_CHARSET}</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
</included>
|
||||
|
||||
@@ -6,10 +6,10 @@ initialization performed by Boot
|
||||
-->
|
||||
|
||||
<included>
|
||||
<appender name="FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
<charset>${FILE_LOG_CHARSET}</charset>
|
||||
</encoder>
|
||||
<file>${LOG_FILE}</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
|
||||
@@ -43,6 +43,8 @@ class LoggingSystemPropertiesTests {
|
||||
|
||||
@BeforeEach
|
||||
void captureSystemPropertyNames() {
|
||||
System.getProperties().remove(LoggingSystemProperties.CONSOLE_LOG_CHARSET);
|
||||
System.getProperties().remove(LoggingSystemProperties.FILE_LOG_CHARSET);
|
||||
this.systemPropertyNames = new HashSet<>(System.getProperties().keySet());
|
||||
}
|
||||
|
||||
@@ -64,6 +66,19 @@ class LoggingSystemPropertiesTests {
|
||||
assertThat(System.getProperty(LoggingSystemProperties.CONSOLE_LOG_PATTERN)).isEqualTo("console pattern");
|
||||
}
|
||||
|
||||
@Test
|
||||
void consoleCharsetWhenNoPropertyUsesUtf8() {
|
||||
new LoggingSystemProperties(new MockEnvironment()).apply(null);
|
||||
assertThat(System.getProperty(LoggingSystemProperties.CONSOLE_LOG_CHARSET)).isEqualTo("UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void consoleCharsetIsSet() {
|
||||
new LoggingSystemProperties(new MockEnvironment().withProperty("logging.charset.console", "UTF-16"))
|
||||
.apply(null);
|
||||
assertThat(System.getProperty(LoggingSystemProperties.CONSOLE_LOG_CHARSET)).isEqualTo("UTF-16");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fileLogPatternIsSet() {
|
||||
new LoggingSystemProperties(new MockEnvironment().withProperty("logging.pattern.file", "file pattern"))
|
||||
@@ -71,6 +86,18 @@ class LoggingSystemPropertiesTests {
|
||||
assertThat(System.getProperty(LoggingSystemProperties.FILE_LOG_PATTERN)).isEqualTo("file pattern");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fileCharsetWhenNoPropertyUsesUtf8() {
|
||||
new LoggingSystemProperties(new MockEnvironment()).apply(null);
|
||||
assertThat(System.getProperty(LoggingSystemProperties.FILE_LOG_CHARSET)).isEqualTo("UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fileCharsetIsSet() {
|
||||
new LoggingSystemProperties(new MockEnvironment().withProperty("logging.charset.file", "UTF-16")).apply(null);
|
||||
assertThat(System.getProperty(LoggingSystemProperties.FILE_LOG_CHARSET)).isEqualTo("UTF-16");
|
||||
}
|
||||
|
||||
@Test
|
||||
void consoleLogPatternCanReferencePid() {
|
||||
new LoggingSystemProperties(environment("logging.pattern.console", "${PID:unknown}")).apply(null);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.boot.logging.logback;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -43,6 +44,8 @@ class LogbackLoggingSystemPropertiesTests {
|
||||
|
||||
@BeforeEach
|
||||
void captureSystemPropertyNames() {
|
||||
System.getProperties().remove(LoggingSystemProperties.CONSOLE_LOG_CHARSET);
|
||||
System.getProperties().remove(LoggingSystemProperties.FILE_LOG_CHARSET);
|
||||
this.systemPropertyNames = new HashSet<>(System.getProperties().keySet());
|
||||
this.environment = new MockEnvironment();
|
||||
this.environment
|
||||
@@ -94,4 +97,18 @@ class LogbackLoggingSystemPropertiesTests {
|
||||
.containsEntry(LogbackLoggingSystemProperties.ROLLINGPOLICY_MAX_HISTORY, "mh");
|
||||
}
|
||||
|
||||
@Test
|
||||
void consoleCharsetWhenNoPropertyUsesDefault() {
|
||||
new LoggingSystemProperties(new MockEnvironment()).apply(null);
|
||||
assertThat(System.getProperty(LoggingSystemProperties.CONSOLE_LOG_CHARSET))
|
||||
.isEqualTo(Charset.defaultCharset().name());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fileCharsetWhenNoPropertyUsesDefault() {
|
||||
new LoggingSystemProperties(new MockEnvironment()).apply(null);
|
||||
assertThat(System.getProperty(LoggingSystemProperties.FILE_LOG_CHARSET))
|
||||
.isEqualTo(Charset.defaultCharset().name());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.logging.logback;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
@@ -30,6 +31,7 @@ import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.spi.LoggerContextListener;
|
||||
import ch.qos.logback.core.ConsoleAppender;
|
||||
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
|
||||
import ch.qos.logback.core.rolling.RollingFileAppender;
|
||||
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -564,6 +566,18 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
assertThat(getRollingPolicy().getFileNamePattern()).isEqualTo(rollingFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customCharset() {
|
||||
this.environment.setProperty("logging.charset.console", "UTF-16");
|
||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||
File file = new File(tmpDir(), "logback-test.log");
|
||||
LogFile logFile = getLogFile(file.getPath(), null);
|
||||
initialize(loggingInitializationContext, null, logFile);
|
||||
this.logger.info("Hello world");
|
||||
LayoutWrappingEncoder<?> encoder = (LayoutWrappingEncoder<?>) getConsoleAppender().getEncoder();
|
||||
assertThat(encoder.getCharset()).isEqualTo(StandardCharsets.UTF_16);
|
||||
}
|
||||
|
||||
private void initialize(LoggingInitializationContext context, String configLocation, LogFile logFile) {
|
||||
this.loggingSystem.getSystemProperties((ConfigurableEnvironment) context.getEnvironment()).apply(logFile);
|
||||
this.loggingSystem.initialize(context, configLocation, logFile);
|
||||
|
||||
Reference in New Issue
Block a user