Logback - set log file name programmatically

conorsomahony picture conorsomahony · Oct 19, 2011 · Viewed 50.2k times · Source

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?

Answer

Ceki picture Ceki · Oct 19, 2011

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.