Log4j2 adding a new plugin and appender dynamically to root

908 Views Asked by At

I have an application that dynamically (via class loaders) loads a different jar that also have a log4j2.xml configuration. The problem - the jar that I'm dynamically loading defines in the log4j2.xml file a custom appender that the application MUST use. Once my application loads the jar dynamically it ignores the log4j2.xml of the loaded jar so I need to programmatically add the missing appender myself.

The dynamically loaded jar original log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration packages="com.mytests.appenders" status="DEBUG">
   <Appenders>
      <Console name="Console" target="SYSTEM_OUT">
        <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
      </Console>
     <MyAppender name="MyAppender" />
  </Appenders>
  <Loggers>
      <Root level="DEBUG">
         <AppenderRef ref="Console"/>
         <AppenderRef ref="MyAppender" />
      </Root>
  </Loggers>

Now, since the jar I loaded needs the data stored in the custom MyAppender, I need to dynamically add the appender (and the plugin definition) since my log4j2.xml was used and not the loaded jars'.

What I'm doing - which DOESN'T work - since the rootLoggerConfig appendersRef list is not updated (and no method I saw replaces/updates it):

  import org.apache.logging.log4j.Level;
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.core.LoggerContext;
  import org.apache.logging.log4j.core.config.AppenderRef;
  import org.apache.logging.log4j.core.config.Configuration;
  import org.apache.logging.log4j.core.config.LoggerConfig;
  import org.apache.logging.log4j.core.config.plugins.util.PluginManager;


  public class LoggingConfig {

   public static void updateLogging() {

    PluginManager.addPackage("com.mytests.appenders"); // Hoped this would add the plugin

    LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    Configuration config = ctx.getConfiguration();
    MyAppender myAppender = MyAppender.createAppender("MyAppender", null);
    myAppender.start(); 
    config.addAppender(myAppender);  
    ctx.getRootLogger().addAppender(myAppender);

    LoggerConfig rootLoggerConfig = config.getLoggerConfig(""); // ctx.getRootLogger... didn't work so I tried this
    rootLoggerConfig.addAppender(myAppender, Level.ALL, null);

    AppenderRef ref = AppenderRef.createAppenderRef("MyAppender", Level.DEBUG, null);
    AppenderRef[] refs = new AppenderRef[] {ref};
    LoggerConfig loggerConfig = LoggerConfig.createLogger("false", Level.DEBUG, "MyAppender",
            "true", refs, null, config, null );
    loggerConfig.addAppender(myAppender, null, null);
    config.addLogger("MyAppender", loggerConfig);

    ctx.updateLoggers();

}

What am I missing? I simply want to add a new custom appender that was not defined in my log4j2.xml file and add it programmatically to the root logger so once added each logging message will be logged there.

Any help would be appreciated, there are not enough examples for this out there.

Note - I've looked at:

Can't add log4j2 appender dynamically and How to add Log4J2 appenders at runtime programmatically? and more examples before I posted my code. In these cases the appender was already defined in the xml file

0

There are 0 best solutions below