以编程方式设置Logback Appender路径

ysh*_*bar 18 java logging logback

我正在尝试以编程方式设置Logback appender路径.(具有FixedWindowRollingPolicy的RollingFileAppender准确)

我这样做是因为我想让我的用户在首选项对话框中设置日志路径(Eclipse RCP)

我尝试过类似的东西,但是我没有改变配置文件中定义的日志路径:

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);
Run Code Online (Sandbox Code Playgroud)

Cek*_*eki 27

一旦以编程方式配置appender,您需要调用其start()方法.如果appender具有子组件,则首先调用start()子组件.然后,将appender添加到您选择的记录器中.

这是一个例子:

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");
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码是logback的XML配置器(即Joran)在解析RollingFixedWindow.xml文件时所采取的步骤的编程表达式.

  • (在记录内容方面有点尴尬不同意,但是)这不是我想要做的事情 - 我想用XML配置我的记录器,并且只按代码更改位置.这样,高级用户可以控制细粒度的日志记录属性,新手用户可以使用UI.通过代码重新启动appender工作; 使用系统属性和ContextInitializer工作得更好,硬编码更少,为什么这不正确? (5认同)

ysh*_*bar 14

使用系统属性并重新加载配置文件似乎更清晰:

更改logback.xml文件:

<file>${log_path:-}myfile.log</file>
....
<FileNamePattern>${log_path:-}myfile.%i.log</FileNamePattern>
Run Code Online (Sandbox Code Playgroud)

这会将默认位置设置为工作目录.然后,使用:

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);
Run Code Online (Sandbox Code Playgroud)

  • 使用ContextInitializer非常不正确.请参阅我的答案,了解正确的方法. (2认同)

ysh*_*bar 5

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

rollingPolicy.stop();
rfappender.stop();
rollingPolicy.start();
rfappender.start();
Run Code Online (Sandbox Code Playgroud)

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