Search code examples
javalogginglog4jlog4j2appender

LOG4J2 - How to create a File appender programmatically?


I need to set a File appender programmatically.

I want to set my appenders on the log4j2.xml BUT I want to write (programmatically) only to one of these appenders at runtime.

<Configuration status="WARN">
<Appenders>
    <File name="File_1" fileName="c:/FILE_1.log" >
        <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </File>
    <File name="File_2" fileName="c:/FILE_2.log" >
        <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </File>
    <File name="File_3" fileName="c:/FILE_3.log" >
        <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </File>
</Appenders>
<Loggers>
    <Root level="debug">
        <AppenderRef ref="File_1"/>
        <AppenderRef ref="File_2"/>
        <AppenderRef ref="File_3"/>
    </Root>
</Loggers>

EXAMPLE:

     if(condition.equals("A")){
             //write log on File_1
         }else if(condition.equals("B")){
              //write log on File_2
         }else {
              //write log on File_3
         }

Looking on the various tutorials in Internet they explain how to add appenders programmatically at runtime; is there a way to select at runtime only one of the appenders defined in xml configuration file?

A FIRST SOLUTION:

I've tried to solve the problem in the following way, but I am not satisfied by my solution because the files defined in the log4j2.xml are not removed programmatically AND the first Appender is never removed! I think there's a bug in log4j2: https://issues.apache.org/jira/browse/LOG4J2-135 (the Status is Solved but I don't think so...I'm using log4j-2.0-beta9)

static org.apache.logging.log4j.core.Logger coreLogger =    
(org.apache.logging.log4j.core.Logger)LogManager.getLogger(MyClass.class.getName());
static LoggerContext context = (LoggerContext)coreLogger.getContext();
static BaseConfiguration configuration = (BaseConfiguration)context.getConfiguration();

static String FILE_1 = "File_1";
static String FILE_2 = "File_2";
static String FILE_3 = "File_3";

private static Map<String, Boolean> appendersMap;
static
{
    appendersMap = new HashMap<String, Boolean>();
    appendersMap.put(FILE_1, true);
    appendersMap.put(FILE_2, true);
    appendersMap.put(FILE_3, true);
}

/**
 * Configure appenders.
 *
 * @param appender the appender
 */
public static void configureAppenders(String appender){

    if(appender.equals(FILE_1)){
        addAppenders(FILE_1);
        removeAppenders(FILE_2,FILE_3);
    }

    else if(appender.equals(FILE_3)){
        addAppenders(FILE_3);
        removeAppenders(FILE_1,FILE_2);
    }

    else if(appender.equals(FILE_2)){
        addAppenders(FILE_2);
        removeAppenders(FILE_1,FILE_3);
    }

}

private static void addAppenders(String appender){
    if (!appendersMap.get(appender)){
        appendersMap.put(appender, true);
        coreLogger.addAppender(configuration.getAppender(appender));
    }
}

private static void removeAppenders(String... appenders){
    for(String appender : appenders){
        appendersMap.put(appender, false);
        coreLogger.removeAppender(configuration.getAppender(appender));
    }
}

Solution

  • I reported the issue to the log4j2 team and they told me they will fix it soon.

    https://issues.apache.org/jira/browse/LOG4J2-468