如何让Log4j2 JsonTemplateLayout仅在ThreadContext有值时输出自定义字段
解决Log4j2 JsonTemplateLayout自定义字段按需显示问题
需求说明
- 采用Log4j2的JSON格式记录2个自定义字段:
- 固定值字段
myApp,值为MYAPPLICATION - 动态字段
customKey1,取值自ThreadContext,仅当该字段有值时才打印,无值时从日志中省略
- 固定值字段
- 使用
JsonTemplateLayout实现上述需求
当前配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="console" target="SYSTEM_OUT"> <JsonTemplateLayout eventTemplateUri="classpath:JsonLayout.json"> <EventTemplateAdditionalField key="myApp" value="MYAPPLICATION" /> <EventTemplateAdditionalField key="customKey1" value="$${ctx:customKey1:-}" /> </JsonTemplateLayout> </Console> </Appenders> <Loggers> <Root level="info" additivity="false"> <AppenderRef ref="console" /> </Root> </Loggers> </Configuration>
版本信息
org.springframework.boot:spring-boot-starter-log4j2:2.7.18org.apache.logging.log4j:log4j-layout-template-json:2.21.1
问题
使用JsonLayout时,customKey1仅在ThreadContext有值时显示;但切换到JsonTemplateLayout后,即使未设置customKey1,该字段仍会以空字符串形式出现在日志中,不符合“无值时省略”的要求。
解决方案
问题根源在于EventTemplateAdditionalField的默认值处理:$${ctx:customKey1:-}会在无值时返回空字符串,而JsonTemplateLayout会将空字符串视为有效值保留字段。要实现无值时省略字段,需要通过自定义JSON模板来控制字段显示逻辑:
1. 自定义JSON模板文件
创建customJsonLayout.json文件(放置在classpath下),基于默认模板添加字段非空判断逻辑:
{ "timestamp": { "$resolver": "timestamp", "pattern": { "$format": "yyyy-MM-dd'T'HH:mm:ss.SSSZZ" } }, "level": { "$resolver": "level", "field": "name" }, "logger": { "$resolver": "logger", "field": "name" }, "message": { "$resolver": "message", "stringified": true }, "myApp": "MYAPPLICATION", "customKey1": { "$resolver": "mdc", "key": "customKey1", "suppressEmpty": true } }
其中"suppressEmpty": true是mdc解析器的内置配置,会在customKey1无值时自动省略该字段。
2. 修改Log4j2配置文件
将模板路径指定为自定义的customJsonLayout.json:
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="console" target="SYSTEM_OUT"> <JsonTemplateLayout eventTemplateUri="classpath:customJsonLayout.json" /> </Console> </Appenders> <Loggers> <Root level="info" additivity="false"> <AppenderRef ref="console" /> </Root> </Loggers> </Configuration>
补充说明
如果不想完全重写模板,可以从log4j-layout-template-json包中找到官方默认的JsonLayout.json,只修改或添加自定义字段的逻辑即可,避免重复编写默认字段的配置。
内容的提问来源于stack exchange,提问作者Sumi Silky
相关产品推荐
相关产品推荐

