1. 簡介
目前大多數 Java 日誌庫都提供不同的佈局選項,用於格式化日誌,以滿足每個項目的需求。
在本快速教程中,我們想將日誌條目格式化為 JSON 格式。 我們將瞭解如何使用兩個最常用的日誌庫:Log4j2 和 Logback。
它們都使用 Jackson 內部來表示日誌為 JSON 格式。
要了解這些庫的介紹,請查看我們的《Java 日誌簡介》文章。
2. Log4j2
Log4j2 是最流行的 Java 日誌庫 Log4j 的直接後繼者。
作為 Java 項目的新標準,我們將演示如何將其配置為輸出 JSON。
2.1. Maven 依賴
首先,我們需要在我們的 <em >pom.</em >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 上找到:log4j-api, log4j-core, jackson-databind.
2.2. 使用 JsonLayout
然後,在我們的 log4j2.xml文件中,我們可以創建一個使用 JsonLayout和新的Logger的Appender:
<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 將增加輸出的大小並使其更易於閲讀。
現在,讓我們測試我們的配置。在我們的代碼中,我們可以實例化新的 JSON 日誌器並生成新的調試級別的跟蹤記錄:
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. 使用 <em >JsonTemplateLayout</em >
在上一節中,我們看到了如何使用 <em >JsonLayout</em > 屬性。自版本 2.14.0 起,該屬性已被棄用並替換為 <em >JsonTemplateLayout</em >。
<em >JsonTemplateLayout</em >> 提供增強功能和提高效率,因為它默認優化為以最快的速度編碼日誌事件。
此外,它支持無垃圾回收日誌記錄,因此在垃圾回收暫停對性能產生影響的情況下,具有一定的性能優勢。要啓用無垃圾回收日誌記錄,我們需要將 <em >log4j2.garbagefreeThreadContextMap</em > 和 <em >log4j2.enableThreadLocals</em >> 屬性設置為 true:
-Dlog4j2.garbagefreeThreadContextMap=true
-Dlog4j2.enableThreadlocals=true 要使用 <em >JsonTemplateLayout</em >》,請將log4j-layout-template-json> 依賴添加到 <em >pom.xml</em >> 中:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-layout-template-json</artifactId>
<version>2.24.3</version>
</dependency>接下來,讓我們修改我們的 Appender,使用 JsonTemplateLayout 代替:
<Appenders>
<Console name="ConsoleJSONAppender" target="SYSTEM_OUT">
<JsonTemplateLayout eventTemplateUri="classpath:JsonLayout.json">
<EventTemplateAdditionalField key="myCustomField" value="myCustomValue"/>
</JsonTemplateLayout>
</Console>
</Appenders>這裏我們使用 JsonTemplateLayout 並使用 eventTemplateUri 指定 JSON 佈局格式。 eventTemplateUri 定義 JSON 輸出的格式。當 eventTemplateUri 未指定時,它將使用 Elastic Common Schema (ECS) 格式作為默認值 (classpath:EcsLayout.json)。
其他支持的模板包括 Graylog Extended Log Format (GELF) ,值為 classpath:GelfLayout.json。
JsonLayout.json 模板旨在輕鬆地從 JsonLayout 轉換為 JsonTemplateLayout。 在我們的情況下,我們使用 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"
}與 JsonLayout 採用 KeyValuePair 屬性添加自定義鍵值對的方式不同,我們使用名為 EventTemplateAdditionalField 的屬性來添加鍵和值。
3. Logback
Logback 可以被認為是 Log4j 的又一繼任者。它由相同的開發者編寫,並聲稱比其前身更高效、更快。
因此,讓我們看看如何配置它以獲得日誌輸出的 JSON 格式。
3.1. Maven 依賴
以下依賴項應包含在我們的 <em pom.xml</em> 中:
<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>我們可以在這裏查看這些依賴項的最新版本: logback-classic, logback-json-classic, logback-jackson, jackson-databind。
3.2. 使用 JsonLayout
首先,我們在我們的 logback-test.xml 中創建一個新的 appender,該 appender 使用 JsonLayout 和 JacksonJsonFormatter。
之後,我們可以創建一個使用該 appender 的新的 logger:
<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 啓用後,可以獲得可讀的 JSON。
為了測試我們的配置,讓我們在代碼中實例化日誌記錄器並記錄一條調試消息:
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. 使用 <em >JsonEncoder</em >
使用 JSON 格式記錄輸出的另一種方式是使用 <em >JsonEncoder</em >。它將日誌事件轉換為有效的 JSON 文本。
讓我們添加一個新的 <em >appender</em >,它使用 <em >JsonEncoder</em >,以及一個使用此 <em >appender</em >> 的新 <em >logger</em >>:
<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並調用debug()來生成一條日誌消息:
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,除非我們已設置多個日誌上下文。
4. 結論
在本文中,我們瞭解到如何輕鬆配置 Log4j2 和 Logback 以生成 JSON 輸出格式。我們將解析的複雜性委託給了日誌庫,因此我們無需修改任何現有的日誌器調用。