Skip to content

Commit bcc2bbe

Browse files
hojooosnicoll
authored andcommitted
Add support for Log4j2 rolling policy configuration
See spring-projectsgh-47260 Signed-off-by: hojooo <ghwn5833@gmail.com>
1 parent 192efca commit bcc2bbe

File tree

10 files changed

+731
-34
lines changed

10 files changed

+731
-34
lines changed

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

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

2727
import org.jspecify.annotations.Nullable;
2828

29+
import org.springframework.core.env.ConfigurableEnvironment;
2930
import org.springframework.core.env.Environment;
3031
import org.springframework.core.io.ClassPathResource;
3132
import org.springframework.util.Assert;
@@ -180,7 +181,10 @@ protected final String getPackagedConfigFile(String fileName) {
180181
}
181182

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

186190
/**

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@
5858
import org.springframework.boot.logging.LoggingInitializationContext;
5959
import org.springframework.boot.logging.LoggingSystem;
6060
import org.springframework.boot.logging.LoggingSystemFactory;
61+
import org.springframework.boot.logging.LoggingSystemProperties;
6162
import org.springframework.core.Conventions;
6263
import org.springframework.core.annotation.Order;
64+
import org.springframework.core.env.ConfigurableEnvironment;
6365
import org.springframework.core.env.Environment;
6466
import org.springframework.core.io.Resource;
6567
import org.springframework.core.io.ResourceLoader;
@@ -128,6 +130,11 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem {
128130
this.loggerContext = loggerContext;
129131
}
130132

133+
@Override
134+
public LoggingSystemProperties getSystemProperties(ConfigurableEnvironment environment) {
135+
return new Log4j2LoggingSystemProperties(environment, getDefaultValueResolver(environment), null);
136+
}
137+
131138
@Override
132139
protected String[] getStandardConfigLocations() {
133140
// With Log4J2 we use the ConfigurationFactory
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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+
import java.util.function.BiConsumer;
20+
import java.util.function.Function;
21+
22+
import org.jspecify.annotations.Nullable;
23+
24+
import org.springframework.boot.logging.LogFile;
25+
import org.springframework.boot.logging.LoggingSystemProperties;
26+
import org.springframework.core.convert.ConversionFailedException;
27+
import org.springframework.core.convert.ConverterNotFoundException;
28+
import org.springframework.core.env.Environment;
29+
import org.springframework.core.env.PropertyResolver;
30+
import org.springframework.util.unit.DataSize;
31+
32+
/**
33+
* {@link LoggingSystemProperties} for Log4j2.
34+
*
35+
* @author HoJoo Moon
36+
* @since 4.0.0
37+
* @see Log4j2RollingPolicySystemProperty
38+
*/
39+
public class Log4j2LoggingSystemProperties extends LoggingSystemProperties {
40+
41+
public Log4j2LoggingSystemProperties(Environment environment) {
42+
super(environment);
43+
}
44+
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+
55+
/**
56+
* Create a new {@link Log4j2LoggingSystemProperties} instance.
57+
* @param environment the source environment
58+
* @param defaultValueResolver function used to resolve default values or {@code null}
59+
* @param setter setter used to apply the property or {@code null} for system
60+
* properties
61+
*/
62+
public Log4j2LoggingSystemProperties(Environment environment,
63+
Function<@Nullable String, @Nullable String> defaultValueResolver,
64+
@Nullable BiConsumer<String, @Nullable String> setter) {
65+
super(environment, defaultValueResolver, setter);
66+
}
67+
68+
@Override
69+
protected void apply(@Nullable LogFile logFile, PropertyResolver resolver) {
70+
super.apply(logFile, resolver);
71+
applyRollingPolicyProperties(resolver);
72+
}
73+
74+
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);
82+
}
83+
84+
private void applyRollingPolicy(Log4j2RollingPolicySystemProperty property, PropertyResolver resolver) {
85+
applyRollingPolicy(property, resolver, String.class);
86+
}
87+
88+
private <T> void applyRollingPolicy(Log4j2RollingPolicySystemProperty property, PropertyResolver resolver,
89+
Class<T> type) {
90+
T value = getProperty(resolver, property.getApplicationPropertyName(), type);
91+
if (value == null && property.getDeprecatedApplicationPropertyName() != null) {
92+
value = getProperty(resolver, property.getDeprecatedApplicationPropertyName(), type);
93+
}
94+
if (value != null) {
95+
String stringValue = String.valueOf((value instanceof DataSize dataSize) ? dataSize.toBytes() : value);
96+
setSystemProperty(property.getEnvironmentVariableName(), stringValue);
97+
}
98+
}
99+
100+
@SuppressWarnings("unchecked")
101+
private <T> @Nullable T getProperty(PropertyResolver resolver, String key, Class<T> type) {
102+
try {
103+
return resolver.getProperty(key, type);
104+
}
105+
catch (ConversionFailedException | ConverterNotFoundException ex) {
106+
if (type != DataSize.class) {
107+
throw ex;
108+
}
109+
// Fallback for Log4j2 compatibility - try parsing as string if DataSize
110+
// conversion fails
111+
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;
122+
}
123+
}
124+
125+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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+
import org.jspecify.annotations.Nullable;
20+
21+
/**
22+
* Log4j2 rolling policy system properties that can later be used by log configuration
23+
* files.
24+
*
25+
* @author HoJoo Moon
26+
* @since 4.0.0
27+
* @see Log4j2LoggingSystemProperties
28+
*/
29+
public enum Log4j2RollingPolicySystemProperty {
30+
31+
/**
32+
* Logging system property for the rolled-over log file name pattern.
33+
*/
34+
FILE_NAME_PATTERN("file-name-pattern", "logging.pattern.rolling-file-name"),
35+
36+
/**
37+
* Logging system property for the file log max size.
38+
*/
39+
MAX_FILE_SIZE("max-file-size", "logging.file.max-size"),
40+
41+
/**
42+
* Logging system property for the file log max history.
43+
*/
44+
MAX_HISTORY("max-history", "logging.file.max-history"),
45+
46+
/**
47+
* Logging system property for the rolling policy strategy.
48+
*/
49+
STRATEGY("strategy", null),
50+
51+
/**
52+
* Logging system property for the rolling policy time interval.
53+
*/
54+
TIME_INTERVAL("time-based.interval", null),
55+
56+
/**
57+
* Logging system property for the rolling policy time modulate flag.
58+
*/
59+
TIME_MODULATE("time-based.modulate", null),
60+
61+
/**
62+
* Logging system property for the cron based schedule.
63+
*/
64+
CRON_SCHEDULE("cron.schedule", null);
65+
66+
private final String environmentVariableName;
67+
68+
private final String applicationPropertyName;
69+
70+
private final @Nullable String deprecatedApplicationPropertyName;
71+
72+
Log4j2RollingPolicySystemProperty(String applicationPropertyName,
73+
@Nullable String deprecatedApplicationPropertyName) {
74+
this.environmentVariableName = "LOG4J2_ROLLINGPOLICY_" + name();
75+
this.applicationPropertyName = "logging.log4j2.rollingpolicy." + applicationPropertyName;
76+
this.deprecatedApplicationPropertyName = deprecatedApplicationPropertyName;
77+
}
78+
79+
/**
80+
* Return the name of environment variable that can be used to access this property.
81+
* @return the environment variable name
82+
*/
83+
public String getEnvironmentVariableName() {
84+
return this.environmentVariableName;
85+
}
86+
87+
String getApplicationPropertyName() {
88+
return this.applicationPropertyName;
89+
}
90+
91+
@Nullable String getDeprecatedApplicationPropertyName() {
92+
return this.deprecatedApplicationPropertyName;
93+
}
94+
95+
}

0 commit comments

Comments
 (0)