spring boot 日志简介
spring boot只依赖 Commons Logging API,而不依赖其他日志(jul、logback、log4j)。
方法1
要想使用logback,必须引入jcl-over-slf4j( 实现了 Commons Logging API),将jcl转接到slf4j。所有的spring boot starter都依赖了spring-boot-starter-web,pom如下
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
</dependencies>
可以看到spring-boot-starter-logging引入了logback,同时将log4j、jul都转接到slf4j,这就是为什么引入jcl-over-slf4j就能使logback生效的原因。
方法2
除了上述操作,还有另外一个办法,根据spring boot 2.1.13的文档说明,不用引入上述那么多的依赖,只要引入spring-boot-starter-web即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
如想修改日志级别,在application.properties中设置logging.level即可。
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
通过logging.file修改日志文件位置。
spring boot 配置logback
类路径下新建logback.xml或者logback-spring.xml,推荐使用后者。
- logback.xml还是用logback-spring.xml?
-
根据,springboot中配置logback所说,logback.xml是标准的logback配置文件,但不支持spring boot logback扩展
-
logback-spring.xml可以使用springboot logback 扩展,支持spring profile、Spring Environment,也就是通常所说的能获取yml、properties中的值,在xml中配置springProperty后方可使用yml、properties中属性值,比如
-
<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>
spring boot提供了logback的默认配置org/springframework/boot/logging/logback/base.xml,除了base.xml还有defaults.xml、console-appender.xml、file-appender.xml,提供了log_pattern、consoleAppender、FileAppender,在自定义的logback-spring.xml中,都可以引入这些文件,加以利用,
<included>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</included>
defaults.xml配置了tomcat、hibernate的日志级别,规定了控制台及文件的输出格式。
<included>
<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" />
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-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}}"/>
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
<logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/>
<logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/>
<logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/>
<logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/>
<logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/>
<logger name="org.hibernate.validator.internal.util.Version" level="WARN"/>
</included>
console-appender.xml使用了defaults.xml规定的控制台输出格式。
<included>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
</included>
file-appender.xml使用了defaults.xml规定的文件输出格式,并会按照大小和时间分片,文件最大10M。
<included>
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
<maxHistory>${LOG_FILE_MAX_HISTORY:-0}</maxHistory>
</rollingPolicy>
</appender>
</included>
配置logback只输出到文件
新建logback-spring.xml 引入 file-appender.xml,没有引入 console-appender.xml,所以不会输出到控制台。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</configuration>
开发环境输出到控制台、线上环境输出到文件
那么就可以使用logback-spring.xml中的springProfile来实现
<springProfile name="dev">
<root level="debug">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<springProfile name="!dev">
<root level="info">
<appender-ref ref="asyncFileAppender"/>
</root>
</springProfile>
logback不起作用,使用了其他日志
在实践中,往往遇到logback不起作用的情况,通过mvn dependency:tree 查看依赖,一般来说都是因为引入了其它日志实现(log4j、apache commons log)导致,控制台一般会有提示,这种情况,排除掉其他日志实现 即可。比如
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
问题
笔者在实践中,遇到了root配置的debug级别,过滤器目标级别是INFO,实际info、warn、error都输出的问题;
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
</filter>
</appender>
<springProfile name="dev">
<root level="debug">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
LevelFilter过滤器只有INFO级别才会匹配,这个从源码可以得知
ch.qos.logback.classic.filter.LevelFilter
public FilterReply decide(ILoggingEvent event) {
if (!isStarted()) {
return FilterReply.NEUTRAL;
}
if (event.getLevel().equals(level)) {
return onMatch;
} else {
return onMismatch;
}
}
不禁想到info、warn等会产生mismatch,mistach采用的是NEUTRAL(中立),
ch.qos.logback.core.filter.AbstractMatcherFilter
protected FilterReply onMismatch = FilterReply.NEUTRAL;
查阅官方文档Filters,当结果是NEUTRAL时,如果没有下一个filter则正常输出,否则交给下一个filter处理,至此真相大白;
Filters are organized as an ordered list and are based on ternary
logic. The decide(ILoggingEvent event) method of each filter is called
in sequence. This method returns one of the FilterReply enumeration
values, i.e. one of DENY, NEUTRAL or ACCEPT. If the value returned by
decide() is DENY, then the log event is dropped immediately without
consulting the remaining filters. If the value returned is NEUTRAL,
then the next filter in the list is consulted. If there are no further
filters to consult, then the logging event is processed normally. If
the returned value is ACCEPT, then the logging event is processed
immediately skipping the invocation of the remaining filters.
要想自定义mismatch,添加onMismatch标签即可,这样配置就会只输出INFO级别;
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMismatch>DENY</onMismatch>
</filter>
除了LevelFilter过滤器,还有ch.qos.logback.classic.filter.ThresholdFilter,这种是大于等于指定级别才会输出,这个可以从源码中得知。
ch.qos.logback.classic.filter.ThresholdFilter
public FilterReply decide(ILoggingEvent event) {
if (!isStarted()) {
return FilterReply.NEUTRAL;
}
if (event.getLevel().isGreaterOrEqual(level)) {
//大于等于指定级别返回中立
return FilterReply.NEUTRAL;
} else {
return FilterReply.DENY;
}
}
总结
spring boot使用logback
- 引入
spring-boot-starter-web - 如果只改变日志级别,在
application.properties中配置logging.level即可 - 细粒度的控制,新建
logback-spring.xml,酌情引入defaults.xml、console-appender.xml、file-appender.xml
LevelFilter和ThresholdFilter
- LevelFilter只有等于指定级别才会输出
- ThresholdFilter大于等于指定级别才会输出
本文详细介绍SpringBoot中Logback的配置方法,包括如何引入依赖、配置日志级别、定制日志输出格式以及如何实现不同环境下的日志输出策略。
1万+

被折叠的 条评论
为什么被折叠?



