Set root logger appender pattern with log4j programmatic API

Viewed 324

I'm trying to configure the pattern of the Root Logger using one of the log4j programatic api's. This is what I have, it's removing the default logger and I know that reconfigure, setLevel and setRootLevel are working, but the new ConsoleAppender isn't actually logging anything

private static void configureLog4j(Level rootLevel, Map<String, Level> levelMap) {
    var pattern = PatternLayout.newBuilder().withPattern( "%highlight{[%t] %-5level: %msg%n%throwable}\n" ).build();
    var console = ConsoleAppender.createDefaultAppenderForLayout( pattern );
    var config = LoggerContext.getContext().getConfiguration();
    config.addAppender( console );

    var root = config.getRootLogger();
    for ( var appenderRef : root.getAppenderRefs() ) {
      root.removeAppender( appenderRef.getRef() );
    }
    root.addAppender( console, rootLevel, null );
    Configurator.setRootLevel( rootLevel );
    Configurator.setLevel( levelMap );
    Configurator.reconfigure(config);
  }

I tried the other API too, same luck there. How can I fix my code?

Here's a full link to my source, sorry, I've been working on it so the line number may change.

https://github.com/xenoterracide/brix/blob/master/src/main/java/com/xenoterracide/brix/Application.java#L108

1 Answers

Update

It would appear the only way to programmatically configure log4j2 would be to create a new configuration using configuration builder. This way it will stop the default configuration and initialize with new configuration.

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
AppenderComponentBuilder appenderBuilder = builder.newAppender("console", "CONSOLE").addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute("pattern", "%highlight{[%t] %-5level: %msg%n%throwable}\n"));
builder.add(appenderBuilder);
builder.add(builder.newRootLogger(rootLevel).add(builder.newAppenderRef("console")));
levelMap.forEach((s, level) -> builder.add(builder.newLogger(s, level)));
Configurator.initialize(builder.build());

Original

Perhaps you mean to set the level and rootLevel after the logger is re-configured. The way you have is applied to the existing logger.

Configurator.reconfigure(config);
Configurator.setRootLevel( rootLevel );
Configurator.setLevel( levelMap );
Related