Merge pull request #18151 from eddumelendez

* pr/18151:
  Polish "Add ROLLING_FILE_NAME_PATTERN for File Appender"
  Add ROLLING_FILE_NAME_PATTERN for File Appender

Closes gh-18151
This commit is contained in:
Stephane Nicoll
2019-09-16 09:28:30 +02:00
13 changed files with 93 additions and 5 deletions

View File

@@ -1307,7 +1307,7 @@ The following files are provided under `org/springframework/boot/logging/logback
* `defaults.xml` - Provides conversion rules, pattern properties and common logger configurations.
* `console-appender.xml` - Adds a `ConsoleAppender` using the `CONSOLE_LOG_PATTERN`.
* `file-appender.xml` - Adds a `RollingFileAppender` using the `FILE_LOG_PATTERN` with appropriate settings.
* `file-appender.xml` - Adds a `RollingFileAppender` using the `FILE_LOG_PATTERN` and `ROLLING_FILE_NAME_PATTERN` with appropriate settings.
In addition, a legacy `base.xml` file is provided for compatibility with earlier versions of Spring Boot.
@@ -1332,6 +1332,7 @@ Your logback configuration file can also make use of System properties that the
* `$\{LOG_FILE}`: Whether `logging.file.name` was set in Boot's external configuration.
* `$\{LOG_PATH}`: Whether `logging.file.path` (representing a directory for log files to live in) was set in Boot's external configuration.
* `$\{LOG_EXCEPTION_CONVERSION_WORD}`: Whether `logging.exception-conversion-word` was set in Boot's external configuration.
* `$\{ROLLING_FILE_NAME_PATTERN}`: Whether `logging.pattern.rolling-file-name` was set in Boot's external configuration.
Spring Boot also provides some nice ANSI color terminal output on a console (but not in a log file) by using a custom Logback converter.
See the `CONSOLE_LOG_PATTERN` in the `default.xml` configuration for an example.

View File

@@ -1,6 +1,6 @@
[[spring-boot-reference-documentation]]
= Spring Boot Reference Documentation
Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch, Andy Wilkinson, Marcel Overdijk, Christian Dupuis, Sébastien Deleuze, Michael Simons, Vedran Pavić, Jay Bryant, Madhura Bhave
Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch, Andy Wilkinson, Marcel Overdijk, Christian Dupuis, Sébastien Deleuze, Michael Simons, Vedran Pavić, Jay Bryant, Madhura Bhave, Eddú Meléndez
:docinfo: shared
The reference documentation consists of the following sections:

View File

@@ -1775,6 +1775,11 @@ To help with the customization, some other properties are transferred from the S
| The format to use when rendering the log level (default `%5p`).
(Only supported with the default Logback setup.)
| `logging.pattern.rolling-file-name`
| `ROLLING_FILE_NAME_PATTERN`
| Pattern for rolled-over log file names (default `$\{LOG_FILE}.%d\{yyyy-MM-dd}.%i.gz`).
(Only supported with the default Logback setup.)
| `PID`
| `PID`
| The current process ID (discovered if possible and when not already defined as an OS environment variable).

View File

@@ -31,6 +31,7 @@ import org.springframework.util.Assert;
* @author Madhura Bhave
* @author Vedran Pavic
* @author Robert Thornton
* @author Eddú Meléndez
* @since 2.0.0
*/
public class LoggingSystemProperties {
@@ -95,6 +96,12 @@ public class LoggingSystemProperties {
*/
public static final String LOG_DATEFORMAT_PATTERN = "LOG_DATEFORMAT_PATTERN";
/**
* The name of the System property that contains the rolled-over log file name
* pattern.
*/
public static final String ROLLING_FILE_NAME_PATTERN = "ROLLING_FILE_NAME_PATTERN";
private final Environment environment;
/**
@@ -122,6 +129,7 @@ public class LoggingSystemProperties {
setSystemProperty(resolver, FILE_TOTAL_SIZE_CAP, "file.total-size-cap");
setSystemProperty(resolver, LOG_LEVEL_PATTERN, "pattern.level");
setSystemProperty(resolver, LOG_DATEFORMAT_PATTERN, "pattern.dateformat");
setSystemProperty(resolver, ROLLING_FILE_NAME_PATTERN, "pattern.rolling-file-name");
if (logFile != null) {
logFile.applyToSystemProperties();
}

View File

@@ -140,7 +140,8 @@ class DefaultLogbackConfiguration {
SizeAndTimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new SizeAndTimeBasedRollingPolicy<>();
rollingPolicy.setCleanHistoryOnStart(
this.patterns.getProperty("logging.file.clean-history-on-start", Boolean.class, false));
rollingPolicy.setFileNamePattern(logFile + ".%d{yyyy-MM-dd}.%i.gz");
rollingPolicy.setFileNamePattern(
this.patterns.getProperty("logging.pattern.rolling-file-name", logFile + ".%d{yyyy-MM-dd}.%i.gz"));
setMaxFileSize(rollingPolicy, getDataSize("logging.file.max-size", MAX_FILE_SIZE));
rollingPolicy
.setMaxHistory(this.patterns.getProperty("logging.file.max-history", Integer.class, MAX_FILE_HISTORY));

View File

@@ -139,6 +139,8 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
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);
context.setPackagingDataEnabled(true);
}

View File

@@ -165,6 +165,13 @@
"sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
"defaultValue": "%5p"
},
{
"name": "logging.pattern.rolling-file-name",
"type": "java.lang.String",
"description": "Pattern for rolled-over log file names. Supported only with the default Logback setup.",
"sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
"defaultValue": "${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz"
},
{
"name": "logging.register-shutdown-hook",
"type": "java.lang.Boolean",

View File

@@ -14,7 +14,7 @@ initialization performed by Boot
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<cleanHistoryOnStart>${LOG_FILE_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<fileNamePattern>${ROLLING_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
<maxHistory>${LOG_FILE_MAX_HISTORY:-7}</maxHistory>
<totalSizeCap>${LOG_FILE_TOTAL_SIZE_CAP:-0}</totalSizeCap>

View File

@@ -83,6 +83,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
* @author Stephane Nicoll
* @author Ben Hale
* @author Fahim Farook
* @author Eddú Meléndez
*/
@ExtendWith(OutputCaptureExtension.class)
@ClassPathExclusions("log4j*.jar")
@@ -134,6 +135,7 @@ class LoggingApplicationListenerTests {
System.clearProperty(LoggingSystemProperties.CONSOLE_LOG_PATTERN);
System.clearProperty(LoggingSystemProperties.FILE_LOG_PATTERN);
System.clearProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN);
System.clearProperty(LoggingSystemProperties.ROLLING_FILE_NAME_PATTERN);
System.clearProperty(LoggingSystem.SYSTEM_PROPERTY);
if (this.context != null) {
this.context.close();
@@ -479,7 +481,8 @@ class LoggingApplicationListenerTests {
void systemPropertiesAreSetForLoggingConfiguration() {
addPropertiesToEnvironment(this.context, "logging.exception-conversion-word=conversion",
"logging.file.name=" + this.logFile, "logging.file.path=path", "logging.pattern.console=console",
"logging.pattern.file=file", "logging.pattern.level=level");
"logging.pattern.file=file", "logging.pattern.level=level",
"logging.pattern.rolling-file-name=my.log.%d{yyyyMMdd}.%i.gz");
this.initializer.initialize(this.context.getEnvironment(), this.context.getClassLoader());
assertThat(System.getProperty(LoggingSystemProperties.CONSOLE_LOG_PATTERN)).isEqualTo("console");
assertThat(System.getProperty(LoggingSystemProperties.FILE_LOG_PATTERN)).isEqualTo("file");
@@ -487,6 +490,8 @@ class LoggingApplicationListenerTests {
assertThat(System.getProperty(LoggingSystemProperties.LOG_FILE)).isEqualTo(this.logFile.getAbsolutePath());
assertThat(System.getProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN)).isEqualTo("level");
assertThat(System.getProperty(LoggingSystemProperties.LOG_PATH)).isEqualTo("path");
assertThat(System.getProperty(LoggingSystemProperties.ROLLING_FILE_NAME_PATTERN))
.isEqualTo("my.log.%d{yyyyMMdd}.%i.gz");
assertThat(System.getProperty(LoggingSystemProperties.PID_KEY)).isNotNull();
}

View File

@@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link LoggingSystemProperties}.
*
* @author Andy Wilkinson
* @author Eddú Meléndez
*/
class LoggingSystemPropertiesTests {
@@ -82,6 +83,15 @@ class LoggingSystemPropertiesTests {
assertThat(System.getProperty(LoggingSystemProperties.FILE_LOG_PATTERN)).matches("[0-9]+");
}
@Test
void rollingFileNameIsSet() {
new LoggingSystemProperties(
new MockEnvironment().withProperty("logging.pattern.rolling-file-name", "rolling file pattern"))
.apply(null);
assertThat(System.getProperty(LoggingSystemProperties.ROLLING_FILE_NAME_PATTERN))
.isEqualTo("rolling file pattern");
}
private Environment environment(String key, Object value) {
StandardEnvironment environment = new StandardEnvironment();
environment.getPropertySources().addLast(new MapPropertySource("test", Collections.singletonMap(key, value)));

View File

@@ -27,6 +27,9 @@ import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.RollingPolicy;
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -35,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for default Logback configuration provided by {@code base.xml}.
*
* @author Andy Wilkinson
* @author Eddú Meléndez
*/
class LogbackConfigurationTests {
@@ -64,4 +68,30 @@ class LogbackConfigurationTests {
assertThat(((PatternLayoutEncoder) encoder).getPattern()).isEqualTo("bar");
}
@Test
void defaultRollingFileNamePattern() throws JoranException {
JoranConfigurator configurator = new JoranConfigurator();
LoggerContext context = new LoggerContext();
configurator.setContext(context);
configurator.doConfigure(new File("src/test/resources/custom-file-log-pattern.xml"));
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
assertThat(appender).isInstanceOf(RollingFileAppender.class);
RollingPolicy rollingPolicy = ((RollingFileAppender<?>) appender).getRollingPolicy();
String fileNamePattern = ((SizeAndTimeBasedRollingPolicy) rollingPolicy).getFileNamePattern();
assertThat(fileNamePattern).endsWith("spring.log.%d{yyyy-MM-dd}.%i.gz");
}
@Test
void customRollingFileNamePattern() throws JoranException {
JoranConfigurator configurator = new JoranConfigurator();
LoggerContext context = new LoggerContext();
configurator.setContext(context);
configurator.doConfigure(new File("src/test/resources/custom-file-log-pattern-with-fileNamePattern.xml"));
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
assertThat(appender).isInstanceOf(RollingFileAppender.class);
RollingPolicy rollingPolicy = ((RollingFileAppender<?>) appender).getRollingPolicy();
String fileNamePattern = ((SizeAndTimeBasedRollingPolicy) rollingPolicy).getFileNamePattern();
assertThat(fileNamePattern).endsWith("my.log.%d{yyyyMMdd}.%i.gz");
}
}

View File

@@ -68,6 +68,7 @@ import static org.mockito.Mockito.verify;
* @author Madhura Bhave
* @author Vedran Pavic
* @author Robert Thornton
* @author Eddú Meléndez
*/
@ExtendWith(OutputCaptureExtension.class)
class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
@@ -537,6 +538,20 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
}
}
@Test
void testRollingFileNameProperty() {
MockEnvironment environment = new MockEnvironment();
String rollingFile = "my.log.%d{yyyyMMdd}.%i.gz";
environment.setProperty("logging.pattern.rolling-file-name", rollingFile);
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(environment);
File file = new File(tmpDir(), "my.log");
LogFile logFile = getLogFile(file.getPath(), null);
this.loggingSystem.initialize(loggingInitializationContext, null, logFile);
this.logger.info("Hello world");
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
assertThat(getRollingPolicy().getFileNamePattern()).isEqualTo(rollingFile);
}
private static Logger getRootLogger() {
ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
LoggerContext context = (LoggerContext) factory;

View File

@@ -0,0 +1,4 @@
<configuration>
<property name="ROLLING_FILE_NAME_PATTERN" value="my.log.%d{yyyyMMdd}.%i.gz"/>
<include resource="org/springframework/boot/logging/logback/base.xml" />
</configuration>