java 日志记录中结构化日志 json 格式输出,核心做法是引入 logback 或 log4j2 的 json 编码器依赖,并配置 patternlayout 使用 %replace 或自定义转换器将日志事件序列化为 json 对象。以 logback 为例,通过添加 logstash-logback-encoder 依赖并在 appender 中使用 jsonencoder,即可让所有日志自动输出为标准的 json 行,便于 elk 等系统解析。

Logback 如何配置 JSON 编码器
在 Logback 中配置 JSON 编码器,需要在 logback.xml 文件中定义一个 ConsoleAppender 或 FileAppender,并将其 encoder 设置为 net.logstash.logback.encoder.LogstashEncoder。这样配置后,日志输出将不再遵循默认的文本模式,而是生成包含时间戳、线程名、日志级别、类名和消息体的 JSON 字符串。这种配置方式无需修改业务代码中的日志调用语句,只需调整配置文件即可实现全局结构化。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>上述配置中,LogstashEncoder 会自动捕获 MDC(Mapped Diagnostic Context)中的数据并合并到 JSON 中。如果项目中使用了 SLF4J API,如 logger.info("User login: {}", userId),编码器会将占位符替换后的实际值写入 JSON 的 message 字段。同时,异常堆栈信息会被序列化为 stack_trace 数组,确保错误信息的完整性。运行此配置后,控制台输出的每一行都是一个合法的 JSON 对象,例如:{"@timestamp":"2023-10-01T12:00:00.000+08:00","level":"INFO","message":"User login: 12345"}。
立即学习“Java免费学习笔记(深入)”;
Log4j2 如何实现 JSON 日志输出
Log4j2 提供内置的 JSON 布局支持,无需额外引入第三方编码器库。通过在 log4j2.xml 中配置 JsonLayout,可以灵活控制 JSON 输出的字段和内容。与 Logback 不同,Log4j2 的 JsonLayout 允许更细粒度的配置,例如是否包含上下文数据、是否压缩堆栈信息等。这种内置支持使得 Log4j2 在微服务架构中成为处理结构化日志的优选方案。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<JsonLayout properties="true" eventEol="true"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>在 Log4j2 的配置中,JsonLayout 的 properties="true" 属性表示将 MDC 中的键值对作为顶层属性添加到 JSON 中。如果未设置此属性,MDC 数据将被嵌套在 contextMap 字段中。此外,eventEol="true" 确保每个 JSON 对象独占一行,便于日志收集工具按行读取。当触发异常时,Log4j2 会将堆栈跟踪信息序列化为 throwable 字段,其内部包含 message 和 stackTrace 数组。这种结构化的输出方式,使得开发者可以直接通过 JSON 解析器提取关键字段,如 level、message 和 throwable.message,从而简化日志分析流程。
MDC 数据在 JSON 日志中如何映射
在 JSON 日志输出中,MDC 数据的映射取决于所使用的日志框架及其编码器配置。对于 Logback 的 LogstashEncoder,MDC 数据默认被扁平化地添加到 JSON 根节点中,这意味着 MDC 中的每个键值对都成为 JSON 对象的一个独立字段。而对于 Log4j2 的 JsonLayout,若未启用 properties="true",MDC 数据将被封装在 contextMap 对象内。这种差异影响了下游日志系统的解析逻辑,开发者需根据实际配置调整查询语句。例如,在 Elasticsearch 中查询 Logback 的 MDC 数据直接使用字段名,而查询 Log4j2 则需访问 contextMap.key 路径。理解这一映射机制,有助于避免日志检索时的字段丢失或路径错误问题。


















