日志这个是一个系统重要的组成部分,不论任何系统,都会有详细的日志记录。日志对于查询问题有着至关重要的作用
背景历史
那么这个日志说起来有点故事,,在学校学习的时候,都是使用下面这俩
System.out.println()
System.err.println()
做一些必要信息的记录的 哈哈哈,虽然是很low但是你别说,还真管用嘞 哈哈哈
随着学习的深入和工作了,开始对这个日志有了一定的了解…..
以前的写法固然可以达到效果,但是在实际的开发中,难免会出现问题,比如
上线了,日志比较多,,System.out.println输出的不会长久保留,会顶掉了,,日后查问题页看不到日志….
接下来,高能时刻….让我装一下,,在下等这一刻很久了,biubiu
有位穿着格子衫,牛仔裤,运动hai的大佬 就开发了一款专门记录日志的框架 log4j 极大的解决了日志记录问题,在当时备受关注,
确实很好用,非常流行,使用的人也越来越多 于是这小伙子想着能不能 开源了这个玩意儿。
于是乎,在某天早晨,这个大佬兴致勃勃的就先找了jdk官方,想让jdk里原生支持下log4j,谁曾想,着tm的jdk不以为然,估计还傲娇的看不起小伙子,
这位大佬碰壁后骑着小破车就回去了…
越想越气,过了几天,他其上心爱的小摩托,去了 apache, 但是看门大爷看到他衣衫褴褛,不让他进去…. 淦,啊这。。。
还好,遇到了老板的大儿子tomcat,没错,就是你熟悉的那只tomcat..他看那小伙子很顺眼,,就打他去见了apache爸爸
apache二话不说,就同意了他的请求,于是乎 log4j 就成了apache的开源项目
jdk知道后,这能忍??于是乎自己开发了一个JUL
再后来,一个项目由多个小组开发,各用各的日志框架,,最后合并代码的时候出问题了,,于是乎,日志门面 出来了
什么是日志门面,就是提供统一的接口,并且做相应的适配器,转换器!可以把不同的日志实现转化为统一的
日志框架分类
- 日志门面 JCL Slf4j
- 日志实现 Log4j JCL LogBack Log4j2 …..
当jdk推出JCL之后,那个小伙子觉得apache不给力,人家都推出了日志门面,apache这一点动静页没有…于是乎就离开了
然后自己开发了一个日志门面 Slf4j 性能是十分好
再后来,由于系统对性能的要求越来越严格,log4j性能不行,,小伙子又开发了一个全新框架 logback,非常流行,,springboot默认页使用了logback
日志实现框架
log4j:几乎不用了
jul:小型的项目可以用用
logback:非常流行,性能很好 springboot默认采用
log4j2:非常流行,性能很好
日志门面
jcl:spring默认采用 JCL,全称为”Jakarta Commons Logging”,也可称为”Apache Commons Logging”。
slf4j:springboot默认采用
推荐组合
slf4j + logback (Springboot默认使用的)
slf4j + log4j2
logback 配置
方式一,通过application.yml简单配置
因为springboot默认是logback,所以通过springboot的application.yml里可以配置最基础的日志相关的信息:如下
新建一个项目springboot-log-demo,就引入web
1 |
|
springboot默认的日志级别是INFO,高于INFO的日志才会打印,如下图,我们的TRACE/DEBUG都没打印
自定义日志的级别 dev环境 com.biubiu.log包下面我们打印trace级别的日志
application-dev.yml
1 | logging: |
logging.file.name把日志存到文件中
application-dev.yml
1 | logging: |
方式二,通过logback配置文件配置日志
- 命名
官方推荐使用的xml名字的格式为:logback-spring.xml而不是logback.xml,至于为什么,因为带spring后缀的可以使用这个标签 - 位置
在resource下创建logback-spring.xml文件 - 详细配置文件
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<!--
根节点<configuration>包含三个属性:
scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,
此属性生效。默认的时间间隔为1分钟。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
这里配置的10秒钟检测一次配置文件
-->
<configuration scan="true" scanPeriod="10 seconds">
<!--
子节点<contextName>:用来设置上下文名称:每个logger都关联到logger上下文,默认上下文名称为“default”。
但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过%contextName来打印日志上下文名称
-->
<contextName>logback</contextName>
<!--
子节点<property>设置变量,类似于maven的property。用来定义变量值的标签,有两个属性,name和value;其中name的值是变量的名称,
value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。
-->
<property name="log.path" value="./log"/>
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<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" />
<!--
日志输出格式:
%-5level 日志级别
%d{yyyy-MM-dd HH:mm:ss} 日期
%c 或者%logger类的完整名称
%M method方法名
%L 行号
%thread 线程名
%m或者%msg 日志信息
%n 换行
-->
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--
子节点<appender>:appender用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,
常用就是控制台输出策略和文件输出策略。
-->
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--日志记录到文件-->
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.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}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_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}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</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为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.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}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</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}/log_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}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</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>
<!--
子节点<logger>:用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>
有三个属性:
- name:用来指定受此logger约束的某一个包或者具体的某一个类
- level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
- addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--使用mybatis的时候,sql语句只有在 debug 级别下才会打印-->
<!--<logger name="com.biubiu.mybatis.mapper" level="debug" />-->
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
-->
<root level="INFO">
</root>
<!--开发环境:打印控制台-->
<springProfile name="dev">
<logger name="com.biubiu.log" level="debug">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</logger>
</springProfile>
<!--生产环境:输出到文件-->
<!--<springProfile name="pro">
<root level="warn">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" />
<appender-ref ref="WARN_FILE" />
</root>
</springProfile>-->
</configuration>