1.前言
log4j
是Java中一个强大的日志记录框架,通过简单的配置便可以在程序中进行日志打印与记录。关于log4j
博主最近碰到一个需求,需要将程序运行过程中的日志按给定的json
模板输出,本文记录一下log4j
如何配置json
格式的日志打印。
2.日志配置
2.1依赖配置
本文使用的是log4j 2.x
版本,log4j
的核心为log4j API
( 接口)和log4j Core
(实现),它可以通过桥接器log4j-slf4j-impl
兼容其他的日志框架如SLF4J
等。另外,由于需要支持json
日志输出,需要引入log4j-layout-template-json
。
根据以上说明,下面给出具体maven
的依赖:
<dependencies>
<dependency>
<!-- SLF4J API -->
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.22</version>
</dependency>
<!-- Log4j 2 API -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<!-- Log4j 2 Core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<!-- SLF4J to Log4j 2 Bridge -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-layout-template-json</artifactId>
<version>2.17.2</version>
</dependency>
</dependencies>
2.2日志行为设置
通过log4j2.xml
来配置日志打印的行为,为了使用json
格式来输出和保存日志,使用了JsonTemplateLayout
,该布局可以通过eventTemplate[Uri]
或stackTraceElementTemplate[Uri]
来自定义json
的结构。
<!--log4j2.xml配置内容-->
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Properties>
<property name="LOG_HOME">log</property>
<property name="MAX_SIZE">100MB</property>
</Properties>
<Appenders>
<!--控制台输出-->
<Console name="Console" target="SYSTEM_OUT">
<!-- 使用 JsonTemplateLayout 输出日志 -->
<JsonTemplateLayout eventTemplateUri="classpath:template.json"/>
</Console>
<!--文件输出-->
<RollingFile name="File" fileName="log/res.log" filePattern="log/res-%d{yyyy-MM-dd}-%i.log">
<!-- 使用 JsonTemplateLayout 输出日志 -->
<JsonTemplateLayout eventTemplateUri="classpath:template.json"/>
<!-- 定义滚动策略 -->
<Policies>
<!--日志文件超过了设定的大小, 会触发日志文件的滚动, 根据filePattern创建新的日志文件-->
<!--旧的日志文件会附加编号,例如res-1.log, res-2.log-->
<SizeBasedTriggeringPolicy size="${MAX_SIZE}"/>
</Policies>
<!--限制只保留最近的5个日志文件-->
<DefaultRolloverStrategy max="5" fileIndex="min"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
JSON模板
log4j
官方给出了自定义的模板JsonLayout.json,参考该配置,本文简单定义了如下的template.json
模板:
{
"Thread": {
"$resolver": "thread",
"field": "name"
},
"ErrorCode": "${ctx:ErrorCode}",
"Timestamp": "${date:yyyy-MM-dd HH:mm:ss}",
"Message": {
"$resolver": "message",
"stringified": true
},
"Thrown": {
"message": {
"$resolver": "exception",
"field": "message"
},
"name": {
"$resolver": "exception",
"field": "className"
},
"extendedStackTrace": {
"$resolver": "exception",
"field": "stackTrace"
}
}
}
说明:
- 模板中的
{ "$resolver": "message", "stringified": true }
由由 JSON 模板布局编译器解释,并替换为引用的事件或堆栈跟踪模板解析器。 - 通过
ThreadContext
可以往json
模板动态传值,例如模板中的${ctx:ErrorCode}
。
3.日志测试
根据上面的配置,定义一个测试类进行日志打印测试:
package com.example.log;
import org.apache.logging.log4j.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TraceLogTest {
static Logger log = LoggerFactory.getLogger(TraceLogTest.class);
public static void main(String[] args) {
// 设置上下文变量
ThreadContext.put("ErrorCode", "1024");
// 记录日志
try{
int i = 1 / 0;
}catch (Exception e){
log.error("Log test", e);
}
// 清除上下文变量
ThreadContext.clearAll();
}
}
运行上述代码的记录的日志(格式化后)如下:
{
"Thread": "main",
"ErrorCode": "1024",
"Timestamp": "2025-02-10 14:35:27",
"Message": "Log test",
"Thrown": {
"message": "/ by zero",
"name": "java.lang.ArithmeticException",
"extendedStackTrace": [
{
"class": "com.example.log.TraceLogTest",
"method": "main",
"file": "TraceLogTest.java",
"line": 15
}
]
}
}