Spring Boot 日志模块详解
Spring Boot 日志模块详解
1、日志框架介绍
市面上有许多的日志框架,比如 JUL( java.util.logging), JCL( Apache Commons Logging), Log4j, Log4j2, Logback,SLF4j,jboss-logging 等等。
Spring Boot 2.x 默认采用了 slf4j+logback 的形式 ,slf4j 是个通用的日志门面,logback 就是个具体的日志框架了,我们记录日志的时候采用 slf4j 的方法去记录日志,底层的实现就是根据引用的不同日志 jar 去判定了。所以 Spring Boot 也能自动适配 JCL、JUL、Log4J 等日志框架,它的内部逻辑就是通过特定的 JAR 包去适配各个不同的日志框架。

从上图可以看出,Spring Boot 通过 jul-to-slf4j.jar 去适配了 JUL 日志框架,通过 log4j-to-slf4j.jar 去适配了 log4j 日志框架。我们得知道,Spring 5.x 相对于 Spring 4.x 有个不同的地方就是对底层使用的日志框架有了个大的改变,去除了原来默认使用的 JCL 框架,而是采用 SLF4j 这个通用的日志门面,所以 Spring Boot 2.x 相对于 Spring Boot 1.x 来说去除了对 JCL 的适配。
Spring Boot 能自动适配所有的日志,其底层使用 slf4j+logback 的方式记录日志,引入其他框架的时候,只需要 把这个框架依赖的日志框架排除掉即可,因为 Spring Boot 会通过自己的 jar 去替代;
2、Logback 的使用
Spring Boot 底层默认使用 slf4j+logback 的方式进行日志记录 ,这里简单介绍一下 logback 的使用。
logback 日志级别从低到高分别为 TRACE, DEBUG, INFO, WARN, ERROR
我们一般是在类路径下建立一个 logback.xml,也可命名为(logback-spring.xml , logback-spring.groovy , logback.xml ,logback.groovy)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>spring-boot-logging</contextName>
<property name="log.path" value="log" />
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- 级别过滤 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/spring-boot-logging.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
<!-- 日志保存周期 -->
<maxHistory>30</maxHistory>
<!-- 总大小 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!-- logback为java中的包 -->
<logger name="com.baiding"/>
</configuration>2.1、根节点包含的属性
<configuration></configuration>- scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为 true
- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当 scan 为 true 时,此属性生效。默认的时间间隔为 1 分钟
- debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 运行状态。默认值为 false
2.2、设置上下文名称
<contextName>spring-boot-logging</contextName>每个 logger 都关联到 logger 上下文,默认上下文名称为“default”。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过 %contextName 来打印日志上下文名称。
2.3、设置变量
用来定义变量值的标签,有两个属性:name 和 value;其中 name 的值是变量的名称,value 的值时变量定义的值。通过定义的值会被插入到 logger 上下文中。定义变量后,可以使 ${} 来使用变量。
<property name="log.path" value="log" />2.4、子节点 appender
appender 用来格式化日志输出节点,有俩个属性 name 和 class,class 用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。
2.4.1、控制台输出 ConsoleAppender
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- 级别过滤 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>filter 是一个过滤器,表示对输出到控制台的日记进行过滤。有两种过滤器,分别为 LevelFilter 和 ThresholdFilter。执行一个过滤器会有返回个枚举值,即 DENY,NEUTRAL,ACCEPT 其中之一。返回 DENY,日志将立即被抛弃不再经过其他过滤器;返回 NEUTRAL,有序列表里的下个过滤器接着处理日志;返回 ACCEPT,日志会被立即处理,不再经过剩余过滤器。
其中 LevelFilter 为级别过滤器,根据日志级别进行过滤。其下有三个子节点,level 表示过滤的级别,用于配置符合过滤条件的操作,ACCEPT 符合级别的输出到控制台,用于配置不符合过滤条件的操作,DENY 不符合的拒绝输出到控制台。
ThresholdFilter为临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回 NEUTRAL;当日志级别低于临界值时,日志会被拒绝。
表示对日志进行格式化
%d{HH:mm:ss.SSS}:日志的输出时间%contextName:上下文名称%thread:输出日志的进程名字,这在 Web 应用以及异步任务处理中很有用%-5level:日志级别,并且使用 5 个字符靠左对齐%logger{36}:日志输出者的名字(一般为类名),名字最长 36 个字符,否则按照句点分割%msg:具体的日志消息%n:换行符
2.4.2、输出到文件 RollingFileAppender
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/spring-boot-logging.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
<!-- 日志保存周期 -->
<maxHistory>30</maxHistory>
<!-- 总大小 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。RollingFileAppender 用于切分文件日志。
其中 file 属性定义文件的带全路径的文件名,重要的是 rollingPolicy 的定义。
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" 是最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责触发滚动
<fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MMdd}.log.zip</fileNamePattern> 定义了日志的切分方式——把每一天的日志归档到一个文件中,同理,可以使用 %d{yyyy-MM-dd HH-mm} 来定义精确到分的日志切分方式。
<maxHistory>30</maxHistory> 表示只保留最近 30 天的日志
<totalSizeCap>1GB</totalSizeCap> 用来指定日志文件的上限大小,例如设置为 1GB 的话,那么到了这个值,就会删除旧的日志
2.5、子节点 root
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>root 节点是必选节点,用来指定最基础的日志输出级别,只有一个 level 属性,默认是 DEBUG。
其中可以包含零个或多个元素,表示我们定义的 appender 将会添加到我们定义的 loger 子节点中。
2.6、子节点 loger
<loger> 用来设置某一个包或者具体的某一个类的日志打印级别、以及指定 <appender>
<loger> 仅有一个 name 属性,一个可选的 level 和一个可选的 addtivity 属性
- name:用来指定受此 loger 约束的某一个包或者具体的某一个类。
- level:用来设置打印级别,如果未设置此属性,那么当前 loger 将会继承上级的级别。
- addtivity:是否向上级 loger 传递打印信息。默认是 true。
<loger> 的实际使用有两种情况
2.6.1、第一种是不指定 level,不指定 appender
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<logger name="com.baiding.logging.Spring BootLoggingApplicationTests"/>这时候的处理流程是:当 Spring BootLoggingApplicationTests 执行日志方法时,首先交给<logger name="com.baiding.logging.SpringBootLoggingApplicationTests"/> 处理(继承上级的 level–info),将级别大于等于 info 的日志交给 root,本身没有打印任何日志
2.6.2、第二种是指定了 level,指定了 appender
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!-- java中的包 -->
<logger name="com.baiding" level="warn" addtivity="false">
<appender-ref ref="console" />
</logger>此 logger 指定了 level 为 warn,addtivity 为 false,不在向上级传递打印信息,若设置了 <appender-ref> 属性,但没有设置 addtivity 为 false,则 com.baiding 包下的日志会先在名为 console 的 appender 记录一次,之后传递给上级,root 又会在名为 console 和 file 的 appender 记录一次,这样就打印了两次了。
Spring Boot 在使用 logback 记录日志时,推荐使用 logback-spring.xml 的格式,这样的话,日志框架就不直接加载日志的配置项,而是由 Spring Boot 解析日志配置,就可以使用 Spring Boot 的高级 Profile 功能
如下 logback-spring.xml
<springProfile name="dev">
<logger name="com.baiding" level="info"/>
</springProfile>
<springProfile name="prod">
<logger name="com.baiding" level="warn"/>
</springProfile>可以在不同的节点中使用 springProfile 功能,用于指定某段配置只在某个环境下生效 。当然使用前,要激活 profile。

