J Barclay
J Barclay

Reputation: 491

Log4J2 Programmatic Reconfiguration

We have implemented a custom configuration factory in order to programmatically configure Log4J2:

ConfigurationFactory.setConfigurationFactory(new MyConfigurationFactory());

The initial configuration works correctly.

We have certain listeners in our code that triggers a global 'refresh configuration' event. When this happens we need to completely reconfigure Log4J.

I have tried a number of options to tell Log4J 'reconfigure', but none of them are adequately recreating the Appenders with new configuration.

Here's the closest thing I have found, but it doesn't work for Appender config:

ConfigurationFactory.setConfigurationFactory(new MyConfigurationFactory());
LoggerContext ctx = (LoggerContext) LogManager.getContext();
ctx.reconfigure();
ctx.updateLoggers();

How can I trigger off a global reconfigure event in Log4J2 so that it will drop its entire configuration and then configure itself in full?

Edit: After further investigation and debugging, it appears that the logger configuration is not being updated either. The initial level set for the logger remains unchanged. A new instance of the immutable class org.apache.logging.log4j.core.Logger.PrivateConfig is not constructed.

Edit 2: I have managed to implement a solution that works, however the implementation is terrible and I can only assume this works by accident not by design:

        LoggerContext ctx = (LoggerContext) ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()).getContext();
        for(org.apache.logging.log4j.core.Logger l : ctx.getLoggers())
        {
            l.getContext().onChange((Reconfigurable) ctx.getConfiguration());
        }
        ctx.reconfigure();

My work is to implement a common framework to support programmatic reconfiguration, so it is important that the implementation is not brittle/flawed. I am hoping there is a correct way to reconfigure Log4J2 in full, rather than code like this that I would consider a hack.

Edit 3: Solution: As per the accepted answer below I have changed my code to the following:

        ConfigurationFactory configFactory = new MyConfigurationFactory();
        ConfigurationFactory.setConfigurationFactory(configFactory);
        org.apache.logging.log4j.core.LoggerContext ctx = (org.apache.logging.log4j.core.LoggerContext) LogManager
            .getContext(false);
        ctx.start(configFactory.getConfiguration(ConfigurationSource.NULL_SOURCE));

Upvotes: 5

Views: 5541

Answers (1)

rgoers
rgoers

Reputation: 9141

If you want a complete reconfiguration then use your configuration factory to create a new one. Then use the Configurator class to replace the configuration or call setConfiguration on the LoggerContext.

Upvotes: 2

Related Questions