Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,15 @@ private void load(LoggingInitializationContext initializationContext, String loc
List<String> overrides = getOverrides(initializationContext);
Environment environment = initializationContext.getEnvironment();
Assert.state(environment != null, "'environment' must not be null");
applySystemProperties(environment, logFile);
applyLog4j2SystemProperties(environment, logFile);
loadConfiguration(location, logFile, overrides);
}


private void applyLog4j2SystemProperties(Environment environment, @Nullable LogFile logFile) {
new Log4j2LoggingSystemProperties(environment, getDefaultValueResolver(environment), null).apply(logFile);
}

private List<String> getOverrides(LoggingInitializationContext initializationContext) {
Environment environment = initializationContext.getEnvironment();
Assert.state(environment != null, "'environment' must not be null");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.logging.log4j2;

import java.util.function.BiConsumer;
import java.util.function.Function;

import org.jspecify.annotations.Nullable;

import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LoggingSystemProperties;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.util.unit.DataSize;

/**
* {@link LoggingSystemProperties} for Log4j2.
*
* @author hojooo
* @see Log4j2RollingPolicySystemProperty
*/
public class Log4j2LoggingSystemProperties extends LoggingSystemProperties {

public Log4j2LoggingSystemProperties(Environment environment) {
super(environment);
}

/**
* Create a new {@link Log4j2LoggingSystemProperties} instance.
* @param environment the source environment
* @param setter setter used to apply the property
*/
public Log4j2LoggingSystemProperties(Environment environment,
@Nullable BiConsumer<String, @Nullable String> setter) {
super(environment, setter);
}

/**
* Create a new {@link Log4j2LoggingSystemProperties} instance.
* @param environment the source environment
* @param defaultValueResolver function used to resolve default values or {@code null}
* @param setter setter used to apply the property or {@code null} for system
* properties
*/
public Log4j2LoggingSystemProperties(Environment environment,
Function<@Nullable String, @Nullable String> defaultValueResolver,
@Nullable BiConsumer<String, @Nullable String> setter) {
super(environment, defaultValueResolver, setter);
}

@Override
protected void apply(@Nullable LogFile logFile, PropertyResolver resolver) {
super.apply(logFile, resolver);
applyRollingPolicyProperties(resolver);
}

private void applyRollingPolicyProperties(PropertyResolver resolver) {
applyRollingPolicy(Log4j2RollingPolicySystemProperty.STRATEGY, resolver);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.TIME_INTERVAL, resolver, Integer.class);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.TIME_MODULATE, resolver, Boolean.class);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.CRON_SCHEDULE, resolver);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.FILE_NAME_PATTERN, resolver);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.CLEAN_HISTORY_ON_START, resolver);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.MAX_FILE_SIZE, resolver, DataSize.class);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.TOTAL_SIZE_CAP, resolver, DataSize.class);
applyRollingPolicy(Log4j2RollingPolicySystemProperty.MAX_HISTORY, resolver);
}

private void applyRollingPolicy(Log4j2RollingPolicySystemProperty property, PropertyResolver resolver) {
applyRollingPolicy(property, resolver, String.class);
}

private <T> void applyRollingPolicy(Log4j2RollingPolicySystemProperty property, PropertyResolver resolver,
Class<T> type) {
T value = getProperty(resolver, property.getApplicationPropertyName(), type);
if (value == null && property.getDeprecatedApplicationPropertyName() != null) {
value = getProperty(resolver, property.getDeprecatedApplicationPropertyName(), type);
}
if (value != null) {
String stringValue = String.valueOf((value instanceof DataSize dataSize) ? dataSize.toBytes() : value);
setSystemProperty(property.getEnvironmentVariableName(), stringValue);
}
}

@SuppressWarnings("unchecked")
private <T> @Nullable T getProperty(PropertyResolver resolver, String key, Class<T> type) {
try {
return resolver.getProperty(key, type);
}
catch (ConversionFailedException | ConverterNotFoundException ex) {
if (type != DataSize.class) {
throw ex;
}
// Fallback for Log4j2 compatibility - try parsing as string if DataSize conversion fails
String value = resolver.getProperty(key);
if (value != null) {
try {
return (T) DataSize.parse(value);
}
catch (Exception parseEx) {
ex.addSuppressed(parseEx);
throw ex;
}
}
return null;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.logging.log4j2;

import org.jspecify.annotations.Nullable;

/**
* Log4j2 rolling policy system properties that can later be used by log configuration
* files.
*
* @author hojooo
* @see Log4j2LoggingSystemProperties
*/
public enum Log4j2RollingPolicySystemProperty {

/**
* Logging system property for the rolled-over log file name pattern.
*/
FILE_NAME_PATTERN("file-name-pattern", "logging.pattern.rolling-file-name"),

/**
* Logging system property for the clean history on start flag.
*/
CLEAN_HISTORY_ON_START("clean-history-on-start", "logging.file.clean-history-on-start"),

/**
* Logging system property for the file log max size.
*/
MAX_FILE_SIZE("max-file-size", "logging.file.max-size"),

/**
* Logging system property for the file total size cap.
*/
TOTAL_SIZE_CAP("total-size-cap", "logging.file.total-size-cap"),

/**
* Logging system property for the file log max history.
*/
MAX_HISTORY("max-history", "logging.file.max-history"),

/**
* Logging system property for the rolling policy strategy.
*/
STRATEGY("strategy", null),

/**
* Logging system property for the rolling policy time interval.
*/
TIME_INTERVAL("time-based.interval", null),

/**
* Logging system property for the rolling policy time modulate flag.
*/
TIME_MODULATE("time-based.modulate", null),

/**
* Logging system property for the cron based schedule.
*/
CRON_SCHEDULE("cron.schedule", null);

private final String environmentVariableName;

private final String applicationPropertyName;

private final @Nullable String deprecatedApplicationPropertyName;

Log4j2RollingPolicySystemProperty(String applicationPropertyName, @Nullable String deprecatedApplicationPropertyName) {
this.environmentVariableName = "LOG4J2_ROLLINGPOLICY_" + name();
this.applicationPropertyName = "logging.log4j2.rollingpolicy." + applicationPropertyName;
this.deprecatedApplicationPropertyName = deprecatedApplicationPropertyName;
}

/**
* Return the name of environment variable that can be used to access this property.
* @return the environment variable name
*/
public String getEnvironmentVariableName() {
return this.environmentVariableName;
}

String getApplicationPropertyName() {
return this.applicationPropertyName;
}

@Nullable String getDeprecatedApplicationPropertyName() {
return this.deprecatedApplicationPropertyName;
}

}
Loading