Log4J2 - assigning file appender filename at runtime

h/t rgoers The FileAppender doesn't support two dollar signs on the file name as the file is opened when the appender is started. What you are indicating with two dollar signs is that you want - potentially - a different file name for each event.

With a single $ (as in ${sys:logFilename}), the system will look for property "logFilename" in the system properties.

Thus, the log4j2.xml should have:

<appenders>
    <File name="MyFile" fileName="${sys:logFilename}">
        <PatternLayout pattern="%-4r %d{${datestamp}} [%t] %-5level %logger{36} - %msg%n"/>
    </File>
</appenders>

The Java application should set the system property:

System.setProperty("logFilename", filename);

and reconfigure the logger:

org.apache.logging.log4j.core.LoggerContext ctx =
    (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
ctx.reconfigure();

This produces the desired behavior.


What you can do is, when running the application, pass logFilename as an argument to the JVM:

java -DlogFilename=myAppName.log -jar /path/to/myApp.jar

As of log4j2 version 2.5 here is the simplest way to achieve this:

In your log4j2.xml:

<Appenders>
   <File name="MyFile" filename="${sys:logFilename}">
   ...

In you main MyApp.java file:

public class MyApp {

    Logger log;

    static {
          System.setProperty("logFilename", ...);
          log = LogManager.getLogger();
    }

    public static void main(String... args) {...}
}

CATCH: You should set logFilename system property before log4j2 is loaded. In this example before calling LogManager.getLogger.


I know this topic is old, but the answers did not really suit me. Here is a function which allows you to reconfigure an existing Appender at runtime:

static void updateLogger(String file_name, String appender_name, String package_name){
LoggerContext context = (LoggerContext) LogManager.getContext(false);
    Configuration configuration = context.getConfiguration();
    Layout<? extends Serializable> old_layout = configuration.getAppender(appender_name).getLayout();

    //delete old appender/logger
    configuration.getAppender(appender_name).stop();
    configuration.removeLogger(package_name);

    //create new appender/logger
    LoggerConfig loggerConfig = new LoggerConfig(package_name, Level.INFO, false);
    FileAppender appender = FileAppender.createAppender(file_name, "false", "false", appender_name, "true", "true", "true",
            "8192", old_layout, null, "false", "", configuration);
    appender.start();
    loggerConfig.addAppender(appender, Level.INFO, null);
    configuration.addLogger(package_name, loggerConfig);

    context.updateLoggers();
}

You can specify a file name, the name of your appender and the package name which you want to log.

Example Logger:

<File name="fileWriter_api" fileName="${LOG_DIR}/api.log" append="false">
  <PatternLayout pattern="${PATTERN}"/>
</File>

Can be reconfigured calling like this:

updateLogger("log/api_new.log", "fileWriter_api", "my.package");

Tags:

Java

Log4J

Log4J2