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 简单易用 传统项目

最佳实践建议

  1. ✅ 新项目优先使用Log4j2 + JsonTemplateLayout
  2. ✅ 生产环境关闭prettyPrint减少日志体积
  3. ⚠️ 自定义字段时避免使用JSON保留关键字
  4. ❌ 不要在日志中输出敏感信息(如密码、token)

通过这些配置,无需修改现有日志调用代码,即可获得结构化的JSON日志输出,方便后续的日志分析和监控。


原始标题:Get Log Output in JSON | Baeldung