Log4J2 - Assigning File Appender Filename at Runtime

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.

How to delay log file creation until Appender fileName is set programmatically for log4j2

If you want to delay the initialization of Log4j, you need to carefully control the usage of LogManager.getLogger and similar methods. For example you should not use a static Logger field in your main class, but call LogManager.getLogger only after you initialized logging.

This can be a little tricky to get right, but the system property log4j2.loggerContextStacktraceOnStart can help you.

An easier approach is to move the configuration file out of the way of the automatic configuration process, e.g. by calling it myapp-log4j2.xml. This way the first configuration will use the default configuration (which uses only a console appender) and you can reconfigure it after you set the appropriate system variables:

  private static final String CONFIG_FILE = "myapp-log4j2.xml";

public static void initializeLoggers(String logPath) {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
final ClassLoader cl = SomeClass.class.getClassLoader();
final URL resource = tccl != null ? tccl.getResource(CONFIG_FILE)
: cl != null ? cl.getResource(CONFIG_FILE) : ClassLoader.getSystemResource(CONFIG_FILE);
if (resource != null) {
System.setProperty("logFileName", logPath + "PROJECT.log");
Configurator.reconfigure(resource.toURI());
}
}

Add file logging dynamically at runtime with Log4j2 2.8.1

Based on additional information in the comments, here is my suggestion. I don't think you need to do this programmatically for all the reasons you mentioned in your question.

Instead you can configure the log4j2 system using something like the following example. Note that you do not necessarily need the console appender I simply used that for testing.

log4j2.xml content:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="[%date{ISO8601}][%-5level][%t] %m%n" />
</Console>
<File
fileName="logs/${ctx:fileName}.txt"
name="logFile">
<PatternLayout>
<Pattern>[%date{ISO8601}][%-5level][%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="example" level="TRACE" additivity="false">
<AppenderRef ref="STDOUT" />
<AppenderRef ref="logFile" />
</Logger>
<Root level="WARN">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>

Java code:

package example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class LogFileNameBasedOnArg0Main {

public static void main(String[] args) {
ThreadContext.put("fileName", args[0]);
Logger log = LogManager.getLogger();
log.info("Here's some info!");
}

}

Output:

I used a program argument of "myFile" which generated the file: logs/myFile.txt with the following content:

[2017-05-03T11:20:37,653][INFO ][main] Here's some info!

You should be able to modify this example to meet your needs and you won't have to do any programmatic configuration thus avoiding the issues you mentioned.



Related Topics



Leave a reply



Submit