0
votes

I'm using log4j2.

I want to create a RollingFileAppender which rotates the log file on a daily basis. The name of the logfile is unknown until the application has started (the logfile name is assembled from the application config).

That is why I need to add a RollingFileAppender at runtime.

I have the following code:

public static final ConfigurationBuilder<BuiltConfiguration> BUILDER = ConfigurationBuilderFactory.newConfigurationBuilder

public void initFileLoggerWithFilePattern(final String pattern) {
   final LoggerComponentBuilder   logger   = BUILDER.newLogger("FileLogger", Level.DEBUG);
   final AppenderComponentBuilder appender = createFileAppenderWithFilePattern(pattern);

   BUILDER.add(appender);

   logger.add(BUILDER.newAppenderRef("RollingFileAppender"));

   BUILDER.add(logger);

   Configurator.initialize(BUILDER.build());
}

public AppenderComponentBuilder createFileAppenderWithFilePattern(final String pattern) {
   final AppenderComponentBuilder acb = BUILDER.newAppender("RollingFileAppender", "RollingFile");
   acb.addAttribute("fileName",    pattern); 
   acb.addAttribute("filePattern", pattern);
   acb.addComponent(createPatternLayout());
   acb.addComponent(createTimeBasedTriggeringPolicy());

   return acb;
}

public LayoutComponentBuilder createPatternLayout() {
   final LayoutComponentBuilder lcb = BUILDER.newLayout("PatternLayout");
   lcb.addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss.SSS}{GMT}Z %m");

   return lcb;
}

public ComponentBuilder createTimeBasedTriggeringPolicy() {
   final ComponentBuilder policies = BUILDER.newComponent("Policies");
   final ComponentBuilder policy   = BUILDER.newComponent("TimeBasedTriggeringPolicy");

   policies.addComponent(policy);

   return policies;  
}

The problem is that this code changes absolutely nothing. No appender as well as no Logger is being added to the configuration. The "FileLogger" that was created programmatically is not available.

I used this code to print the loggers and Appenders after executing the code above.


private void printLog4jConfig() {
   final LoggerContext context = (LoggerContext) LogManager.getContext(false);
   final Configuration config  = context.getConfiguration();


   // Print appenders
   for(Appender app : config.getAppenders().values()) {
      System.out.println(app.getName());
   }

   // Print Loggers and their Appenders
   for(LoggerConfig lc : config.getLoggers().values()) {
      System.out.println(lc);

      for(Appender app : lc.getAppenders().values()) {
         System.out.println("   " + app);
      }
   }
}

Output:

Appenders
-------------
STDOUT


Loggers
-------------
root
   STDOUT
Console
   STDOUT

My Question:

What is wrong with my code? Why is my Appender as well as my Logger not added? Respectively why is the configuration not being refreshed / updated ?

How can I add a RollingFileAppender as well as a logger to the log4j2 configuration during runtime?

1
How would you capture application startup failures if the logger doesn't log until it successfully starts up?user872858
@user872858 Before the application really starts processing it logs to the console. Everything like invalid parameters etc. It reads it's configuration and (if successful) instantiates the logger mentioned above. Then it starts processing. So the application does not process anything until the logger has been instantiated. Everything before that point is just user feedback about the parameter he's given and if the configuration file is correct.Sirop

1 Answers

0
votes

I found the solution to my problem.

Instead using

Configurator.initialize(BUILDER.build())

I had to use

Configurator.reconfigure(BUILDER.build());

This reloaded the configuration and i was able to see and use my appender and logger.