在日志中显示线程 ID 而不是线程名称

2022-09-01 22:53:15

我有一个带有log4j的Struts应用程序,用于显示有关应用程序的信息。

格式化日志输出的模式如下:

log4j.appender.RALL.layout.ConversionPattern=[%p] %d{dd/MM/yyyy HH:mm:ss} [THREAD ID=%t] [CLASS=(%C{1}:%L)] %m%n 

我需要在日志中显示线程ID而不是线程名称。显示线程名称的转换字符是 %t。我没有在log4j文档中看到获取它的方法。

任何人都可以帮我吗??


答案 1

这是可能的,但不像使用一些预配置的模式那么容易。

Log4j 1.X和Log4j 2.x没有任何用于打印线程ID的预配置模式,但您始终可以使用一些“魔术”。

PatternLayout使用标记为类的类,并将“模式”的静态映射作为键,将类作为值。每次当解析找到用于记录模式格式的模式时,它都会使用与map中的此模式键匹配的转换器。PatternParserfinalConverters%

您无法将自己的规则添加到该地图中,但仍可以编写自己的 MyOwnPatternLayout:

public class MyOwnPatternLayout extends PatternLayout

这将在其方法中做这样的技巧:format

public String format(LoggingEvent event) {
   String log = super.format(event);
   /*
   Now you just have to replace with regex all occurences of %i or 
   any mark you would like to use as mark to represent Thread ID 
   with Thread ID value.
   Only thing you have to be sure to not use any mark as your Thread ID
   that already is defined by PatterParser class
   */
   return log.replaceAll("%i", someThreadID);
}

唯一的问题是您必须以某种方式获取该线程ID。有时你所要做的就是解析线程名称,你可以很容易地收集:

String threadName = event.getThreadName();

例如,Apache-Tomcat 将线程 ID 放在线程名称 http-nio-/127.0.0.1-8084“-exec-41 的末尾。

为了确保线程ID是正确的,你也可以创建自己的LogginEvent和Logger子类(MyLoggingEvent和MyLogger),在MyLogger中创建MyLoggingEvent女巫也将线程ID作为参数,而不仅仅是线程名称。然后,您可以轻松地在上面的代码中收集它。


答案 2

一种方法是使用log4j MDC自己添加它。我们用它来添加 Web 请求的用户名。我们在每个请求开始时的筛选器中执行此操作。例如。

import org.apache.log4j.MDC;

...

  // Add username to MDC
  String username = ...;
  MDC.put("user", username);

然后添加到您的转化模式中。[%X{user}]


推荐