Skip to content

Commit ab9833b

Browse files
committed
Polish "Add support for Log4j2 rolling policy configuration"
See spring-projectsgh-47260
1 parent 946ede7 commit ab9833b

File tree

10 files changed

+128
-164
lines changed

10 files changed

+128
-164
lines changed

core/spring-boot/src/main/java/org/springframework/boot/logging/AbstractLoggingSystem.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import org.jspecify.annotations.Nullable;
2828

29-
import org.springframework.core.env.ConfigurableEnvironment;
3029
import org.springframework.core.env.Environment;
3130
import org.springframework.core.io.ClassPathResource;
3231
import org.springframework.util.Assert;
@@ -181,10 +180,7 @@ protected final String getPackagedConfigFile(String fileName) {
181180
}
182181

183182
protected final void applySystemProperties(Environment environment, @Nullable LogFile logFile) {
184-
LoggingSystemProperties systemProperties = (environment instanceof ConfigurableEnvironment configurableEnvironment)
185-
? getSystemProperties(configurableEnvironment)
186-
: new LoggingSystemProperties(environment, getDefaultValueResolver(environment), null);
187-
systemProperties.apply(logFile);
183+
new LoggingSystemProperties(environment, getDefaultValueResolver(environment), null).apply(logFile);
188184
}
189185

190186
/**

core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4j2LoggingSystemProperties.java

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,15 @@
3333
* {@link LoggingSystemProperties} for Log4j2.
3434
*
3535
* @author HoJoo Moon
36-
* @since 4.0.0
37-
* @see Log4j2RollingPolicySystemProperty
36+
* @since 4.1.0
37+
* @see RollingPolicySystemProperty
3838
*/
3939
public class Log4j2LoggingSystemProperties extends LoggingSystemProperties {
4040

4141
public Log4j2LoggingSystemProperties(Environment environment) {
4242
super(environment);
4343
}
4444

45-
/**
46-
* Create a new {@link Log4j2LoggingSystemProperties} instance.
47-
* @param environment the source environment
48-
* @param setter setter used to apply the property
49-
*/
50-
public Log4j2LoggingSystemProperties(Environment environment,
51-
@Nullable BiConsumer<String, @Nullable String> setter) {
52-
super(environment, setter);
53-
}
54-
5545
/**
5646
* Create a new {@link Log4j2LoggingSystemProperties} instance.
5747
* @param environment the source environment
@@ -72,25 +62,22 @@ protected void apply(@Nullable LogFile logFile, PropertyResolver resolver) {
7262
}
7363

7464
private void applyRollingPolicyProperties(PropertyResolver resolver) {
75-
applyRollingPolicy(Log4j2RollingPolicySystemProperty.STRATEGY, resolver);
76-
applyRollingPolicy(Log4j2RollingPolicySystemProperty.TIME_INTERVAL, resolver, Integer.class);
77-
applyRollingPolicy(Log4j2RollingPolicySystemProperty.TIME_MODULATE, resolver, Boolean.class);
78-
applyRollingPolicy(Log4j2RollingPolicySystemProperty.CRON_SCHEDULE, resolver);
79-
applyRollingPolicy(Log4j2RollingPolicySystemProperty.FILE_NAME_PATTERN, resolver);
80-
applyRollingPolicy(Log4j2RollingPolicySystemProperty.MAX_FILE_SIZE, resolver, DataSize.class);
81-
applyRollingPolicy(Log4j2RollingPolicySystemProperty.MAX_HISTORY, resolver);
65+
applyRollingPolicy(RollingPolicySystemProperty.FILE_NAME_PATTERN, resolver);
66+
applyRollingPolicy(RollingPolicySystemProperty.MAX_FILE_SIZE, resolver, DataSize.class);
67+
applyRollingPolicy(RollingPolicySystemProperty.MAX_HISTORY, resolver);
68+
applyRollingPolicy(RollingPolicySystemProperty.STRATEGY, resolver);
69+
applyRollingPolicy(RollingPolicySystemProperty.TIME_INTERVAL, resolver, Integer.class);
70+
applyRollingPolicy(RollingPolicySystemProperty.TIME_MODULATE, resolver, Boolean.class);
71+
applyRollingPolicy(RollingPolicySystemProperty.CRON_SCHEDULE, resolver);
8272
}
8373

84-
private void applyRollingPolicy(Log4j2RollingPolicySystemProperty property, PropertyResolver resolver) {
74+
private void applyRollingPolicy(RollingPolicySystemProperty property, PropertyResolver resolver) {
8575
applyRollingPolicy(property, resolver, String.class);
8676
}
8777

88-
private <T> void applyRollingPolicy(Log4j2RollingPolicySystemProperty property, PropertyResolver resolver,
78+
private <T> void applyRollingPolicy(RollingPolicySystemProperty property, PropertyResolver resolver,
8979
Class<T> type) {
9080
T value = getProperty(resolver, property.getApplicationPropertyName(), type);
91-
if (value == null && property.getDeprecatedApplicationPropertyName() != null) {
92-
value = getProperty(resolver, property.getDeprecatedApplicationPropertyName(), type);
93-
}
9481
if (value != null) {
9582
String stringValue = String.valueOf((value instanceof DataSize dataSize) ? dataSize.toBytes() : value);
9683
setSystemProperty(property.getEnvironmentVariableName(), stringValue);
@@ -106,19 +93,8 @@ private <T> void applyRollingPolicy(Log4j2RollingPolicySystemProperty property,
10693
if (type != DataSize.class) {
10794
throw ex;
10895
}
109-
// Fallback for Log4j2 compatibility - try parsing as string if DataSize
110-
// conversion fails
11196
String value = resolver.getProperty(key);
112-
if (value != null) {
113-
try {
114-
return (T) DataSize.parse(value);
115-
}
116-
catch (Exception parseEx) {
117-
ex.addSuppressed(parseEx);
118-
throw ex;
119-
}
120-
}
121-
return null;
97+
return (value != null) ? (T) DataSize.parse(value) : null;
12298
}
12399
}
124100

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.logging.log4j2;
18+
19+
/**
20+
* Available rolling policy strategies.
21+
*
22+
* @author Stephane Nicoll
23+
* @since 4.1.0
24+
*/
25+
public enum RollingPolicyStrategy {
26+
27+
/**
28+
* Roll a file over based on its size.
29+
*/
30+
SIZE,
31+
32+
/**
33+
* Roll a file over based on time.
34+
*/
35+
TIME,
36+
37+
/**
38+
* Roll a file over based on its size and time.
39+
*/
40+
SIZE_AND_TIME,
41+
42+
/**
43+
* Roll a file over based on its size.
44+
*/
45+
CRON
46+
47+
}

core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4j2RollingPolicySystemProperty.java renamed to core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/RollingPolicySystemProperty.java

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,64 +16,59 @@
1616

1717
package org.springframework.boot.logging.log4j2;
1818

19-
import org.jspecify.annotations.Nullable;
20-
2119
/**
2220
* Log4j2 rolling policy system properties that can later be used by log configuration
2321
* files.
2422
*
2523
* @author HoJoo Moon
26-
* @since 4.0.0
24+
* @since 4.1.0
2725
* @see Log4j2LoggingSystemProperties
2826
*/
29-
public enum Log4j2RollingPolicySystemProperty {
27+
public enum RollingPolicySystemProperty {
3028

3129
/**
3230
* Logging system property for the rolled-over log file name pattern.
3331
*/
34-
FILE_NAME_PATTERN("file-name-pattern", "logging.pattern.rolling-file-name"),
32+
FILE_NAME_PATTERN("file-name-pattern"),
3533

3634
/**
3735
* Logging system property for the file log max size.
3836
*/
39-
MAX_FILE_SIZE("max-file-size", "logging.file.max-size"),
37+
MAX_FILE_SIZE("max-file-size"),
4038

4139
/**
4240
* Logging system property for the file log max history.
4341
*/
44-
MAX_HISTORY("max-history", "logging.file.max-history"),
42+
MAX_HISTORY("max-history"),
4543

4644
/**
47-
* Logging system property for the rolling policy strategy.
45+
* Logging system property for the {@linkplain RollingPolicyStrategy rolling policy
46+
* strategy}.
4847
*/
49-
STRATEGY("strategy", null),
48+
STRATEGY("strategy"),
5049

5150
/**
5251
* Logging system property for the rolling policy time interval.
5352
*/
54-
TIME_INTERVAL("time-based.interval", null),
53+
TIME_INTERVAL("time-based.interval"),
5554

5655
/**
5756
* Logging system property for the rolling policy time modulate flag.
5857
*/
59-
TIME_MODULATE("time-based.modulate", null),
58+
TIME_MODULATE("time-based.modulate"),
6059

6160
/**
6261
* Logging system property for the cron based schedule.
6362
*/
64-
CRON_SCHEDULE("cron.schedule", null);
63+
CRON_SCHEDULE("cron.schedule");
6564

6665
private final String environmentVariableName;
6766

6867
private final String applicationPropertyName;
6968

70-
private final @Nullable String deprecatedApplicationPropertyName;
71-
72-
Log4j2RollingPolicySystemProperty(String applicationPropertyName,
73-
@Nullable String deprecatedApplicationPropertyName) {
69+
RollingPolicySystemProperty(String applicationPropertyName) {
7470
this.environmentVariableName = "LOG4J2_ROLLINGPOLICY_" + name();
7571
this.applicationPropertyName = "logging.log4j2.rollingpolicy." + applicationPropertyName;
76-
this.deprecatedApplicationPropertyName = deprecatedApplicationPropertyName;
7772
}
7873

7974
/**
@@ -88,8 +83,4 @@ String getApplicationPropertyName() {
8883
return this.applicationPropertyName;
8984
}
9085

91-
@Nullable String getDeprecatedApplicationPropertyName() {
92-
return this.deprecatedApplicationPropertyName;
93-
}
94-
9586
}

core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/SpringBootTriggeringPolicy.java

Lines changed: 35 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.boot.logging.log4j2;
1818

19+
import java.util.Objects;
20+
1921
import org.apache.logging.log4j.core.LogEvent;
2022
import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
2123
import org.apache.logging.log4j.core.appender.rolling.CronTriggeringPolicy;
@@ -32,6 +34,8 @@
3234
import org.apache.logging.log4j.core.util.Builder;
3335
import org.jspecify.annotations.Nullable;
3436

37+
import org.springframework.boot.convert.ApplicationConversionService;
38+
import org.springframework.core.convert.ConversionException;
3539
import org.springframework.util.Assert;
3640

3741
/**
@@ -40,7 +44,8 @@
4044
* {@code size-and-time}, and {@code cron}.
4145
*
4246
* @author HoJoo Moon
43-
* @since 4.0.0
47+
* @author Stephane Nicoll
48+
* @since 4.1.0
4449
*/
4550
@Plugin(name = "SpringBootTriggeringPolicy", category = Node.CATEGORY, elementType = "TriggeringPolicy",
4651
deferChildren = true, printObject = true)
@@ -51,12 +56,12 @@ private SpringBootTriggeringPolicy() {
5156

5257
@Override
5358
public void initialize(RollingFileManager manager) {
54-
throw new UnsupportedOperationException("This class should not be instantiated");
59+
throw new UnsupportedOperationException();
5560
}
5661

5762
@Override
5863
public boolean isTriggeringEvent(LogEvent logEvent) {
59-
throw new UnsupportedOperationException("This class should not be instantiated");
64+
throw new UnsupportedOperationException();
6065
}
6166

6267
@PluginBuilderFactory
@@ -73,7 +78,7 @@ public static class SpringBootTriggeringPolicyBuilder implements Builder<Trigger
7378

7479
private static final String DEFAULT_MAX_FILE_SIZE = "10MB";
7580

76-
private static final int DEFAULT_TIME_INTERVAL = 1;
81+
private static final String DEFAULT_TIME_INTERVAL = "1";
7782

7883
private static final String DEFAULT_CRON_EXPRESSION = "0 0 0 * * ?";
7984

@@ -97,79 +102,51 @@ public static class SpringBootTriggeringPolicyBuilder implements Builder<Trigger
97102

98103
@Override
99104
public TriggeringPolicy build() {
100-
// Read strategy from system properties first, then from attributes
101-
String resolvedStrategy = System.getProperty("LOG4J2_ROLLINGPOLICY_STRATEGY");
102-
if (resolvedStrategy == null) {
103-
resolvedStrategy = (this.strategy != null) ? this.strategy : DEFAULT_STRATEGY;
104-
}
105+
RollingPolicyStrategy resolvedStrategy = getRollingPolicyStrategy();
105106
return switch (resolvedStrategy) {
106-
case "time" -> createTimePolicy();
107-
case "size-and-time" -> CompositeTriggeringPolicy.createPolicy(createSizePolicy(), createTimePolicy());
108-
case "cron" -> createCronPolicy();
109-
case "size" -> createSizePolicy();
110-
default -> throw new IllegalArgumentException(
111-
"Unsupported rolling policy strategy '%s'".formatted(resolvedStrategy));
107+
case TIME -> createTimePolicy();
108+
case SIZE_AND_TIME -> CompositeTriggeringPolicy.createPolicy(createSizePolicy(), createTimePolicy());
109+
case CRON -> createCronPolicy();
110+
case SIZE -> createSizePolicy();
112111
};
113112
}
114113

115-
private TriggeringPolicy createSizePolicy() {
116-
// Read from system properties first, then from attributes
117-
String size = System.getProperty("LOG4J2_ROLLINGPOLICY_MAX_FILE_SIZE");
118-
if (size == null) {
119-
size = (this.maxFileSize != null) ? this.maxFileSize : DEFAULT_MAX_FILE_SIZE;
114+
private static RollingPolicyStrategy getRollingPolicyStrategy() {
115+
String resolvedStrategy = getSystemProperty(RollingPolicySystemProperty.STRATEGY, DEFAULT_STRATEGY);
116+
try {
117+
return Objects.requireNonNull(ApplicationConversionService.getSharedInstance()
118+
.convert(resolvedStrategy, RollingPolicyStrategy.class));
120119
}
120+
catch (ConversionException ex) {
121+
throw new IllegalArgumentException(
122+
"Unsupported rolling policy strategy '%s'".formatted(resolvedStrategy));
123+
}
124+
}
125+
126+
private TriggeringPolicy createSizePolicy() {
127+
String size = getSystemProperty(RollingPolicySystemProperty.MAX_FILE_SIZE, DEFAULT_MAX_FILE_SIZE);
121128
return SizeBasedTriggeringPolicy.createPolicy(size);
122129
}
123130

124131
private TriggeringPolicy createTimePolicy() {
125-
// Read from system properties first, then from attributes
126-
String intervalStr = System.getProperty("LOG4J2_ROLLINGPOLICY_TIME_INTERVAL");
127-
int interval = (intervalStr != null) ? Integer.parseInt(intervalStr)
128-
: (this.timeInterval != null) ? this.timeInterval : DEFAULT_TIME_INTERVAL;
129-
130-
String modulateStr = System.getProperty("LOG4J2_ROLLINGPOLICY_TIME_MODULATE");
131-
boolean modulate = (modulateStr != null) ? Boolean.parseBoolean(modulateStr)
132-
: (this.timeModulate != null) ? this.timeModulate : false;
133-
132+
int interval = Integer
133+
.parseInt(getSystemProperty(RollingPolicySystemProperty.TIME_INTERVAL, DEFAULT_TIME_INTERVAL));
134+
boolean modulate = Boolean
135+
.parseBoolean(getSystemProperty(RollingPolicySystemProperty.TIME_MODULATE, Boolean.FALSE.toString()));
134136
return TimeBasedTriggeringPolicy.newBuilder().withInterval(interval).withModulate(modulate).build();
135137
}
136138

137139
private TriggeringPolicy createCronPolicy() {
138140
Assert.notNull(this.configuration, "configuration must not be null");
139141
Configuration configuration = this.configuration;
140142

141-
// Read from system properties first, then from attributes
142-
String schedule = System.getProperty("LOG4J2_ROLLINGPOLICY_CRON_SCHEDULE");
143-
if (schedule == null) {
144-
schedule = (this.cronExpression != null) ? this.cronExpression : DEFAULT_CRON_EXPRESSION;
145-
}
146-
143+
String schedule = getSystemProperty(RollingPolicySystemProperty.CRON_SCHEDULE, DEFAULT_CRON_EXPRESSION);
147144
return CronTriggeringPolicy.createPolicy(configuration, null, schedule);
148145
}
149146

150-
SpringBootTriggeringPolicyBuilder setStrategy(@Nullable String strategy) {
151-
this.strategy = strategy;
152-
return this;
153-
}
154-
155-
SpringBootTriggeringPolicyBuilder setMaxFileSize(@Nullable String maxFileSize) {
156-
this.maxFileSize = maxFileSize;
157-
return this;
158-
}
159-
160-
SpringBootTriggeringPolicyBuilder setTimeInterval(@Nullable Integer timeInterval) {
161-
this.timeInterval = timeInterval;
162-
return this;
163-
}
164-
165-
SpringBootTriggeringPolicyBuilder setTimeModulate(@Nullable Boolean timeModulate) {
166-
this.timeModulate = timeModulate;
167-
return this;
168-
}
169-
170-
SpringBootTriggeringPolicyBuilder setCronExpression(@Nullable String cronExpression) {
171-
this.cronExpression = cronExpression;
172-
return this;
147+
private static String getSystemProperty(RollingPolicySystemProperty property, String fallback) {
148+
String value = System.getProperty(property.getEnvironmentVariableName());
149+
return (value != null) ? value : fallback;
173150
}
174151

175152
SpringBootTriggeringPolicyBuilder setConfiguration(Configuration configuration) {

0 commit comments

Comments
 (0)