【问题标题】:Logback - set log file name programmaticallyLogback - 以编程方式设置日志文件名
【发布时间】:2011-12-11 02:19:30
【问题描述】:

我正在使用 logback,并尝试在我的 Java 程序中以编程方式设置日志文件名(类似于 Setting Logback Appender path programmatically),我尝试按如下方式调整该解决方案:

在 logback-test.xml 中:

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

然后在我的 Java 程序中:

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);

但是结果是两个日志,一个是完整的并按照我的意愿命名,例如“1319041145343.log”,另一个是空的并命名为“log_file_name_IS_UNDEFINED.log”。如何停止创建另一个空日志文件?

【问题讨论】:

  • 您的代码的唯一问题似乎是您设置System.setProperty("log_file_name", logFileName); 为时已晚。在执行 Logback 自动配置之前执行它,你就有了你想要的。
  • 它实际上可以比在您的代码 sn-p 中更容易地完成:stackoverflow.com/a/21886071/709537

标签: java slf4j logback


【解决方案1】:

我相信以下内容更接近您想要的。

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");
  }
}

如果你只需要添加日志文件名的时间戳,logback 已经supports the timestamp element。因此,您实际上根本不需要任何自定义代码。

【讨论】:

  • 感谢您的帮助,我会试一试。 (我只是以时间戳为例,实际文件名会有所不同)
  • 谢谢,这行得通 - 在 logback-test.xml 中我不再指定文件附加程序,在 java 代码中我正在创建一个并将其附加到“根”记录器。
  • 不是slf4j的重点是避免导入ch.qos.logback.classic.Logger
  • @Zombies:是的。然而,slf4j 应该是 simple,顾名思义,因此 slf4j API 不提供对日志输出的任何控制。如果您想要该控件,则必须直接与(并依赖)您使用的日志记录框架进行对话。
  • 我注意到这只改变了当前类的日志文件,如果我想改变整个应用程序的日志文件,有没有类似的方法?因为将这段代码摘录到所有文件中是一个漫长的过程,而且日志文件似乎没有按照正常的时间顺序执行
【解决方案2】:

要根据运行时属性将日志消息分离/筛选到不同的文件,您可能需要使用ch.qos.logback.classic.sift.SiftingAppender

简而言之,这允许您使用&lt;file&gt;${userid}.log&lt;/file&gt; 设置FileAppender(或任何其他附加程序),其中${userId} 基于MDC (Mapped Diagnostic Context) 替换(例如,MDC.put("userid", "Alice");)。完整示例请参见第一个链接。

【讨论】:

    【解决方案3】:

    你可以这样做来忽略那些额外的文件创建。下面是配置文件

    <configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- "application-name" is a variable -->
    <File>c:/logs/${application-name}.log</File>
    <layout class="ch.qos.logback.classic.PatternLayout">
    <Pattern>%d %p %t %c - %m%n</Pattern>
    </layout>
    </appender>
    <root level="debug">
    <appender-ref ref="FILE"/>
    </root>
    </configuration>  
    

    这里是java部分,

    LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
    JoranConfigurator jc = new JoranConfigurator();
    jc.setContext(context);
    context.reset(); // override default configuration
    // inject the name of the current application as "application-name"
    // property of the LoggerContext
    context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION);
    jc.doConfigure("/path/to/the/above/configuration/file.xml");
    

    我从这里得到这个http://logback.qos.ch/faq.html#sharedConfiguration

    【讨论】:

    • 另一种方法是在调用 Logger 之前初始化所有系统变量。这也有效。
    • 最终使用 System.setProperty(..) 而不是重置上下文。对我来说似乎更干净。谢谢你的例子。
    • 不幸的是,当您想要共享配置时,使用系统属性无法正常工作
    【解决方案4】:

    看起来记录器被初始化了两次。第一次,可能是当应用程序加载并且无法解析${log_file_name} 时。如果您使用 -Dlog_file_name=*something* 启动应用程序,则可以验证此行为是否创建另一个名为 *something* 的日志文件

    【讨论】:

    • 以编程方式设置文件名的方法是使用所需配置(名称、类别、包等)实例化文件附加程序并将其添加到附加程序层次结构中。
    • 谢谢,我将 -Dlog_file_name=verify 添加到 VM 参数中,并且确实得到了一个名为“verify.log”的空日志 - 有没有办法阻止记录器启动两次?
    猜你喜欢
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2014-02-17
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多