在SpringBoot项目中使用Logback进行日志管理,Logback配置详解
Logback简介
logback 官网:https://logback.qos.ch/
logback是由log4j创始人设计的又一个开源日志组件 , 优化了log4j存在的性能问题。
logback包含了三个模块:logback-core、logback-classic、logback-access。
logback-core
是其它模块的基础设施,其它模块基于它构建,显然,logback-core
提供了一些关键的通用机制。logback-classic
的地位和作用等同于Log4J
,它也被认为是Log4J
的一个改进版,并且它实现了简单日志门面SLF4J
;logback-access
主要作为一个与Servlet
容器交互的模块,比如说tomcat
或jetty
,提供一些与HTTP
访问相关的功能。
SpringBoot的日志模块
在Spring官网,对SpringBoot日志的描述是:
SpringBoot使用 Commons Logging 来记录所有内部日志,但是实现是开放的,默认配置中支持 Java Util Logging,Log4J2 和 Logback. 。
如果使用了启动器“ Starters ”,那么将会默认使用Logback作为日志系统。
当需要配置日志信息时,可以在application.properties、application.yaml中进行简单的配置,比如日志级别。 SpringBoot默认为我们输出的日志级别为info
、warn
、error
,如果还使用其他级别的日志,可以在配置中进行配置 。
支持的日志级别有: ERROR
, WARN
, INFO
, DEBUG
, TRACE
(Logback中没有FATAL
级别,等同于ERROR
)。
日志级别 trace
< debug
< info
< warn
< error
< fatal
,高级别的日志会输出低级别的日志信息,反之不行,不区分大小写。
在application.properties中配置:
#配置根logger的输出级别,也可以直接使用大写的 LEVEL=WARN指定
logging.level.root=WARN
#指定logger的name属性为org.springframework.web,即该包下的日志级别为DEBUG
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
#指定日志输出的文件路径,/在windows下是直接定位到当前工作文件磁盘下的
logging.path=/logs
#指定日志文件的名称
logging.file=logs.log
在application.yaml中:
loggin:
level:
root: WARN
扩展Logback
SpringBoot系统配置文件中,对日志只有一些简单的配置。当无法满足使用需求时可以进行扩展,扩展时需在配置文件中自定义扩展日志配置文件名称,可以定义按模块分别打印日志等。
在 application.properties 中定义扩展的日志文件名称:
logging.config=classpath:logback-spring.xml
在application.yaml中:
logging:
config: classpath:logback-spring.xml
在官方文件中,建议Logback扩展文件命名使用logback-spring.xml,并建在 src/main/resources 目录下就能使用。
根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:
日志类型 | 扩展日志名称 |
---|---|
Logback | logback-spring.xml、logback-spring.groovy、logback.xml 、 logback.groovy |
Log4j2 | log4j2-spring.xml 、 log4j2.xml |
JDK (Java Util Logging) | logging.properties |
注:日志记录是在创建ApplicationContext之前初始化的,所以无法通过 @Configuration 文件中的 @PropertySources 去配置日志。 通过系统属性和传统的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。
logback-spring.xml配置详解
接下来说说logback中各个配置怎么使用。首先看看下面这张图,这就是logback 整个配置文件的结构 。
文末有博主自己整理的所有配置参数详解的脑图,可以保存留用。
configuration
<configuration>
是Logback配置的根节点,它可以设置以下信息。
- scan:表示配置文件如果发生改变,是否会被重新加载,默认为true。
- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是秒;当scan为true时,此属性生效。默认的时间间隔为1分钟。
- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
configuration下一些配置
(1)<include>
:用来引入外部资源文件
- resource:表示资源路径
(2)<contextName>
:每个logger都关联到logger上下文,默认上下文名称为default,但可以使用设置成其他名字,用于区分不同应用程序的记录,一旦设置,不能修改,可以通过%contextName来打印日志上下文名称
(3)<property>
:自定义变量,使用${}来使用变量
- name:变量名
- value:变量值
(4)<springProfile>
:用来指定不同环境来使不同的日志输出。在此标签内相当于隔出了一个标签块,<root>
、<logger>
等可在其中使用并配置。
-
name:使用的环境名称,多个环境使用,分开,需在application.properties文件中通过spring.profiles.active来指定当前使用的环境,可以用!+ 环境名称表示当前环境不适用,如!dev即dev下禁用此日志配置
-
<root>
:和上面的root配置一致 -
<logger>
:和上面的root配置一致
appender
(1)<appender>
:日志输出策略
- name:策略名称
- class:策略类型。
- ch.qos.logback.core.ConsoleAppender是对应的控制台输出策略;
- ch.qos.logback.core.rolling.RollingFileAppender是对应的文件输出策略。
(2)<file>
:日志输出的路径及文件名
(3)<filter>
:过滤规则,可以同时配置多个过滤规则,按照配置顺序执行。
- class:过滤器类型。
- ch.qos.logback.classic.filter.ThresholdFilter 临界值过滤器,过滤掉低于指定临界值的日志
<level>
:日志输出级别
- ch.qos.logback.classic.filter.LevelFilter 级别过滤器,被定义的日志级别根据规则过滤。
<level>
:日志输出级别<onMatch>
:级别匹配时操作。即当日志的级别和定义的level匹配时,进行的过滤操作。<onMismatch>
:不匹配时操作 。即当日志的级别和定义的level匹配时,进行的过滤操作。
- ch.qos.logback.classic.filter.ThresholdFilter 临界值过滤器,过滤掉低于指定临界值的日志
级别过滤器 操作枚举有三个:
- DENY:日志将立即被抛弃不再经过其他过滤器
- NEUTRAL:有序列表里的下个过滤器接着处理日志
- ACCEPT:日志会被立即处理,不再经过剩余过滤器
(4)<encoder>
:设置日志输出的格式。
- class: 目前仅一种输出类型,ch.qos.logback.classic.encoder.PatternLayoutEncoder 把日志转换成字节流写入文件 。
- charset:日志输出的编码。
<pattern>
:日志输出的格式。
(5)<rollingPolicy>
:设置日志切割策略。
- class:日志切割策略。
- ch.qos.logback.core.rolling.TimeBasedRollingPolicy 按天切割 ;
- SizeAndTimeBasedRollingPolicy 按天和文件大小切割 。
<fileNamePattern>
:定义了日志的切割方式,切割后存放的文件名。<maxFileSize>
:指定单个日志文件的上限大小,超限就会进行切割。<maxHistory>
:表示只保存最近多少天的日志,以防止日志填满整个磁盘空间。<totalSizeCap>
:所有日志文件总上限 。
(6) <triggeringPolicy>
: 触发策略,在切割策略进行切割的过程中,满足触发策略也可以触发切割,作为补充条件 。 SizeBasedTriggeringPolicy 按文件大小切割 。
logger
<logger>
:用来指定某一个包或者具体的类的日志打印级别。
- name:指定某个包或者具体的类。
- level:指定日志输出级别。
<level>
:指定日志输出级别。- value:指定日志输出级别。
<appender-ref>
:引用自定义的日志输出策略,就是引用<appender>
。- ref:引用日志输出策略。
- additivity:是否向上级logger传递打印信息。默认是true。
root
<root>
:用来指定最基础的日志输出级别。
- level:指定日志输出级别。
<appender-ref>
:引用自定义的日志输出策略,就是引用<appender>
。- ref:引用日志输出策略。
logger 中 additivity=true是什么样的?
我们先假设有一段代码,在该段代码中打印了各种级别的日志信息。
@RestController
public class testLogbackController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping(value = "/testLogbackController",method = RequestMethod.GET)
public void login(HttpServletRequest request, HttpServletResponse response){
//日志级别从低到高为 TRACE < DEBUG < INFO < WARN < ERROR,如果设置为WARN,则低于WARN的信息都不会输出。
logger.trace("日志输出 trace");
logger.debug("日志输出 debug");
logger.info("日志输出 info");
logger.warn("日志输出 warn");
logger.error("日志输出 error");
}
}
logger在实际使用的时候有两种情况 。
第一种:不指定级别,不指定appender的logger的配置
<root level="info">
</root>
<logger name="com.xxx.controller"/>
由于logger没设置级别,所以继承上级(此处只有根logger)的级别为info,additivity默认为true开启。
所以这个logger首先执行,然后将级别为“info”及大于“info”的日志信息传递给root。由于该logger没有定义打印方式,于是将在root的方式打印日志信息。
第二种:带有指定级别,指定appender的logger的配置
<logger name="com.xxx.controller" level="WARN" additivity="false">
<appender-ref ref="console"/>
</logger>
将级别为“WARN”及大于“WARN”的日志信息交给此logger指定的名为“console”的appender处理,不再向上级root传递打印信息。
如果你把additivity=”false”
改成additivity=”true”
的话,就会打印两次,因为打印信息向上级传递,logger本身打印一次,root接到后又打印一次。
mybatis使用Logback不打印sql语句信息问题
使用mybatis的时候,sql语句是debug下才会打印。所以想要查看sql语句的话,有以下两种操作:
- 第一种:把
<root level="info">
改成<root level="DEBUG">
这样就会打印sql,不过这样日志那边会出现很多其他消息。 - 第二种:单独给mybatis或者dao目录配置debug模式。,这样配置sql语句会打印,其他还是正常info级别。
#给dao包设置debug模式
<logger name="com.xx.dao" additivity="false">
<level value="DEBUG"/>
</logger>
#给mybatis包设置debug模式
<logger name="org.mybatis" additivity="false">
<level value="DEBUG"/>
</logger>
出现这个问题的原因是因为mybatis源代码BaseExceutor.java,在其中会判断是debug模式时才会打印sql语句。
protected Connection getConnection(Log statementLog) throws SQLException {
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
return ConnectionLogger.newInstance(connection, statementLog);
} else {
return connection;
}
}
Logback配置示例
简单示例:
?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="TRACE" />
<!-- 开发、测试环境 -->
<springProfile name="dev,test">
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="INFO" />
<logger name="com.xx.projectName" level="DEBUG" />
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<logger name="org.springframework.web" level="ERROR"/>
<logger name="org.springboot.sample" level="INFO" />
<logger name="com.xx.projectName" level="INFO" />
</springProfile>
<!-- root用来指定最基础的日志输出级别 -->
<root level="INFO">
</root>
</configuration>
Logback详细配置示例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds" debug="false">
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<contextName>logback</contextName>
<property name="log_path" value="/log"/><!-- 如果在Windows环境下使用/开头的路径,将会被指定到项目所在的盘符 -->
<!-- %d{yyyy-MM-dd HH:mm:ss.SSS}:日志输出时间,精确到分按天切割; -->
<!-- %-5level:日志级别,并且使用5个字符靠左对齐; %thread:输出日志的进程名字 -->
<!-- %logger{50}:日志输出者的名字; %msg:日志消息; %n:换行符 -->
<property name="log_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger{50} - %msg%n"/>
<property name="log_fileNamePattern" value="-%d{yyyy-MM-dd}.%i.log"/>
<property name="log_maxFileSize" value="100MB"/>
<property name="log_maxHistory" value="15"/>
<!-- 输出到控制台,一般生产环境都是后台启动,这个没太大作用 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder charset="UTF-8">
<pattern>${log_pattern}</pattern>
</encoder>
</appender>
<!-- 输出到app.log文件 -->
<appender name="APP" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_path}/app.log</file>
<encoder charset="UTF-8">
<pattern>${log_pattern}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/app${log_fileNamePattern}</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${log_maxFileSize}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>${log_maxHistory}</maxHistory>
</rollingPolicy>
</appender>
<!-- 输出到sql.log文件 -->
<appender name="SQL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_path}/sql.log</file>
<encoder charset="UTF-8">
<pattern>${log_pattern}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log_path}/sql-${log_fileNamePattern}</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${log_maxFileSize}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>${log_maxHistory}</maxHistory>
</rollingPolicy>
</appender>
<!-- 自定义包日志级别要加上additivity="false",表示不会向上传递 -->
<logger name="org.springframework">
<level value="WARN"/>
</logger>
<logger name="org.apache" additivity="false">
<level value="WARN"/>
</logger>
<logger name="org.mybatis" additivity="false">
<level value="DEBUG"/>
</logger>
<!-- dao层的sql配置 -->
<logger name="com.example.xxx.dao" level="DEBUG" additivity="false">
<appender-ref ref="SQL" />
</logger>
<!-- root用来指定最基础的日志输出级别 -->
<root level="INFO">
<appender-ref ref="APP"/>
</root>
</configuration>
Logback所有配置详解脑图
本文参考:
[1] Spring官网 :SpringBoot 官网在线说明
[2] @断橋殘雪 :SpringBoot整合logback实现对日志的管理
[3] @glmapperl :看完这个不会配置 logback ,请你吃瓜!
[4] @维1 :SpringBoot默认日志logback配置解析