简体   繁体   中英

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

I have a project with log4j properties defined in xml.

<?xml version="1.0" encoding="UTF-8" ?>
    <Configuration>
        <Appenders>
            <File name="LogFileAppender" fileName="${sys:logFileName:-default}" append="false">
                <PatternLayout>
                    <Pattern>%d [%t] %p - %m%n</Pattern>
                </PatternLayout>
            </File>
        </Appenders>
    
        <Loggers>
            <Root level="error">
                <AppenderRef ref="LogFileAppender"/>
            </Root>
        </Loggers>
    </Configuration>

I update the fileName value to the correct path in the code before any logging occurs to get the correct output folder.

public static void initializeLoggers(String logPath)
{
    // set output paths for log files
    System.setProperty("logFileName", logPath + "PROJECT.log");

    // reconfigure loggers with paths
    org.apache.logging.log4j.core.LoggerContext ctx =
            (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
    ctx.reconfigure();
}

Everything works as expected for the most part. Log files are output to the correct logPath with data written out. However, there is a file called "default" created in the default project directory before we even reach initializeLoggers() because of the call to

static Logger log = LogManager.getLogger(MyClass.class); // Logging

at the top of the code.

I found away to not generate a "default file" by simply leaving the field as blank like so:

fileName="${sys:logFileName:-}"

But in doing so the code complains and gives errors since the property is null at that specific time.

2022-01-19 13:07:51,936 main ERROR The parameter is null: fileName 2022-01-19 13:07:51,944 main ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.FileAppender for element File org.apache.logging.log4j.core.config.ConfigurationException: Arguments given for element File are invalid: field 'fileName' has invalid value '' at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.injectFields(PluginBuilder.java:210)

Is there any way around this so that I can

  • not generate an unused "default file"
  • not have errors being thrown about null values

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, eg 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 = getClass().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());
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM