ELK统一日志解决方案
# 背景
公司日志输出至控制台,然后运维配置日志采集,将日志信息采集至es。但是存在两个致命bug
- 日志采集是按行收集的,导致异常栈信息每行被生成了一条日志
skywalking
的traceId及spring-cloud-sleuth
的traceId和具体的日志信息打印在同一个字段,导致依据traceId无法搜索到全部日志链路
# 解决方案
# pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.2</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>6.4.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- spring-cloud-starter-sleuth
- springcloud的日志追踪
- logstash-logback-encoder
- 用于输出json格式日志
- apm-toolkit-logback-1.x
- 用于获取skywalking的traceId
# Logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!-- 日志存放路径 -->
<property name="LOG_HOME" value="./opt/logs"/>
<!-- 项目名称 -->
<springProperty scope="context" name="app_name" source="spring.application.name"/>
<!-- 控制台输出日志配置 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(pid=${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){%cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 输出json格式log日志,方便es采集 -->
<!-- add converter for %tid -->
<conversionRule conversionWord="tid"
converterClass="org.apache.skywalking.apm.toolkit.log.logback.v1.x.LogbackPatternConverter"/>
<appender name="LOG_STASH" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/log_stash.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${LOG_HOME}/log_stash-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 单个日志文件大小 -->
<maxFileSize>100MB</maxFileSize>
<!--日志文档保留天数-->
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<!-- add TID(traceId) field -->
<provider class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.logstash.TraceIdJsonProvider"/>
</encoder>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>PRC</timeZone>
</timestamp>
<pattern>
<pattern>
{
"kubernetes_pod_ip": "${MY_POD_IP}",
"kubernetes_pod_name": "${MY_POD_NAME}",
"appName": "${app_name}",
"level": "%level",
"skywalking_trace": "%tid",
"trace": "%X{X-B3-TraceId:-}",
"span": "%X{X-B3-SpanId:-}",
"parent": "%X{X-B3-ParentSpanId:-}",
"thread": "%thread",
"class": "%logger#%method,%line",
"message": "%message",
"stack_trace": "%exception"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<!-- 输出logFile -->
<property name="LOG_FILE_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} pid=${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${LOG_HOME}/log.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>${LOG_FILE_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${LOG_HOME}/log-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 单个日志文件大小 -->
<maxFileSize>100MB</maxFileSize>
<!--日志文档保留天数-->
<maxHistory>7</maxHistory>
</rollingPolicy>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.alibaba.nacos" level="WARN"/>
<!-- 本地,开发,测试 环境使用logFile输出 -->
<springProfile name="local | dev | kmos_dev | test">
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="LOG_FILE"/>
</root>
</springProfile>
<!-- 为空或其他环境,使用log_stash输出 -->
<springProfile name="!(local | dev | kmos_dev | test)">
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="LOG_STASH"/>
</root>
</springProfile>
</configuration>
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 成果
pre、pro环境日志输出为json格式到文件中, 运维配置采集json格式日志至es中
上次更新: 2021/10/22, 16:08:06