开发者

Setting Logback Appender path programmatically

I'm trying to set Logback appender path programmatically. (RollingFileAppender with FixedWindowRollingPolicy to be exact)

I'm doing this because I want to enable my users to set the log path in a preference dialog (Eclipse 开发者_StackOverflowRCP)

I've tried something like this, but I doesn't change the log path from what's defined in the configuration file:

Logger logback_logger = (ch.qos.logback.classic.Logger)LoggerFactory
   .getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
RollingFileAppender<ILoggingEvent> rfappender = 
   (RollingFileAppender<ILoggingEvent>)logback_logger.getAppender("FILE");
rfappender.setFile(newFile);
FixedWindowRollingPolicy rollingPolicy = 
   (FixedWindowRollingPolicy)rfappender.getRollingPolicy();
rollingPolicy.setFileNamePattern(newPattern);


Once you programmatically configure your appender, you need invoke its start() method. If the appender has sub-components, invoke start() on the sub-components first. You then add the appender to the logger of your choice.

Here is an example:

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
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();

    RollingFileAppender rfAppender = new RollingFileAppender();
    rfAppender.setContext(loggerContext);
    rfAppender.setFile("testFile.log");
    FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy();
    rollingPolicy.setContext(loggerContext);
    // rolling policies need to know their parent
    // it's one of the rare cases, where a sub-component knows about its parent
    rollingPolicy.setParent(rfAppender);
    rollingPolicy.setFileNamePattern("testFile.%i.log.zip");
    rollingPolicy.start();

    SizeBasedTriggeringPolicy triggeringPolicy = new ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy();
    triggeringPolicy.setMaxFileSize("5MB");
    triggeringPolicy.start();

    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
    encoder.setContext(loggerContext);
    encoder.setPattern("%-4relative [%thread] %-5level %logger{35} - %msg%n");
    encoder.start();

    rfAppender.setEncoder(encoder);
    rfAppender.setRollingPolicy(rollingPolicy);
    rfAppender.setTriggeringPolicy(triggeringPolicy);

    rfAppender.start();

    // attach the rolling file appender to the logger of your choice
    Logger logbackLogger = loggerContext.getLogger("Main");
    logbackLogger.addAppender(rfAppender);

    // OPTIONAL: print logback internal status messages
    StatusPrinter.print(loggerContext);

    // log something
    logbackLogger.debug("hello");
  }
}

The above code is the programmatic expression of the steps taken by the logback's XML configurator, i.e. Joran, when it parses the RollingFixedWindow.xml file.


Using system properties and reloading the configuration file seems cleaner:

change the logback.xml file:

<file>${log_path:-}myfile.log</file>
....
<FileNamePattern>${log_path:-}myfile.%i.log</FileNamePattern>

This will set the default location to the working directory. Then, use:

System.setProperty("log_path", my_log_path);

//Reload:
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);


Looking at the Logback code, I have found a workaround:

rollingPolicy.stop();
rfappender.stop();
rollingPolicy.start();
rfappender.start();

This causes Logback to use the new definitions. It still feels like a workaround, though.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜