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

如何为Log4j2 JsonTemplateLayout仅在错误日志中添加支持动态赋值与默认值的自定义字段

没问题,我来帮你实现这个需求!咱们一步步来,用Log4j的JsonTemplateLayout结合自定义模板和上下文参数就能搞定。

1. 自定义JSON日志模板

首先,我们需要创建一个自定义的JSON模板文件,用来实现仅在ERROR级别显示额外字段的逻辑,同时支持默认值。在src/main/resources下新建CustomLogstashJsonEventLayoutV1.json,内容如下:

{
  "@version": 1,
  "source_host": "${hostName}",
  "message": "$${message}",
  "thread_name": "$${threadName}",
  "@timestamp": "$${date:format=yyyy-MM-dd'T'HH:mm:ss.SSSXXX}",
  "level": "$${level}",
  "logger_name": "$${loggerName}",
  "aNumber": 1,
  {{#if level == "ERROR"}}
  "severity": "${json:map=contextMap:key=severity:default=DEFAULT_SEVERITY}",
  "err_code": "${json:map=contextMap:key=err_code:default=DEFAULT_ERROR_CODE}"
  {{/if}}
}

这里用到了Handlebars语法的{{#if}}条件判断,只有当日志级别为ERROR时才渲染severity和err_code字段;同时通过json:map从日志上下文读取参数,如果没有传入则使用默认值。

2. 修改Log4j2配置文件

更新你的log4j2.properties,把布局的模板路径改成我们刚创建的自定义模板,还可以把默认值提到配置文件里方便修改:

monitorInterval=20
appenders = APP_CONSOLE
appender.APP_CONSOLE.type = Console
appender.APP_CONSOLE.name = APP_CONSOLE
appender.APP_CONSOLE.filter.threshold.type = ThresholdFilter
appender.APP_CONSOLE.filter.threshold.level = DEBUG
appender.APP_CONSOLE.layout.type = JsonTemplateLayout
# 改用自定义模板
appender.APP_CONSOLE.layout.eventTemplateUri = classpath:CustomLogstashJsonEventLayoutV1.json
# 配置默认值(可选,也可以直接写在模板里)
appender.APP_CONSOLE.layout.defaultSeverity = MEDIUM
appender.APP_CONSOLE.layout.defaultErrCode = ERR_DEFAULT
appender.APP_CONSOLE.layout.eventTemplateAdditionalField[0].type = EventTemplateAdditionalField
appender.APP_CONSOLE.layout.eventTemplateAdditionalField[0].key = aNumber
appender.APP_CONSOLE.layout.eventTemplateAdditionalField[0].value = 1
appender.APP_CONSOLE.layout.eventTemplateAdditionalField[0].format = JSON
loggers = app
logger.app.name = com.vajira.test
logger.app.level = DEBUG
logger.app.additivity = false
logger.app.appenderRef.console.ref = APP_CONSOLE
rootLogger.level = ERROR
rootLogger.appenderRef.APP_CONSOLE.ref = APP_CONSOLE

如果用了配置文件里的默认值,记得把模板里的DEFAULT_SEVERITY和DEFAULT_ERROR_CODE改成${config:defaultSeverity}和${config:defaultErrCode},这样就能读取配置里的默认值了。

3. 修改应用代码,支持传入自定义字段

现在可以在调用log.error时传入自定义的severity和err_code,如果不传就会用默认值。推荐用传入Map的方式,每个日志事件的参数独立,不会污染线程上下文:

package com.vajira.test;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Map;

public class Main {
    static Logger log = LogManager.getLogger(Main.class);

    public static void main(String[] args) {
        System.setProperty("log4j.configurationFile","/home/vajira/test_projects/log4j2_test/src/main/resources/log4j2.properties");
        
        log.info("Helllllooooooooooo this is a sample info message");
        log.debug("Helllllooooooooooo this is a sample debug message");
        
        // 1. 传入自定义字段的错误日志
        log.error("Helllllooooooooooo this is a custom error message", 
            Map.of("severity", "CRITICAL", "err_code", "E001"));
        
        // 2. 不传入字段,使用默认值的错误日志
        log.error("Helllllooooooooooo this is a sample error message with defaults");
    }
}

最终效果

运行后,INFO和DEBUG日志不会显示severity和err_code,而ERROR日志会根据是否传入参数显示对应值或默认值:

  • 自定义参数的ERROR日志:
{"@version":1,"source_host":"vajira","message":"Helllllooooooooooo this is a custom error message","thread_name":"main","@timestamp":"2022-01-09T20:30:31.592+0530","level":"ERROR","logger_name":"com.vajira.test.Main","aNumber":1, "severity":"CRITICAL", "err_code":"E001"}
  • 默认值的ERROR日志:
{"@version":1,"source_host":"vajira","message":"Helllllooooooooooo this is a sample error message with defaults","thread_name":"main","@timestamp":"2022-01-09T20:30:31.593+0530","level":"ERROR","logger_name":"com.vajira.test.Main","aNumber":1, "severity":"MEDIUM", "err_code":"ERR_DEFAULT"}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 02:52:52