1. 概述
现代Java日志框架都支持多种输出格式,以满足不同项目的需求。本文将重点介绍如何将日志输出为JSON格式,这种格式特别适合结构化日志分析和集中式日志系统。
我们将分别演示两大主流日志框架的实现方案:
两者底层都使用Jackson处理JSON序列化。如果需要日志框架基础入门,可参考我们的Java日志入门指南。
2. Log4j2实现方案
Log4j2作为Log4j的继任者,已成为Java项目的标准日志框架。下面介绍其JSON输出配置。
2.1 Maven依赖
在pom.xml
中添加以下依赖:
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
</dependency>
</dependencies>
最新版本可在Maven Central获取:
2.2 使用JsonLayout
在log4j2.xml
中配置JSON输出:
<Appenders>
<Console name="ConsoleJSONAppender" target="SYSTEM_OUT">
<JsonLayout complete="false" compact="false">
<KeyValuePair key="myCustomField" value="myCustomValue"/>
</JsonLayout>
</Console>
</Appenders>
<Logger name="CONSOLE_JSON_APPENDER" level="TRACE" additivity="false">
<AppenderRef ref="ConsoleJSONAppender"/>
</Logger>
关键配置说明:
- ✅
KeyValuePair
可添加自定义字段(支持从日志上下文取值) - ✅
compact=false
启用美化输出(方便调试) - ⚠️ 生产环境建议设为
compact=true
减少日志体积
测试代码:
Logger logger = LogManager.getLogger("CONSOLE_JSON_APPENDER");
logger.debug("Debug message");
输出示例:
{
"instant" : {
"epochSecond" : 1696419692,
"nanoOfSecond" : 479118362
},
"thread" : "main",
"level" : "DEBUG",
"loggerName" : "CONSOLE_JSON_APPENDER",
"message" : "Debug message",
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"threadId" : 1,
"threadPriority" : 5,
"myCustomField" : "myCustomValue"
}
2.3 使用JsonTemplateLayout(推荐)
⚠️ 自2.14.0版本起,JsonLayout
已被弃用,推荐使用JsonTemplateLayout
。
优势对比: | 特性 | JsonLayout | JsonTemplateLayout | |------|------------|-------------------| | 性能 | 常规 | 优化编码速度(支持无垃圾日志) | | 灵活性 | 有限 | 支持自定义模板 |
启用无垃圾日志需添加JVM参数:
-Dlog4j2.garbagefreeThreadContextMap=true
-Dlog4j2.enableThreadlocals=true
新增Maven依赖:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-layout-template-json</artifactId>
<version>2.24.3</version>
</dependency>
配置示例:
<Appenders>
<Console name="ConsoleJSONAppender" target="SYSTEM_OUT">
<JsonTemplateLayout eventTemplateUri="classpath:JsonLayout.json">
<EventTemplateAdditionalField key="myCustomField" value="myCustomValue"/>
</JsonTemplateLayout>
</Console>
</Appenders>
模板说明:
- 默认使用ECS格式(
classpath:EcsLayout.json
) - 支持GELF格式(
classpath:GelfLayout.json
) - 自定义模板示例(
JsonLayout.json
):{ "instant": { "epochSecond": 1736320992, "nanoOfSecond": 804274875 }, "thread": "main", "level": "DEBUG", "loggerName": "CONSOLE_JSON_APPENDER", "message": "Debug message", "endOfBatch": false, "loggerFqcn": "org.apache.logging.log4j.spi.AbstractLogger", "threadId": 1, "threadPriority": 5, "myCustomField": "myCustomValue" }
3. Logback实现方案
Logback由Log4j原班人马开发,性能更优。下面介绍其JSON输出配置。
3.1 Maven依赖
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-json-classic</artifactId>
<version>0.1.5</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-jackson</artifactId>
<version>0.1.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>
最新版本可在Maven Central获取:
3.2 使用JsonLayout
配置logback-test.xml
:
<appender name="json" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<jsonFormatter
class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>true</prettyPrint>
</jsonFormatter>
<timestampFormat>yyyy-MM-dd' 'HH:mm:ss.SSS</timestampFormat>
</layout>
</appender>
<logger name="jsonLogger" level="TRACE">
<appender-ref ref="json" />
</logger>
关键配置:
- ✅
prettyPrint=true
美化输出(调试用) - ✅
timestampFormat
自定义时间格式
测试代码:
Logger logger = LoggerFactory.getLogger("jsonLogger");
logger.debug("Debug message");
输出示例:
{
"timestamp":"2017-12-14 23:36:22.305",
"level":"DEBUG",
"thread":"main",
"logger":"jsonLogger",
"message":"Debug message",
"context":"default"
}
3.3 使用JsonEncoder
另一种JSON输出方案,直接将日志事件转为JSON:
<appender name="jsonEncoder" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.JsonEncoder"/>
</appender>
<logger name="jsonEncoderLogger" level="TRACE">
<appender-ref ref="jsonEncoder" />
</logger>
测试代码:
Logger logger = LoggerFactory.getLogger("jsonEncoderLogger");
logger.debug("Debug message");
输出示例:
{
"sequenceNumber":0,
"timestamp":1696689301574,
"nanoseconds":574716015,
"level":"DEBUG",
"threadName":"main",
"loggerName":"jsonEncoderLogger",
"context":
{
"name":"default",
"birthdate":1696689301038,
"properties":{}
},
"mdc": {},
"message":"Debug message",
"throwable":null
}
字段说明:
message
:日志内容context
:日志上下文(默认为"default")mdc
:诊断上下文映射(MDC)
4. 总结
本文展示了在Log4j2和Logback中配置JSON日志输出的两种方案:
方案对比
框架 | 实现方式 | 优势 | 适用场景 |
---|---|---|---|
Log4j2 | JsonTemplateLayout | 高性能、无垃圾日志 | 高并发系统 |
Logback | JsonLayout/Encoder | 简单易用 | 传统项目 |
最佳实践建议
- ✅ 新项目优先使用Log4j2 + JsonTemplateLayout
- ✅ 生产环境关闭
prettyPrint
减少日志体积 - ⚠️ 自定义字段时避免使用JSON保留关键字
- ❌ 不要在日志中输出敏感信息(如密码、token)
通过这些配置,无需修改现有日志调用代码,即可获得结构化的JSON日志输出,方便后续的日志分析和监控。