在JsonLayout中添加MDC变量 - log4j2

9
如何在log4j2的JsonLayout生成的json日志中添加MDC变量。我已经使用了KeyValuePair标签将属性(如主机名)添加到日志中,但我没有找到任何方法来添加MDC变量。在模式布局中,我使用了%X {traceId},但我确信JsonLayout无法解析这些转换字符(据我所知,转换字符仅由模式布局使用)。我查看了JsonLayout的源代码,但没有找到实际将所有数据放入日志消息中的函数。
谢谢。
1个回答

14
你需要的是log4j2查找。根据你提到的MDC(在log4j2中现在被称为ThreadContext),看起来你特别感兴趣的是上下文映射查找
这里有一个简单的例子:
package example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class ThreadContextExample {

    private static final Logger log = LogManager.getLogger();

    public static void main(String[] args) {
        ThreadContext.put("myKey", "myValue");
        log.info("Here's a message!");
    }
}

这是log4j2.xml的配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <JsonLayout compact="false" eventEol="false" stacktraceAsString="true">
                <KeyValuePair key="myJsonKey" value="${ctx:myKey}"/>
            </JsonLayout>
        </Console>

    </Appenders>

    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

最后是一些样例输出(为了易读性而缩短):

{
  "thread" : "main",
  "level" : "INFO",
  "loggerName" : "example.ThreadContextExample",
  "message" : "Here's a message!",
  ...
  "myJsonKey" : "myValue"
}

1
然而,有一个问题。并不是所有的日志消息都应该包含MyJsonKey。因此,在这种情况下,日志被打印出来,它的值字段变成了"{ctx:mykey}",看起来非常糟糕。我们是否有办法动态地向JSON日志添加参数?@D.B. - omjego
如果您不想在日志中打印密钥,您可能需要查看RoutingAppender,并在Routes中使用两个不同的appender配置 - 一个带有密钥,另一个没有。此外,请阅读log4j2 FAQ页面,其中有一个很好的RoutingAppender示例。 - D.B.
4
您可以更好地使用您的值字段,方法是 $${ctx:myKey:-}。即使没有值,json键也会存在,但是 ctx:myKey 将不会出现在日志中,只会是一个空字符串。 - gaellm
在结束时是否需要执行 ThreadContext.clearMap();,就像以前我们执行 MDC.clear() 一样? - Sankalp

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