How to configure log4j 2.x purely programmatically?

PM 77-1 picture PM 77-1 · Jun 17, 2015 · Viewed 24.7k times · Source

How do I configure log4j 2.3 with console appender pure programmatically (no configuration files of any format)?

Basically I'm looking for 2.x version of this 1.x code.

In my classes I would then use

private static final Logger logger = LogManager.getLogger();
// 
    // some method
       logger.debug(someString);

Without any configuration I'm (as expected) facing

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.

While usage of configuration files seems to be properly documented, I couldn't find a good example of a bare-bone code-only case.

The closest I got is this article that still uses a dummy file.

Here's my best (though completely unsuccessful) shot:

private static void configureLog4J() {
    PatternLayout layout = PatternLayout.createDefaultLayout();
    ConsoleAppender appender = ConsoleAppender.createDefaultAppenderForLayout(layout);
    LoggerConfig loggerConfig = new LoggerConfig();
    loggerConfig.addAppender(appender, DEBUG, null);
}

Have I missed something?

If it's still a RTFM case, please point me into the right direction.

Answer

alan7678 picture alan7678 · Jun 23, 2015
package com;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
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.layout.PatternLayout;

import java.nio.charset.Charset;

public class MyLoggerTest  {

    public static void main(String[] args){
        LoggerContext context= (LoggerContext) LogManager.getContext();
        Configuration config= context.getConfiguration();

        PatternLayout layout= PatternLayout.createLayout("%m%n", null, null, Charset.defaultCharset(),false,false,null,null);
        Appender appender=ConsoleAppender.createAppender(layout, null, null, "CONSOLE_APPENDER", null, null);
        appender.start();
        AppenderRef ref= AppenderRef.createAppenderRef("CONSOLE_APPENDER",null,null);
        AppenderRef[] refs = new AppenderRef[] {ref};
        LoggerConfig loggerConfig= LoggerConfig.createLogger("false", Level.INFO,"CONSOLE_LOGGER","com",refs,null,null,null);
        loggerConfig.addAppender(appender,null,null);

        config.addAppender(appender);
        config.addLogger("com", loggerConfig);
        context.updateLoggers(config);

        Logger logger=LogManager.getContext().getLogger("com");
        logger.info("HELLO_WORLD");


    }
}

Not sure if this is what you are looking for. This creates a default configuration and adds a console logger. However, LogManager.getLogger() does not work and using the LogManager.getContext().getLogger() does not allow for logger hierarchy. Honestly i don't recommend the programmatic approach, Log4j2 is allergic to it.