Search code examples
javaslf4jlogback

Logback - set log file name programmatically


I am using logback, and I am trying to set the log file name programmatically within my Java program (similar to Setting Logback Appender path programmatically), and I tried to adapt that solution as follows:

In logback-test.xml:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>log/${log_file_name}.log</file>
  ...

And then again in my Java program:

String logFileName = "" + System.currentTimeMillis(); // just for example
System.setProperty("log_file_name", logFileName);

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
ContextInitializer ci = new ContextInitializer(lc);
lc.reset();
try
{
    // I prefer autoConfig() over JoranConfigurator.doConfigure() so I
    // wouldn't need to find the file myself.
    ci.autoConfig();
}
catch (JoranException e)
{
    // StatusPrinter will try to log this
    e.printStackTrace();
}
StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

However the result is two logs, one full and named as I wanted, e.g., "1319041145343.log", and the other is empty and named "log_file_name_IS_UNDEFINED.log". How do I stop this other empty log file from being created?


Solution

  • I believe the following to be closer to what you want.

    import ch.qos.logback.classic.Logger;
    import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
    import ch.qos.logback.core.FileAppender;
    import ch.qos.logback.core.util.StatusPrinter;
    import org.slf4j.LoggerFactory;
    import ch.qos.logback.classic.LoggerContext;
    
    public class Main {
      public static void main(String[] args) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    
        FileAppender fileAppender = new FileAppender();
        fileAppender.setContext(loggerContext);
        fileAppender.setName("timestamp");
        // set the file name
        fileAppender.setFile("log/" + System.currentTimeMillis()+".log");
    
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(loggerContext);
        encoder.setPattern("%r %thread %level - %msg%n");
        encoder.start();
    
        fileAppender.setEncoder(encoder);
        fileAppender.start();
    
        // attach the rolling file appender to the logger of your choice
        Logger logbackLogger = loggerContext.getLogger("Main");
        logbackLogger.addAppender(fileAppender);
    
        // OPTIONAL: print logback internal status messages
        StatusPrinter.print(loggerContext);
    
        // log something
        logbackLogger.debug("hello");
      }
    }
    

    If all you need is to add a timestamp of the log file name, logback already supports the timestamp element. Thus, you actually don't need any custom code at all.