Springboot [日志管理LogBack]
# Spring Boot 的日志详解
# 日志框架的介绍
Logback 是由 log4j 创始人设计的另一个开源日志组件,官方网站: http://logback.qos.ch。它当前分为下面下个模块:
- logback-core:其它两个模块的基础模块
- logback-classic:它是 log4j 的一个改良版本,同时它完整实现了 slf4j API 使你可以很方便地更换成其它日志系统如 log4j 或 JDK14 Logging
- logback-access:访问模块与 Servlet 容器集成提供通过 Http 来访问日志的功能 Spring Boot 默认使用的是 Logback 这个日志框架,一般而言,使用默认的就足够了,如果读者不习惯的话,只需要更换对应框架的 Starter 就足够了。
# 日志格式
- 日期时间:精确到毫秒
- 日志级别:ERROR, WARN, INFO, DEBUG or TRACE
- 进程 id
- 分割符:用于区分实际的日志记录
- 线程名:括在方括号中
- 日志名字:通常是源类名
- 日志信息
# 加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
2
3
4
# 更改配置
- application.properties
server.port=8888
spring.output.ansi.enabled=always
logging.level.org.springframework.web=warn
logging.level.root=INFO
logging.path=D:/java/log
logging.file.max-size=10MB
#写入文件的格式
#logging.pattern.file=
2
3
4
5
6
7
8
- 控制台输出 日志级别从低到高分为 TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为 WARN,则低于 WARN 的信息都不会输出。 Spring Boot 中默认配置 ERROR、WARN 和 INFO 级别的日志输出到控制台。您还可以通过启动您的应用程序--debug 标志来启用“调试”模式(开发的时候推荐开启)
- 文件输出
默认情况下,Spring Boot 将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,则需在 application.properties 中设置 logging.file 或 logging.path 属性。
- logging.file,设置文件,可以是绝对路径,也可以是相对路径。如:logging.file=my.log
- logging.path,设置目录,会在该目录下创建 spring.log 文件,并写入日志内容,如:logging.path=/var/log 如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log 文件夹生成一个日志文件为 spring.log 注:二者不能同时使用,如若同时使用,则只有 logging.file 生效 默认情况下,日志文件的大小达到 10MB 时会切分一次,产生新的日志文件,默认级别为:ERROR、WARN、INFO
# logback 的配置介绍
Logger、appender 及 layout Logger 作为日志的记录器,把它关联到应用的对应的 context 上后,主要用于存放日志对象,也可以定义日志类型、级别。 Appender 主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、PostreSQL、 Oracle 和其他数据库、 JMS 和远程 UNIX Syslog 守护进程等。 Layout 负责把事件转换成字符串,格式化的日志信息的输出。
logger context 各个 logger 都被关联到一个 LoggerContext,LoggerContext 负责制造 logger,也负责以树结构排列各 logger。其他所有 logger 也通过 org.slf4j.LoggerFactory 类的静态方法 getLogger 取得。 getLogger 方法以 logger 名称为参数。用同一名字调用 LoggerFactory.getLogger 方法所得到的永远都是同一个 logger 对象的引用。
有效级别及级别的继承 Logger 可以被分配级别。级别包括:TRACE、DEBUG、INFO、WARN 和 ERROR,定义于 ch.qos.logback.classic.Level 类。如果 logger 没有被分配级别,那么它将从有被分配级别的最近的祖先那里继承级别。root logger 默认级别是 DEBUG。
打印方法与基本的选择规则 打印方法决定记录请求的级别。例如,如果 L 是一个 logger 实例,那么,语句 L.info("..")是一条级别为 INFO 的记录语句。记录请求的级别在高于或等于其 logger 的有效级别时被称为被启用,否则,称为被禁用。记录请求级别为 p,其 logger 的有效级别为 q,只有则当 p>=q 时,该请求才会被执行。 该规则是 logback 的核心。级别排序为:
TRACE < DEBUG < INFO < WARN < ERROR
# 自定义日志配置
由于日志服务一般都在 ApplicationContext 创建前就初始化了,它并不是必须通过 Spring 的配置文件控制。因此通过系统属性和传统的 Spring Boot 外部配置文件依然可以很好的支持日志控制和管理。 根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:
- Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
- Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
- Log4j2:log4j2-spring.xml, log4j2.xml
- JDK (Java Util Logging):logging.properties Spring Boot 官方推荐优先使用带有-spring 的文件名作为你的日志配置(如使用 logback-spring.xml,而不是 logback.xml),命名为 logback-spring.xml 的日志配置文件,spring boot 可以为它添加一些 spring boot 特有的配置项(下面会提到)。 上面是默认的命名规则,并且放在 src/main/resources 下面即可。
logging.config=classpath:logging-config.xml
- 下面我们来看看一个普通的 logback-spring.xml 例子
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>spring-boot-logging</contextName>
<property name="logPath" value="log"/>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--<file>${logPath}/spring-boot-logging.log</file>-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
<!-- 日志保存周期 -->
<maxHistory>30</maxHistory>
<!-- 总大小 -->
<totalSizeCap>100KB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</root>
<logger name="cn.andyoung.logback.controller" level="WARN">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</logger>
</configuration>
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
# logback.xml 常用配置详解
- scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为 true。
- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当 scan 为 true 时,此属性生效。默认的时间间隔为 1 分钟。
- debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 运行状态。默认值为 false。
# 根节点<configuration>
的子节点:
<configuration>
下面一共有 2 个属性,3 个子节点,分别是:
# 属性一:设置上下文名称<contextName>
每个 logger 都关联到 logger 上下文,默认上下文名称为“default”。但可以使用<contextName>
设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过%contextName
来打印日志上下文名称。
<contextName>logback</contextName>
# 属性二:设置变量<property>
用来定义变量值的标签,<property>
有两个属性,name 和 value;其中 name 的值是变量的名称,value 的值时变量定义的值。通过<property>
定义的值会被插入到 logger 上下文中。定义变量后,可以使“${}”来使用变量。
<property name="logPath" value="log"/>
# 子节点一<appender>
appender 用来格式化日志输出节点,有俩个属性 name 和 class,class 用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。
# 控制台输出 ConsoleAppender:
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n</pattern>
</encoder>
</appender>
2
3
4
5
6
7
8
9
<encoder>
表示对日志进行编码:- %d{HH: mm:ss.SSS}——日志输出时间
- %thread——输出日志的进程名字,这在 Web 应用以及异步任务处理中很有用
- %-5level——日志级别,并且使用 5 个字符靠左对齐
- %logger{36}——日志输出者的名字
- %msg——日志消息
- %n——平台的换行符
ThresholdFilter 为系统定义的拦截器,例如我们用 ThresholdFilter 来过滤掉 ERROR 级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~
# FileAppender:把日志添加到文件,有以下子节点:
<file>
:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。<append>
:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是 true。<encoder>
:对记录事件进行格式化。(具体参数稍后讲解 )<prudent>
:如果是 true,日志会被安全的写入文件,即使其他的 FileAppender 也在向此文件做写入操作,效率低,默认是 false。
# RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件
另一种常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。RollingFileAppender 用于切分文件日志:
<file>
:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。<append>
:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是 true。<rollingPolicy>
:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。属性 class 定义具体的滚动策略类class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。有以下子节点:<fileNamePattern>
:必要节点,包含文件名及“%d”转换符,“%d”可以包含一个 java.text.SimpleDateFormat 指定的时间格式,如:%d{yyyy-MM}。如果直接使用 %d,默认格式是 yyyy-MM-dd。RollingFileAppender 的 file 字节点可有可无,通过设置 file,可以为活动文件和归档文件指定不同位置,当前日志总是记录到 file 指定的文件(活动文件),活动文件的名字不会改变;如果没设置 file,活动文件的名字会根据 fileNamePattern 的值,每隔一段时间改变一次。“/”或者“\”会被当做目录分隔符。<maxHistory>
: 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每个月滚动,且<maxHistory>
是 6,则只保存最近 6 个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除。
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"
: 查看当前活动文件的大小,如果超过指定大小会告知 RollingFileAppender 触发当前活动文件滚动。只有一个节点:<maxFileSize>
:这是活动文件的大小,默认值是 10MB。<prudent>
:当为 true 时,不支持 FixedWindowRollingPolicy。支持 TimeBasedRollingPolicy,但是有两个限制,1 不支持也不允许文件压缩,2 不能设置 file 属性,必须留空。<triggeringPolicy>
: 告知 RollingFileAppender 合适激活滚动。class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"
根据固定窗口算法重命名文件的滚动策略。有以下子节点:<minIndex>
:窗口索引最小值<maxIndex>
:窗口索引最大值,当用户指定的窗口过大时,会自动将窗口设置为 12。<fileNamePattern>
:必须包含“%i”例如,假设最小值和最大值分别为 1 和 2,命名模式为 mylog%i.log,会产生归档文件 mylog1.log 和 mylog2.log。还可以指定文件压缩选项,
<encoder>
:对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。PatternLayoutEncoder 是唯一有用的且默认的 encoder ,有一个
<pattern>
节点,用来设置日志的输入格式。使用“%”加“转换符”方式,如果要输出“%”,则必须用“\”对“%”进行转义。还有 SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender,并不常用,这里就不详解了。 大家可以参考官方文档(http://logback.qos.ch/documentation.html),还可以编写自己的Appender。
子节点
<loger>
:用来设置某一个包或具体的某一个类的日志打印级别、以及指定<appender>
。<loger>
仅有一个 name 属性,一个可选的 level 和一个可选的 addtivity 属性。 可以包含零个或多个<appender-ref>
元素,标识这个appender
将会添加到这个 loger- name: 用来指定受此 loger 约束的某一个包或者具体的某一个类。
- level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值 INHERITED 或者同义词 NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前 loger 将会继承上级的级别。
- addtivity: 是否向上级 loger 传递打印信息。默认是 true。同
<loger>
一样,可以包含零个或多个<appender-ref>
元素,标识这个 appender 将会添加到这个 loger。
子节点
<root>
:它也是<loger>
元素,但是它是根 loger,是所有<loger>
的上级。只有一个 level 属性,因为 name 已经被命名为"root",且已经是最上级了。- level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为 INHERITED 或者同义词 NULL。 默认是 DEBUG。
# 常用 logger 配置
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/spring-boot-logging.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/spring-boot-logging.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志保存周期 -->
<maxHistory>30</maxHistory>
<!-- 总大小 -->
<totalSizeCap>100KB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
其中重要的是 rollingPolicy 的定义,上例中<fileNamePattern>
logback.%d{yyyy-MM-dd}.log</fileNamePattern>
定义了日志的切分方式——把每一天的日志归档到一个文件中,<maxHistory>
30</maxHistory>
表示只保留最近 30 天的日志,以防止日志填满整个磁盘空间。同理,可以使用%d{yyyy-MM-dd_HH-mm}来定义精确到分的日志切分方式。<totalSizeCap>
1GB</totalSizeCap
>用来指定日志文件的上限大小,例如设置为 1GB 的话,那么到了这个值,就会删除旧的日志
说明:当天的日志会记录在
spring-boot-logging.log
文件里。昨天的日志会被转移到<fileNamePattern>
logback.%d{yyyy-MM-dd}.log</fileNamePattern>
文件
# 使用 Spring 参数 日志配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false">
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<jmxConfigurator/>
<springProperty scope="context" name="appName" source="spring.application.name"/>
<contextName>${appName}</contextName>
<!-- 日志的输出目录 -->
<property name="log.path" value="./logs"/>
<!--控制台日志格式:彩色日志-->
<!-- magenta:洋红 -->
<!-- boldMagenta:粗红-->
<!-- cyan:青色 -->
<!-- white:白色 -->
<!-- magenta:洋红 -->
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) %highlight([%-5level]) %thread %green(%logger) %msg%n"/>
<!--文件日志格式-->
<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n"/>
<!--编码-->
<property name="ENCODING"
value="UTF-8"/>
<!-- 控制台日志 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- 文件日志 -->
<!-- <appender name="FILE" class="ch.qos.logback.core.FileAppender">-->
<!-- <file>${log.path}/${appName}-file.log</file>-->
<!-- <append>true</append>-->
<!-- <encoder>-->
<!-- <pattern>${FILE_LOG_PATTERN}</pattern>-->
<!-- <charset>${ENCODING}</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 要区别于其他的appender中的文件名字 -->
<file>${log.path}/${appName}.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
<!-- 设置滚动日志记录的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档路径以及格式 -->
<fileNamePattern>${log.path}/${appName}-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--归档日志文件保留的最大数量-->
<maxHistory>15</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<!-- 日志记录器 -->
<!-- <logger name="com.gkcrm" level="INFO">-->
<!-- <appender-ref ref="CONSOLE" />-->
<!-- <appender-ref ref="FILE" />-->
<!-- </logger>-->
<root level="ERROR">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING_FILE"/>
</root>
<!-- 开发环境和测试环境 -->
<springProfile name="dev,test">
<logger name="com.gkcrm.server" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING_FILE"/>
</logger>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<logger name="com.gkcrm.server" level="ERROR" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING_FILE"/>
</logger>
</springProfile>
</configuration>
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
- 01
- idea 热部署插件 JRebel 安装及破解,不生效问题解决04-10
- 02
- spark中代码的执行位置(Driver or Executer)12-12
- 03
- 大数据技术之 SparkStreaming12-12