2

我正在使用 SLF4J 和 Log4J 后端。

我有独立的 Java 服务,它从队列中获取“任务”并在单独的线程中执行任务(Akka Actors,如果这很重要)。我想将日志消息发送到每个任务的日志文件(因此每个任务都开始登录到它自己的唯一日志文件)。

我的要求是:

  • 使用日志消息隐式传递任务 ID
  • 选择要按该 ID 记录的文件
  • 任务结束时删除ID,因此后续任务不会意外登录到错误的文件

到目前为止,看起来我必须创建自己的日志附加程序,它将通过某些标准“识别”任务(这是一个大问题,因为我看不到如何轻松地将任务 ID 传递给记录器,并且不能依赖ThreadLocal 因为有些任务可能会启动线程池/fork-join,所以继承线程上下文会很复杂)

您知道任何可能对我有用的现有日志记录实现吗?可能是 Log4J 的一些扩展?

4

1 回答 1

2

Log4J 有一个不太广为人知的特性可以帮助您完成任务。自己的 appender 方法似乎是正确的,并且要可靠地传递 ID,您可以使用 Mapped Diagnostic Context (MDC)。在某个已知任务 ID 的地方,您可以将任务 ID 放入 MDC:

MDC.put("id", id);

在您的自定义附加程序中,只需将其取回:

Object id = MDC.get("id");

与简单的 ThreadLocal 存储相比,MDC 可以给您的主要优势是一种“线程继承”。子线程自动继承其父线程的映射诊断上下文的副本:

    MDC.put("id", "1");
    new Thread(){
        @Override
        public void run() {
            System.out.println(MDC.get("id"));  // prints 1
        }
    }.start();

在您的自定义 appender 中有一个任务 ID,您可以轻松地将输出转发到适当的文件。SLF4J 也提供 MDC,但它的行为取决于底层实现。

于 2013-08-07T18:38:38.637 回答