有没有一种方法可以在Java中动态命名日志文件?

3
我正在使用logback作为我的日志框架,有几个使用不同参数运行相同main函数的作业,我想为每个作业创建一个日志文件并以作业名称命名日志文件。例如,如果我有作业a,b,c,它们都运行MyClass.main()但使用不同的参数,则希望看到a-{date}.log,b-{date}.log,c-{date}.log。
我可以通过在我的logback.xml中指定myjob-%d{yyyy-MM-dd}.log来实现{date}部分,但是我不确定如何(或者它是否可能)动态地创建文件名的前缀(以作业名称命名)。
有没有一种方法在logback中动态命名日志文件?还有另一个使这种情况成为可能的日志框架吗?
作为后续问题,我是否采用了不好的方法,即使用不同参数调用相同main函数并想要为每个作业命名日志文件?如果是这样,是否有标准/最佳实践解决方案?
编辑:我想为每个作业命名日志文件的原因是每个作业自然定义了“工作单元”,如果其中一个作业失败,那么找到适当的日志文件对我来说会更容易。我可以简单地为作业a、b、c使用滚动日志文件,但我发现在查看日志并确定每个作业的开始和结束位置方面更加困难。
4个回答

2
我建议你使用自己的日志记录方式。
public static PrintWriter getLogerFor(String prefix) {
     SimpleDatFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
     String filename= prefix + sdf.format(new Date());
     return new PrintWriter(filename, true); // auto flush.
}

你可以使用LinkedHashMap编写一个简单的LRU缓存,以便重复使用PrintWriters。

1
有办法在logback中动态命名日志文件吗?还有其他日志框架可以实现此功能吗?
我不认为使用标准的logback.xml文件配置的“开箱即用”的输出器(如“File”,“RollingFile”等)可以实现这一点。要做到这一点,您需要动态地创建输出器并将记录器分配给不同的输出器。或者,您需要发明一个新的输出器,它足够聪明,可以根据记录器名称同时写入多个文件。
“我是否只是采用了错误的方法,拥有调用相同主函数但带有不同参数的多个作业,并希望每个作业都有一个日志文件的命名方式?” logback的作者在Mapped Diagnostic Context一节中解决了这个问题,稍微反对它。
一种可能但不太鼓励的区分一个客户端日志输出的方法是为每个客户端实例化一个新的和独立的记录器。这种技术会促进记录器的增加,并可能增加它们的管理开销。... 一种更轻量级的技术是为服务于给定客户端的每个日志请求打上唯一标记。
然后他们继续讨论映射诊断上下文作为解决此问题的方法。他们举了一个NumberCruncherServer的例子,该服务器正在同时为各个客户端在各个线程中进行数字计算。通过设置映射诊断上下文和适当的日志模式,很容易确定哪些日志事件来自哪个客户端。然后,您可以简单地使用grep工具将感兴趣的日志事件分离到单独的文件中进行详细分析。

0

您可以利用Logback中的区分器,因为区分器的键可以在<FileNamePattern>标记中使用。我可以想到两个选项:

选项一:

您可以使用Mapped Diagnostic Context区分器来实现日志分离,您需要使用MDC.put();为每个作业设置不同的值。

完成后,您在Logback配置上附加器应该像这样:

<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
    <discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
        <key>jobName</key> <!-- the key you used with MDC.put() -->
        <defaultValue>none</defaultValue>
    </discriminator>
    <sift>
        <appender name="jobsLogs-${jobName}" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${jobName}.%d{dd-MM-yyyy}.log.zip</FileNamePattern>
                .
                .
                .
            </rollingPolicy>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <Pattern>...</Pattern>
            </layout>
        </appender>
    </sift>
</appender>

第二个选择:

实现自己的鉴别器 - 实现 ch.qos.logback.core.sift.Discriminator,基于线程名进行鉴别。代码大致如下:

public class ThreadNameDiscriminator implements Discriminator<ILoggingEvent> {

    private final String THREAD_NAME_KEY = "threadName";

    @Override
    public String getDiscriminatingValue(ILoggingEvent event) {
    return Thread.currentThread().getName();
    }

    @Override
    public String getKey() {
    return THREAD_NAME_KEY;
    }

    // implementation for more methods
    .
    .
    .
}

日志附加器将类似于选项一,其中鉴别器类为ThreadNameDiscriminator,键为threadName。在此选项中,无需从作业中设置MDC的值,因此不需要对它们进行修改。


0

可以的。

首先,你需要熟悉这两个概念:Logger 和 Appender。一般来说,你的代码获得一个 Logger,并调用 logging 方法,例如 debug()、warn()、info() 等等。Logger 附有 Appender,而 Appender 根据其设置的配置将日志信息呈现给用户。

一旦你熟悉了这些,你需要为每个不同的作业类型动态创建一个具有不同文件名的 FileAppender,并将其附加到你的 Logger 上。

如果以上内容对你来说没有意义,我建议你花些时间阅读 logback 手册。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接