Skip to content

Commit

Permalink
Allow skipping unavailable override configurations in Log4j2
Browse files Browse the repository at this point in the history
Introduced support for the 'optional:' prefix in Log4j2
override file locations, ensuring missing files are ignored without
throwing exceptions.

See spring-projectsgh-44399

Signed-off-by: Dmytro Nosan <[email protected]>
  • Loading branch information
nosan committed Feb 27, 2025
1 parent f45a3d7 commit e4d2593
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,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 @@ -85,6 +86,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 @@ -269,9 +272,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 @@ -282,8 +289,22 @@ 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 load(ResourceLoader resourceLoader, String location, LoggerContext context)
throws IOException {
Resource resource = resourceLoader.getResource(location);
return load(resource, context);
}

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()));
return (resource.exists()) ? load(resource, context) : null;
}
return load(resourceLoader, location, context);
}

private Configuration load(Resource resource, LoggerContext context) throws IOException {
ConfigurationSource source = getConfigurationSource(resource);
return ConfigurationFactory.getInstance().getConfiguration(context, source);
}
Expand Down Expand Up @@ -323,9 +344,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 loadConfigurationOptionalOverrideConfigurationWhenDoesNotExist() {
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 loadConfigurationOptionalOverrideConfigurationWhenExists() {
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

0 comments on commit e4d2593

Please sign in to comment.