Browse Source

Switch Logback's file logging charset to UTF-8

This commit aligns the file charset between Log4j2 and Logback.

Prior to this commit, there was an inconsistency between the two: Log4j2
used UTF-8, while Logback used Charset.defaultCharset(), which is
platform-dependent.

See gh-46846

Signed-off-by: Dmytro Nosan <dimanosan@gmail.com>
pull/46890/head
Dmytro Nosan 4 months ago committed by Stéphane Nicoll
parent
commit
26372e78c6
  1. 15
      core/spring-boot/src/main/java/org/springframework/boot/logging/logback/DefaultLogbackConfiguration.java
  2. 6
      core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystemProperties.java
  3. 68
      core/spring-boot/src/test/java/org/springframework/boot/logging/logback/DefaultLogbackConfigurationTests.java
  4. 4
      core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemPropertiesTests.java

15
core/spring-boot/src/main/java/org/springframework/boot/logging/logback/DefaultLogbackConfiguration.java

@ -16,7 +16,9 @@ @@ -16,7 +16,9 @@
package org.springframework.boot.logging.logback;
import java.io.Console;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
@ -55,7 +57,7 @@ import org.springframework.util.StringUtils; @@ -55,7 +57,7 @@ import org.springframework.util.StringUtils;
*/
class DefaultLogbackConfiguration {
private static final String DEFAULT_CHARSET = Charset.defaultCharset().name();
private static final String DEFAULT_CHARSET = StandardCharsets.UTF_8.name();
private static final String NAME_AND_GROUP = "%esb(){APPLICATION_NAME}%esb{APPLICATION_GROUP}";
@ -106,7 +108,7 @@ class DefaultLogbackConfiguration { @@ -106,7 +108,7 @@ class DefaultLogbackConfiguration {
config.conversionRule("wEx", ExtendedWhitespaceThrowableProxyConverter.class,
ExtendedWhitespaceThrowableProxyConverter::new);
putProperty(config, "CONSOLE_LOG_PATTERN", CONSOLE_LOG_PATTERN);
putProperty(config, "CONSOLE_LOG_CHARSET", "${CONSOLE_LOG_CHARSET:-" + DEFAULT_CHARSET + "}");
putProperty(config, "CONSOLE_LOG_CHARSET", "${CONSOLE_LOG_CHARSET:-" + getConsoleCharset() + "}");
putProperty(config, "CONSOLE_LOG_THRESHOLD", "${CONSOLE_LOG_THRESHOLD:-TRACE}");
putProperty(config, "CONSOLE_LOG_STRUCTURED_FORMAT", "${CONSOLE_LOG_STRUCTURED_FORMAT:-}");
putProperty(config, "FILE_LOG_PATTERN", FILE_LOG_PATTERN);
@ -123,6 +125,15 @@ class DefaultLogbackConfiguration { @@ -123,6 +125,15 @@ class DefaultLogbackConfiguration {
config.logger("org.springframework.boot.actuate.endpoint.jmx", Level.WARN);
}
private String getConsoleCharset() {
Console console = getConsole();
return (console != null) ? console.charset().name() : DEFAULT_CHARSET;
}
@Nullable Console getConsole() {
return System.console();
}
void putProperty(LogbackConfigurator config, String name, String val) {
config.getContext().putProperty(name, resolve(config, val));
}

6
core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystemProperties.java

@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
package org.springframework.boot.logging.logback;
import java.io.Console;
import java.nio.charset.Charset;
import java.util.function.BiConsumer;
import java.util.function.Function;
@ -78,11 +77,6 @@ public class LogbackLoggingSystemProperties extends LoggingSystemProperties { @@ -78,11 +77,6 @@ public class LogbackLoggingSystemProperties extends LoggingSystemProperties {
return super.getConsole();
}
@Override
protected Charset getDefaultFileCharset() {
return Charset.defaultCharset();
}
@Override
protected void apply(@Nullable LogFile logFile, PropertyResolver resolver) {
super.apply(logFile, resolver);

68
core/spring-boot/src/test/java/org/springframework/boot/logging/logback/DefaultLogbackConfigurationTests.java

@ -16,14 +16,19 @@ @@ -16,14 +16,19 @@
package org.springframework.boot.logging.logback;
import java.io.Console;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import ch.qos.logback.classic.LoggerContext;
import org.junit.jupiter.api.Test;
import org.springframework.util.StreamUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
/**
* Tests for {@link DefaultLogbackConfiguration}
@ -32,6 +37,10 @@ import static org.assertj.core.api.Assertions.assertThat; @@ -32,6 +37,10 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class DefaultLogbackConfigurationTests {
private final LoggerContext loggerContext = new LoggerContext();
private final LogbackConfigurator logbackConfigurator = new LogbackConfigurator(this.loggerContext);
@Test
void defaultLogbackXmlContainsConsoleLogPattern() throws Exception {
assertThatDefaultXmlContains("CONSOLE_LOG_PATTERN", DefaultLogbackConfiguration.CONSOLE_LOG_PATTERN);
@ -42,6 +51,48 @@ class DefaultLogbackConfigurationTests { @@ -42,6 +51,48 @@ class DefaultLogbackConfigurationTests {
assertThatDefaultXmlContains("FILE_LOG_PATTERN", DefaultLogbackConfiguration.FILE_LOG_PATTERN);
}
@Test
void consoleLogCharsetShouldUseConsoleCharsetIfConsoleAvailable() {
DefaultLogbackConfiguration logbackConfiguration = spy(new DefaultLogbackConfiguration(null));
Console console = mock(Console.class);
given(console.charset()).willReturn(StandardCharsets.UTF_16);
given(logbackConfiguration.getConsole()).willReturn(console);
logbackConfiguration.apply(this.logbackConfigurator);
assertThat(this.loggerContext.getProperty("CONSOLE_LOG_CHARSET")).isEqualTo(StandardCharsets.UTF_16.name());
}
@Test
void consoleLogCharsetShouldDefaultToUtf8WhenConsoleIsNull() {
DefaultLogbackConfiguration logbackConfiguration = spy(new DefaultLogbackConfiguration(null));
given(logbackConfiguration.getConsole()).willReturn(null);
logbackConfiguration.apply(this.logbackConfigurator);
assertThat(this.loggerContext.getProperty("CONSOLE_LOG_CHARSET")).isEqualTo(StandardCharsets.UTF_8.name());
}
@Test
void consoleLogCharsetShouldUseSystemPropertyIfSet() {
withSystemProperty("CONSOLE_LOG_CHARSET", StandardCharsets.US_ASCII.name(), () -> {
new DefaultLogbackConfiguration(null).apply(this.logbackConfigurator);
assertThat(this.loggerContext.getProperty("CONSOLE_LOG_CHARSET"))
.isEqualTo(StandardCharsets.US_ASCII.name());
});
}
@Test
void fileLogCharsetShouldUseSystemPropertyIfSet() {
withSystemProperty("FILE_LOG_CHARSET", StandardCharsets.ISO_8859_1.name(), () -> {
new DefaultLogbackConfiguration(null).apply(this.logbackConfigurator);
assertThat(this.loggerContext.getProperty("FILE_LOG_CHARSET"))
.isEqualTo(StandardCharsets.ISO_8859_1.name());
});
}
@Test
void fileLogCharsetShouldDefaultToUtf8() {
new DefaultLogbackConfiguration(null).apply(this.logbackConfigurator);
assertThat(this.loggerContext.getProperty("FILE_LOG_CHARSET")).isEqualTo(StandardCharsets.UTF_8.name());
}
private void assertThatDefaultXmlContains(String name, String value) throws Exception {
String expected = "<property name=\"%s\" value=\"%s\"/>".formatted(name, value);
assertThat(defaultXmlContent()).contains(expected);
@ -51,4 +102,21 @@ class DefaultLogbackConfigurationTests { @@ -51,4 +102,21 @@ class DefaultLogbackConfigurationTests {
return StreamUtils.copyToString(getClass().getResourceAsStream("defaults.xml"), StandardCharsets.UTF_8);
}
private static void withSystemProperty(String name, String value, Runnable action) {
String previous = System.getProperty(name);
try {
System.setProperty(name, value);
action.run();
}
finally {
if (previous != null) {
System.setProperty(name, previous);
}
else {
System.clearProperty(name);
}
}
}
}

4
core/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemPropertiesTests.java

@ -131,10 +131,10 @@ class LogbackLoggingSystemPropertiesTests { @@ -131,10 +131,10 @@ class LogbackLoggingSystemPropertiesTests {
}
@Test
void fileCharsetWhenNoPropertyUsesDefault() {
void fileCharsetWhenNoPropertyUsesUtf8() {
new LoggingSystemProperties(new MockEnvironment()).apply(null);
assertThat(System.getProperty(LoggingSystemProperty.FILE_CHARSET.getEnvironmentVariableName()))
.isEqualTo(Charset.defaultCharset().name());
.isEqualTo(StandardCharsets.UTF_8.name());
}
}

Loading…
Cancel
Save