原文标题:Java日志通关(四) - Logback 介绍
原文作者:阿里云开发者
冷月清谈:
Logback提供XML、Groovy两种配置方式。XML方式默认查找resources目录下的logback-test.xml/logback.xml文件。Spring Boot还可以使用logback-spring.xml文件进行配置。
配置文件介绍
一个Logback配置文件主要包括以下标签:
- configuration:最外层的父标签
- property:定义变量
- appender:负责日志输出
- logger:设置LoggerName的打印级别
- root:logger的兜底配置
- conversionRule:定义转换规则
Appender
负责日志输出,常见Appender有:
- ch.qos.logback.core.rolling.RollingFileAppender:滚动打印日志文件
- ch.qos.logback.classic.AsyncAppender:异步打印日志,避免线程阻塞
Logger和Root
- logger:设置某个LoggerName的打印级别
- root:当LoggerName未匹配到任何logger时,兜底配置
一般建议logger配置additivity=“false”,避免日志重复打印。
SpringProfile
Spring还提供了springProfile标签,根据Spring Profiles动态调整日志信息:
<springProfile name="production">
<root level="INFO">
<appender-ref ref="APPLICATION-async"/>
</root>
</springProfile>
<springProfile name="staging,testing">
<root level="TRACE">
<appender-ref ref="APPLICATION-async"/>
</root>
</springProfile>
占位符
Logback提供了大量占位符,如:
- %logger:输出LoggerName
- %message:输出日志信息
- %level:输出日志级别
- %xException:输出异常堆栈,包括JAR包名
- %date:输出时间,可指定格式
- %n:输出换行符
Format modifiers
用于控制占位符的格式,如:%-5level
:左对齐,不足5个字符补空格。
Java API
Logback还提供了Java API,支持更复杂的业务诉求,如:
- MessageConverter:统一转换对象为JSON String输出
- MDC:自动记录traceId(Key:trace_id)
后记
详情请参考Logback官方文档。
怜星夜思:
2、Logback如何处理日志文件大小问题?
3、Spring Boot使用Logback时,如何动态调整日志级别?
原文内容
阿里妹导读
一、配置入口
-
logback-spring.xml是由 Spring Boot 找到,插入自己的上下文信息[1]并做进一步处理后再传递给Logback的,你可以在其中使用<springProfile>区分环境配置,也可以使用<springProperty>拿到Spring上下文信息(比如spring.application.name)。
-
logback.xml是由Logback自己找到的,自然不会有Spring Boot相关的能力。
二、配置文件介绍
-
confinuration:最外层的父标签,其中有几个属性配置,但项目中较少使用,就不啰嗦了;
-
property:定义变量;
-
appender:负责日志输出(一般是写到文件),我们可以通过它设置输出方案;
-
logger:用来设置某个LoggerName的打印级别;
-
root:logger的兜底配置,从而我们不必配置每个LoggerName;
-
conversionRule:定义转换规则,参考【四、Java API】;
2.1 springProperty 和 property
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<property name=“LOG_PATH” value=“${user.home}/${APP_NAME}/logs”/>
<property name=“APP_LOG_FILE” value=“${LOG_PATH}/application.log”/>
<property name=“APP_LOG_PATTERN”
value=“%date{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%X{trace_id}|%thread|%logger{20}|%message%n%exception”/>
2.2 appender
<appender name="APPLICATION" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${APP_LOG_FILE}</file> <encoder> <pattern>${APP_LOG_PATTERN}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${APP_LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern> <maxHistory>30</maxHistory> <maxFileSize>200MB</maxFileSize> <totalSizeCap>10GB</totalSizeCap> </rollingPolicy> </appender> <appender name="APPLICATION-async" class="ch.qos.logback.classic.AsyncAppender"> <queueSize>256</queueSize> <discardingThreshold>0</discardingThreshold> <neverBlock>true</neverBlock> <appender-ref ref="APPLICATION"/> </appender>
示例中涉及的变量在上一节已经提到,这里不啰嗦了。需要关注的是以下几个点:
-
ch.qos.logback.core.rolling.RollingFileAppender负责将日志滚动打印,避免单文件体积过大。具体的滚动策略都在<rollingPolicy>中指定,各配置项都还算好理解。
-
ch.qos.logback.classic.AsyncAppender负责将日志异步打印,避免大量打印日志时阻塞线程。
2.3 logger和root
<logger level="INFO" additivity="false" name="com.foo.bar"> <appender-ref ref="APPLICATION-async"/> </logger> <root level="INFO"> <appender-ref ref="APPLICATION-async"/> </root>
上面的配置指定所有LoggerName为com.foo.bar的日志以INFO级别进行打印(TRACE和DEBUG级别将不会输出),此配置绑定的输出器(appender)为APPLICATION-async。
-
com.foo.bar.service.ExampleService
-
com.foo.bar.service
-
com.foo.bar(此时命中了我们示例中的<logger>,另外因为配置了additivity="false" 所以停止继续向下查找)
-
com.foo
-
com
-
<root>
2.4 springProfile
<springProfile name="production"> <root level="INFO"> <appender-ref ref="APPLICATION-async"/> </root> </springProfile> <springProfile name="staging,testing"> <root level="TRACE"> <appender-ref ref="APPLICATION-async"/> </root> </springProfile>
三、占位符
3.1 Conversion Word
占位符
|
说明
|
%logger
|
输出LoggerName(参考【第三篇:1.1 工厂函数】节)
|
%message
|
输出你实际要打印的日志信息(参考【第三篇:3.1 info方法】节)
|
%exception
|
输出异常堆栈,对应通过Slf4j传入的异常(参考【第三篇:3.1 info方法】节)
|
%level
|
输出日志级别,即TRACE/DEBUG/INFO/WARN/ERROR/FATAL。
注意这里有别于Slf4j(参考【第三篇:二、日志级别】),多了个FATAL级别,这是为了适配Log4j而存在的。
|
%xException
|
输出异常堆栈,同时包含每行堆栈所归属的JAR包名
|
%marker
|
输出通过Marker(参考【第三篇:四、Marker】节)传入的字符串
|
%mdc
|
输出MDC(参考【第三篇:五、MDC】节)中对应的值
|
%kvp
|
输出通过addKeyValue(参考【第三篇:六、Fluent API (链式调用)】节)传入的KV对
|
%date
|
输出时间,可以添加符合ISO 8601[6]的参数指定输出格式,比如我们常用的yyyy-MM-dd HH:mm:ss
|
%thread
|
输出打印日志方法所在的线程名
|
%n
|
输出一个换行符
|
%replace(p){r, t}
|
将p中的r替换为t,r为正则。请参考【第五篇:七、将堆栈合并为一行】节
|
%nopex
|
忽略传入的堆栈,不打印。请参考【第五篇:七、将堆栈合并为一行】节
Logback会判断你的日志pattern,如果没有输出堆栈,会默认追加%exception,以保证传入的异常信息不会丢。这个占位符就是明确要求不做追加。
|
另外,针对%logger额外做一下补充。%logger的参数中可以传一个正整数,用于指定输出长度,当LoggerName长度超过限制时,Logback会以 . 为分隔智能缩短。假设LoggerName是com.example.foo.bar.ExampleService(这个字符串长度为34),那么:
配置
|
输出结果
|
说明
|
[%logger]
|
[com.example.foo.bar.ExampleService]
|
原样输出
|
[%logger{32}]
|
[c.example.foo.bar.ExampleService]
|
实际长度32,与限制值一致
|
[%logger{30}]
|
[c.e.foo.bar.ExampleService]
|
实际长度26,比限制值小。因为每一级 package要么保留原样,要么只取第一个字符
|
[%logger{10}]
|
[c.e.f.b.ExampleService]
|
实际长度20,比限制值大。因为每一级 package至少会保留一个字符,且最后一级不会被缩短
|
[%logger{0}]
|
[ExampleService]
|
0比较特殊,表示只保留最后一级,且不会被缩短
|
3.2 Format modifiers
-
-:第一个-表示不足最小长度时在右侧填充空格,即输出内容左对齐(默认是在左侧填充空格,即右对齐);
-
10:第一个数字表示输出最小长度,不足的补空格;
-
.:与后边两项配置的分隔符,本身没有含义;
-
-:第二个-表示超过最大长度时先裁剪右侧,即保留左侧字符(默认先裁剪左侧,即保留右侧字符);
-
20:第二个数字表示输出最大长度,超出部分会做裁剪;
配置
|
文本
|
输出结果
|
说明
|
[%5level]
|
INFO
|
[ INFO]
|
最小5个字符,右对齐
|
[%-5level]
|
INFO
|
[INFO ]
|
最小5个字符,左对齐
|
[%.-1level]
|
INFO
|
[I]
|
最大1个字符,优先保留左侧字符
|
[%-5,-10logger]
|
com.foo.bar.Service
|
[com.foo.ba]
|
最大10个字符,优先保留左侧字符
|
[%-5,10logger]
|
com.foo.bar.Service
|
[ar.Service]
|
最大10个字符,优先保留右侧字符
|
四、Java API
-
场景一:使用log.info("obj={}", obj) 时,如何将obj统一转JSON String后输出;
-
场景二:日志中涉及到的手机号、身份证号,如何脱敏后再记录日志;
-
场景三:Logback配置基于XML,如何不改代码不发布,也可以动态修改日志级别;
五、MDC 中的 traceId
log.info("traceId={}, blah blah blah", Span.current().getSpanContext().getTraceId());
六、后记
[1]https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.logging.logback
[2]https://logback.qos.ch/manual/configuration.html#variableSubstitution
[3]https://logback.qos.ch/manual/appenders.html
[4]https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.profiles
[5]https://logback.qos.ch/manual/layouts.html#conversionWord
[6]https://www.iso.org/iso-8601-date-and-time-format.html
[7]https://logback.qos.ch/manual/layouts.html#formatModifiers
[8]https://logback.qos.ch/apidocs/index.html
[9]https://logback.qos.ch/apidocs/ch/qos/logback/classic/pattern/MessageConverter.html
[10]https://logback.qos.ch/apidocs/ch/qos/logback/classic/LoggerContext.html
[11]https://logback.qos.ch/apidocs/ch/qos/logback/classic/Logger.html
[12]https://www.aliyun.com/product/xtrace
点击查看《》
》