3

我使用 logback 作为我的日志记录框架,并且有几个作业运行main具有不同参数的相同函数,并且希望为每个作业创建一个日志文件并用作业名称命名日志文件。

例如,如果我有a,b,c所有运行MyClass.main()但参数不同的作业,那么我希望看到a-{date}.log, b-{date}.log, c-{date}.log.

我可以通过在 my中{date}指定 a 来实现该部分,但我不确定如何(或者是否可能)动态创建文件名的前缀(作为作业的名称)。<fileNamePattern>myjob-%d{yyyy-MM-dd}.log</fileNamePattern>logback.xml

有没有办法在 logback 中动态命名日志文件?是否有另一个日志框架使这成为可能?

作为一个后续问题,我是否只是采取了一种糟糕的方法来让多个作业main使用不同的参数调用相同的函数并且想要一个以每个作业命名的日志文件?如果是这样,是否有针对这种情况的标准/最佳实践解决方案?

编辑:我想在作业名称之后命名每个日志文件的原因是每个作业自然定义了一个“工作单元”,如果其中一个作业失败,我更容易找到合适的日志文件。我可以简单地为作业使用滚动日志文件,a,b,c但我发现查看日志并查明每个作业的开始和结束位置对我来说更加困难。

4

4 回答 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.
}

您可以编写一个简单的 LRU 缓存,例如使用 LinkedHashMap 来重用 PrintWriter。

于 2012-12-19T22:34:51.257 回答
1

有没有办法在 logback 中动态命名日志文件?是否有另一个日志框架使这成为可能?

我不相信使用标准 logback.xml 文件配置的out of the box附加程序(File等)是不可能的。RollingFile要执行您想要的操作,您需要动态创建附加程序并将记录器分配给不同的附加程序。或者您需要发明一个新的附加程序,它足够聪明,可以根据记录器名称同时写入多个文件。

我是否只是采取了一种糟糕的方法来让多个作业调用具有不同参数的相同主函数并想要一个以每个作业命名的日志文件?

logback 的作者在Mapped Diagnostic Contextslightly discourage部分解决了这个问题

将一个客户端的日志输出与另一个客户端区分开来的一种可能但稍微不鼓励的方法包括为每个客户端实例化一个新的单独的记录器。这种技术促进了记录器的扩散,并可能增加它们的管理开销。... 一种更轻的技术包括唯一地标记为给定客户端服务的每个日志请求。

然后他们继续讨论映射诊断上下文作为解决这个问题的方法。他们给出了一个 NumberCruncherServer 的例子,它同时为不同线程中的不同客户端处理数字。通过设置映射的诊断上下文和适当的日志记录模式,可以轻松确定哪些日志事件源自哪个客户端。然后,您可以简单地使用grep工具将感兴趣的日志记录事件分离到单独的文件中以进行详细分析。

于 2012-12-19T23:05:50.957 回答
0

您可以使用 logback 鉴别器,因为鉴别器的键可以在<FileNamePattern>标签中使用。我可以想到两个选择:

选项一:

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

一旦你完成了 logback 配置上的 appender 将如下所示:

<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 设置值,因此无需对其进行修改。

于 2013-02-13T16:12:44.247 回答
0

是的你可以。

首先你必须熟悉这两个概念:Logger 和 Appender。一般来说,你的代码获取一个Logger,然后调用debug()、warn()、info()等日志方法。Logger附加了Appender,Appender根据设置的配置将日志信息呈现给用户它。

熟悉后,您需要做的是为每个不同的作业类型动态创建一个具有不同文件名的 FileAppender,并将其附加到您的 Logger。

如果以上都没有意义,我建议你花一些时间阅读 logback 手册。

于 2012-12-19T23:03:49.037 回答