slf4j+logback
先引入相关依赖(当然很多包会间接依赖这些依赖)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
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
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
这里使用Slf4j的原因,市面上有很多日志框架,Slf4j可以看作一个接口或类似jdbc,将不同的日志框架整合起来,方便我们在一个项目中需要改变日志框架时,可以很好的进行维护。这里我们使用的是Slf4j + logback的方式。
另外,Slf4j 日志输出采用占位符{}的方式,相对于其他的日志框架可以避免很多字符串拼接而造成的性能问题。
接下来聊一聊关于logback配置文件的问题:
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:-->
<!-- 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。-->
<!-- scanPeriod:-->
<!-- 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。-->
<!-- debug:-->
<!-- 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<!-- 每隔10秒扫描一次xml文件,当发生改变时重新进行加载-->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>austin</contextName>
<!-- 设置日志输出路径 可以使“${}”来使用变量。 -->
<!-- 这里相当于是变量,后面可以根据name来获取value,即是将一些经常修改的数据提取出来·-->
<property name="log.path" value="logs"/>
<springProperty scope="context" name="grayLogIp" source="austin.business.graylog.ip"/>
<!-- 格式化输出 -->
<property name="LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5level][%t][%file:%line][%X{traceId}] -| %m%n"/>
<!-- 在一个configuration下可以有多个appender appender主要指定输出目的地 其中属性name用于指定自己定义的名字 class用于指定输出的目的地-->
<!-- ch.qos.logback.core.ConsoleAppender 输出的控制台-->
<!-- ch.qos.logback.core.rolling.RollingFileAppender 文件滚动输出:现将日志写到一个文件中,在特定的条件下,将某些日志输出到另一个文件-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- file日志输出的文件路径,可以是绝对路径也可以是相对路径-->
<!-- encoder格式化方式-->
<!-- rollingPolicy滚动策略 也是通过class来指定滚动策略-->
<!-- 最常见的滚动策略为 基于时间的滚动策略 ch.qos.logback.core.rolling.TimeBasedRollingPolicy-->
<!-- fileNamePattern用于指生产出来的滚动日志的文件名称格式-->
<!--时间滚动也即是生成的日志不仅仅会只打印在一个文件中,会根据一定的策略打印到不同的有一定顺序的文件中-->
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/austin-info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/logs/austin-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 当超过1000MB时,触发滚动策略-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1000MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/austin-error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/logs/austin-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1000MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="GELF" class="de.siegmar.logbackgelf.GelfUdpAppender">
<!-- Graylog服务的地址 -->
<graylogHost>${grayLogIp}</graylogHost>
<!-- UDP Input端口 -->
<graylogPort>12201</graylogPort>
<!-- 最大GELF数据块大小(单位:字节),508为建议最小值,最大值为65467 -->
<maxChunkSize>508</maxChunkSize>
<!-- 是否使用压缩 -->
<useCompression>true</useCompression>
<encoder class="de.siegmar.logbackgelf.GelfEncoder">
<!-- 是否发送原生的日志信息 -->
<includeRawMessage>false</includeRawMessage>
<includeMarker>true</includeMarker>
<includeMdcData>true</includeMdcData>
<includeCallerData>false</includeCallerData>
<includeRootCauseData>false</includeRootCauseData>
<!-- 是否发送日志级别的名称,否则默认以数字代表日志级别 -->
<includeLevelName>true</includeLevelName>
<shortPatternLayout class="ch.qos.logback.classic.PatternLayout">
<pattern>%m%nopex</pattern>
</shortPatternLayout>
<fullPatternLayout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d - [%thread] %-5level %logger{35} - %msg%n</pattern>
</fullPatternLayout>
<!-- 配置应用名称(服务名称),通过staticField标签可以自定义一些固定的日志字段 -->
<staticField>app_name:austin</staticField>
</encoder>
</appender>
<root level="info">
<!-- TODO console打印后面可以只针对dev环境的 -->
<appender-ref ref="CONSOLE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="GELF"/>
</root>
</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
132
133
134
135
136
137
138
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
132
133
134
135
136
137
138
当spring加载时会自动去路径下找到logback.xml的名字的文件并加载配置
另一种写法:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义全局常量 -->
<!-- 配置默认的日志级别 -->
<property name="log.level" value="debug"/>
<!-- 配置文件存放的最大日期 30天-->
<property name="log.maxHistory" value="10" />
<!-- 配文件存放的路径 根目录下的logs-->
<property name="log.filePath" value="logs"/>
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- appender用于指定日志文件输出到什么地方,以及怎么输出,相当于定义一套规范 -->
<!-- 控制台日志 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<!-- 配置日志转化成字符串 -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- debug -->
<appender name="debugAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定文件路径 -->
<file>${log.filePath}/debug.log</file>
<!-- DEBUG日志 -->
<!-- 指定滚动策略 -->
<!-- 基于时间滚动的策略:常用 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 基于时间的文件名字格式 -->
<fileNamePattern>${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<!-- 除了指定策略外,一定要指定格式String -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
<!-- 本appender只记录debug信息 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- info -->
<appender name="infoAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定文件路径 -->
<file>${log.filePath}/info.log</file>
<!-- DEBUG日志 -->
<!-- 指定滚动策略 -->
<!-- 基于时间滚动的策略:常用 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 基于时间的文件名字格式 -->
<fileNamePattern>${log.filePath}/info/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<!-- 除了指定策略外,一定要指定格式String -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
<!-- 本appender只记录debug信息 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- error -->
<appender name="errorAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定文件路径 -->
<file>${log.filePath}/error.log</file>
<!-- DEBUG日志 -->
<!-- 指定滚动策略 -->
<!-- 基于时间滚动的策略:常用 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 基于时间的文件名字格式 -->
<fileNamePattern>${log.filePath}/error/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>${log.maxHistory}</maxHistory>
</rollingPolicy>
<!-- 除了指定策略外,一定要指定格式String -->
<encoder>
<pattern>${log.pattern}</pattern>
<!-- 指定字符集防止乱码 -->
<charset>UTF-8</charset>
</encoder>
<!-- 本appender只记录debug信息 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- logger指定记录com.joofeel包下的日志,且只记录level以上水平的日志 -->
<!-- additivity表示将root中的appender-ref也加入到logger中 -->
<!-- 表示当com.joofeel.miniprogram包下有日志打印时,会采用该logger而不会采用root,如果没有在指定包的其他地方进行了日志-->
<!-- 则使用root而不是用logger。-->
<!-- 这里一定要将additivity指定为true,将root中的appeder弄到logger中,不然控制台就没有任何东西打印了-->
<logger name="com.joofeel.miniprogram" level="${log.level}" additivity="true">
<appender-ref ref="infoAppender"/>
<appender-ref ref="debugAppender"/>
<appender-ref ref="errorAppender"/>
</logger>
<root level="info">
<appender-ref ref="consoleAppender"/>
</root>
</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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
使用
@Slf4j
class UserServiceImpl{
public void deleteUser(int id){
log.info("传入id为{}",id);
}
}
1
2
3
4
5
6
2
3
4
5
6
@Slf4j是Lombok的注解,代替了一下语句
Logger log=LoggerFactory.getLogger();
1
编辑 (opens new window)
上次更新: 2024/02/22, 14:03:19