使用log4j2 JsonLayout自定义JSON格式日志
需求
log4j2 在性能上提升了很多,可以减小日志输出对高并发程序的性能。
程序的日志需要输出为json格式,通过ELK 收集和存储日志,使用json格式便于Elasticsearch提取JSON字段信息,进行搜索或者通过Kinana展示
log4j2 JsonLayout使用
log4j2 输出json log 使用示例
maven pom 依赖:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28<properties>
<java.version>1.8</java.version>
<java.compile.version>1.8</java.compile.version>
<log4j-api.version>2.13.1</log4j-api.version>
<jackson.version>2.10.0</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j-api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j-api.version}</version>
</dependency>
<!-- json format -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
- Java Code 示例:
1 | import java.time.LocalDateTime; |
- log4j
log4j2.xml
配置示例:
1 |
|
- json 日志输出格式
{"thread":"main","level":"ERROR","loggerName":"com.github.ordiy.LogJsonTest","message":"error cause:","thrown":{"commonElementCount":0,"localizedMessage":"hello i am fool","message":"hello i am fool","name":"java.lang.RuntimeException","extendedStackTrace":"java.lang.RuntimeException: hello i am fool\n\tat com.github.ordiy.LogJsonTest.main(LogJsonTest.java:24) [classes/:?]\n"},"endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","instant":{"epochSecond":1594867434,"nanoOfSecond":597759000},"contextMap":{"hello":"world"},"threadId":1,"threadPriority":5,"source":{"class":"com.github.ordiy.LogJsonTest","method":"main","file":"LogJsonTest.java","line":26,"classLoaderName":"app"},"project":"spring-cloud-app-demo"} |
json layout 配置说明
JsonLayout可以使用compact
locationInfo
等配置输出格式和内容,配置项解说参照log4j2 json layout
常用的配置项目:
<JsonLayout complete="false" compact="true" eventEol="true" properties="true" |
json 输出格式及备注:
使用log4j 输出自定义的日志格式
log4j2.xml 文件内容:
1 |
|
- Java 代码示例:
private static Logger log = LogManager.getLogger(LogJsonTest.class); |
- Json日志输出文件示例:
{"thread":"main","level":"INFO","loggerName":"com.github.ordiy.LogJsonTest","message":"demo str:[]","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","instant":{"epochSecond":1594888243,"nanoOfSecond":231053000},"threadId":1,"threadPriority":5,"project":"spring-cloud-app-demo","timestamp":"2020-07-16T16:30:42.913+0800","parent":"world","span":"world-span","user":"world-user","trace":"world-trace","index":"spring-cloud-app-demo-2020-07-16","line_number":""} |
进行pretty 优化展示后的格式:
1 | { |
Thread Context
thread context
通过Thread Context Stack保存context信息。
ThreadContext.put("id", UUID.randomUUID().toString()); // Add the fishtag; |
CloseableThreadContext
CloseableThreadContext 用于代码块内部ThreadContext。
//在IO 操作使用ThreadContext标记特定的操作信息 |
跨Thread的ThreadContext
Thread之间切换会导致ThreadContext信息丢失。需要进行手动处理:
1 | public class StreamGobbler implements Runnable{ |
需要注意的问题
log4j2 jsonLayout
处理MDC
的兼容问题spring cloud sleuth
默认的 Trace日志默认使用的是slf4j
在MDC
中保存的traceID
等信息,log4j2 jsonLayout
处理MDC
,会存在兼容性问题。(貌似可以通过重新实现JsonLayout
解决该问题,可以参照log4j2-logstash-layout的实现)代码地址
https://github.com/ordiy/demo-project/tree/master/test-log4j2-json-layout