Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support optional: prefix with logging.log4j2.config.override #44488

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,5 @@ To configure Log4j 2 to use an alternative configuration file format, add the ap
Log4j 2 has support for combining multiple configuration files into a single composite configuration.
To use this support in Spring Boot, configure configprop:logging.log4j2.config.override[] with the locations of one or more secondary configuration files.
The secondary configuration files will be merged with the primary configuration, whether the primary's source is Spring Boot's defaults, a standard location such as `log4j.xml`, or the location configured by the configprop:logging.config[] property.

NOTE: Log4j2 override configuration file locations can be prefixed with `optional:`, for example, `optional:classpath:log4j2-override.xml`, to indicate that the location is optional and should only be loaded if the resource exists.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.springframework.boot.logging.log4j2;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
Expand Down Expand Up @@ -69,6 +70,7 @@
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
Expand All @@ -86,6 +88,8 @@
*/
public class Log4J2LoggingSystem extends AbstractLoggingSystem {

private static final String OPTIONAL_PREFIX = "optional:";

private static final String LOG4J_BRIDGE_HANDLER = "org.apache.logging.log4j.jul.Log4jBridgeHandler";

private static final String LOG4J_LOG_MANAGER = "org.apache.logging.log4j.jul.LogManager";
Expand Down Expand Up @@ -270,9 +274,13 @@ protected void loadConfiguration(String location, LogFile logFile, List<String>
try {
List<Configuration> configurations = new ArrayList<>();
LoggerContext context = getLoggerContext();
configurations.add(load(location, context));
ResourceLoader resourceLoader = ApplicationResourceLoader.get();
configurations.add(load(resourceLoader, location, context));
for (String override : overrides) {
configurations.add(load(override, context));
Configuration overrideConfiguration = loadOptional(resourceLoader, override, context);
if (overrideConfiguration != null) {
configurations.add(overrideConfiguration);
}
}
Configuration configuration = (configurations.size() > 1) ? createComposite(configurations)
: configurations.iterator().next();
Expand All @@ -283,8 +291,27 @@ protected void loadConfiguration(String location, LogFile logFile, List<String>
}
}

private Configuration load(String location, LoggerContext context) throws IOException {
Resource resource = ApplicationResourceLoader.get().getResource(location);
private Configuration loadOptional(ResourceLoader resourceLoader, String location, LoggerContext context)
throws IOException {
if (location.startsWith(OPTIONAL_PREFIX)) {
Resource resource = resourceLoader.getResource(location.substring(OPTIONAL_PREFIX.length()));
try {
return (resource.exists()) ? load(resource, context) : null;
}
catch (FileNotFoundException ex) {
return null;
}
}
return load(resourceLoader, location, context);
}

private Configuration load(ResourceLoader resourceLoader, String location, LoggerContext context)
throws IOException {
Resource resource = resourceLoader.getResource(location);
return load(resource, context);
}

private Configuration load(Resource resource, LoggerContext context) throws IOException {
ConfigurationFactory factory = ConfigurationFactory.getInstance();
if (resource.isFile()) {
try (InputStream inputStream = resource.getInputStream()) {
Expand Down Expand Up @@ -325,9 +352,13 @@ private void reinitializeWithOverrides(List<String> overrides) {
Configuration base = context.getConfiguration();
List<AbstractConfiguration> configurations = new ArrayList<>();
configurations.add((AbstractConfiguration) base);
ResourceLoader resourceLoader = ApplicationResourceLoader.get();
for (String override : overrides) {
try {
configurations.add((AbstractConfiguration) load(override, context));
Configuration overrideConfiguration = loadOptional(resourceLoader, override, context);
if (overrideConfiguration != null) {
configurations.add((AbstractConfiguration) overrideConfiguration);
}
}
catch (IOException ex) {
throw new RuntimeException("Failed to load overriding configuration from '" + override + "'", ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.apache.logging.log4j.core.config.Reconfigurable;
import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
import org.apache.logging.log4j.core.config.plugins.util.PluginRegistry;
import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
import org.apache.logging.log4j.jul.Log4jBridgeHandler;
import org.apache.logging.log4j.status.StatusListener;
Expand Down Expand Up @@ -453,6 +454,23 @@ void shutdownHookIsDisabled() {
.isFalse();
}

@Test
@WithNonDefaultXmlResource
void loadOptionalOverrideConfigurationWhenDoesNotExist() {
this.environment.setProperty("logging.log4j2.config.override", "optional:classpath:override.xml");
this.loggingSystem.initialize(this.initializationContext, "classpath:nondefault.xml", null);
assertThat(this.loggingSystem.getConfiguration()).isInstanceOf(XmlConfiguration.class);
}

@Test
@WithNonDefaultXmlResource
@WithOverrideXmlResource
void loadOptionalOverrideConfigurationWhenExists() {
this.environment.setProperty("logging.log4j2.config.override", "optional:classpath:override.xml");
this.loggingSystem.initialize(this.initializationContext, "classpath:nondefault.xml", null);
assertThat(this.loggingSystem.getConfiguration()).isInstanceOf(CompositeConfiguration.class);
}

@Test
@WithNonDefaultXmlResource
@WithOverrideXmlResource
Expand Down
Loading