You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止Log4j2 JsonTemplateLayout将堆栈跟踪追加到其他JSON字段

问题描述

我正在使用Log4j2的JsonTemplateLayout,配置了JSON模板将堆栈跟踪信息放到stack字段中。但记录异常时,堆栈跟踪除了出现在指定字段外,还会被追加到service、component这类自定义字段里。

使用的JSON模板如下:

{"level": {"$resolver": "level","field": "name"},"message": {"$resolver": "message","stringified": true},"timestamp": {"$resolver": "timestamp","pattern": {"format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'","timeZone": "UTC"}},"logger": {"$resolver": "logger","field": "name"},"service": {"$resolver": "pattern","pattern": "${env:FOO_SERVICE}"},"component": {"$resolver": "pattern","pattern": "${env:FOO_COMPONENT}"},"exception": {"exception_class": {"$resolver": "exception","field": "className"},"exception_message": {"$resolver": "exception","field": "message"},"stacktrace": {"$resolver": "exception","field": "stackTrace","stackTrace": {"stringified": true}}},"line_number": {"$resolver": "source","field": "lineNumber"}}

控制台Appender配置:

<Appenders>
  <Console name="Console" target="SYSTEM_OUT">
    <JsonTemplateLayout eventTemplateUri="classpath:log4j2-layout.json"/>
  </Console>
</Appenders>

异常日志示例中,service和component字段被追加了堆栈信息:

{"level":"INFO","message":"Force trigger exception","timestamp":"2022-11-02T20:37:35.270Z","logger":"foo.example.acme.system.connector.dataset.EchoAPI","service":"example1 java.lang.Exception: This is a forced exception\n\tat foo.example.acme.system.connector.dataset.EchoAPI.handle(EchoAPI.java:18) ~[classes/:?]\n\tat foo.example.acme.system.connector.ConnectorApi.handle(ConnectorApi.java:33) ~[classes/:?]\n\tat somesystem.com.connector.undertow.UndertowHandler.handleBody(UndertowHandler.java:131) ~[classes/:?]\n\tat io.undertow.io.AsyncReceiverImpl.receiveFullBytes(AsyncReceiverImpl.java:366) ~[undertow-core-2.2.19.Final.jar:2.2.19.Final]\n\tat somesystem.com.connector.undertow.UndertowHandler.handleRequest(UndertowHandler.java:61) ~[classes/:?]\n\tat io.undertow.server.Connectors.executeRootHandler(Connectors.java:387) ~[undertow-core-2.2.19.Final.jar:2.2.19.Final]\n\tat io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852) ~[undertow-core-2.2.19.Final.jar:2.2.19.Final]\n\tat org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282) ~[xnio-api-3.8.7.Final.jar:3.8.7.Final]\n\tat java.lang.Thread.run(Thread.java:832) ~[?:?]\n","component":"example2 java.lang.Exception: This is a forced exception\n\tat foo.example.acme.system.connector.dataset.EchoAPI.handle(EchoAPI.java:18) ~[classes/:?]\n\tat foo.example.acme.system.connector.ConnectorApi.handle(ConnectorApi.java:33) ~[classes/:?]\n\tat somesystem.com.connector.undertow.UndertowHandler.handleBody(UndertowHandler.java:131) ~[classes/:?]\n\tat io.undertow.io.AsyncReceiverImpl.receiveFullBytes(AsyncReceiverImpl.java:366) ~[undertow-core-2.2.19.Final.jar:2.2.19.Final]\n\tat somesystem.com.connector.undertow.UndertowHandler.handleRequest(UndertowHandler.java:61) ~[classes/:?]\n\tat io.undertow.server.Connectors.executeRootHandler(Connectors.java:387) ~[undertow-core-2.2.19.Final.jar:2.2.19.Final]\n\tat io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852) ~[undertow-core-2.2.19.Final.jar:2.2.19.Final]\n\tat org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]\n\tat org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282) ~[xnio-api-3.8.7.Final.jar:3.8.7.Final]\n\tat java.lang.Thread.run(Thread.java:832) ~[?:?]\n","exception":{"exception_class":"java.lang.Exception","exception_message":"This is a forced exception","stacktrace":"java.lang.Exception: This is a forced exception\n\tat foo.example.acme.system.connector.dataset.EchoAPI.handle(EchoAPI.java:18)\n\tat foo.example.acme.system.connector.ConnectorApi.handle(ConnectorApi.java:33)\n\tat somesystem.com.connector.undertow.UndertowHandler.handleBody(UndertowHandler.java:131)\n\tat io.undertow.io.AsyncReceiverImpl.receiveFullBytes(AsyncReceiverImpl.java:366)\n\tat somesystem.com.connector.undertow.UndertowHandler.handleRequest(UndertowHandler.java:61)\n\tat io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)\n\tat io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852)\n\tat org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)\n\tat org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)\n\tat org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)\n\tat org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423)\n\tat org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282)\n\tat java.base/java.lang.Thread.run(Thread.java:832)\n"}}

试过将stringified设为false、把自定义字段改成嵌套形式都无效,当前使用Log4j2 2.19.0版本,也试过更早的版本。

解决方案

这个问题的根源是PatternResolver默认会自动追加异常堆栈信息:当使用pattern解析器时,如果当前日志事件携带异常,它会自动把堆栈跟踪追加到解析结果之后。

要解决这个问题,只需在service和component的pattern解析器配置中添加"exception": "none"参数,明确禁用自动追加异常的行为。

修改后的JSON模板如下:

{
  "level": {"$resolver": "level","field": "name"},
  "message": {"$resolver": "message","stringified": true},
  "timestamp": {"$resolver": "timestamp","pattern": {"format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'","timeZone": "UTC"}},
  "logger": {"$resolver": "logger","field": "name"},
  "service": {"$resolver": "pattern","pattern": "${env:FOO_SERVICE}", "exception": "none"},
  "component": {"$resolver": "pattern","pattern": "${env:FOO_COMPONENT}", "exception": "none"},
  "exception": {
    "exception_class": {"$resolver": "exception","field": "className"},
    "exception_message": {"$resolver": "exception","field": "message"},
    "stacktrace": {"$resolver": "exception","field": "stackTrace","stackTrace": {"stringified": true}}
  },
  "line_number": {"$resolver": "source","field": "lineNumber"}
}

参数说明:

  • "exception": "none":告诉PatternResolver只返回pattern解析后的原始值,不再自动追加异常堆栈信息。

修改后,service和component字段就只会显示环境变量的原始值,不会再被追加异常堆栈内容。

内容的提问来源于stack exchange,提问作者Shogan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:55:18