场景需求
console client 日志记录业务场景如下:
- error 日志单独记录到error.log
- 非error 日志记录到client.log
- 日志按照时间和大小进行滚动,且限制日志总量大小
原始配置
为满足以上日志打印需求,原始logback配置如下图所示:
发现问题
为验证日志滚动问题,将上图中的配置的500MB,改为50KB,并重启console client
现象描述:
(1)client.log 文件大小达到50KB后,不再有日志打印输出,且没有预期的滚动日志.zip产生
(2)前几次client 均可正常启动,重启几次后发现client 不能正常启动,且日志输出停留在如下所示的语句
2020-09-03-09:40:27.525 DEBUG [main]-org.springframework.boot.StartupInfoLogger:53>>Running with Spring Boot v2.1.0.RELEASE, Spring v5.1.2.RELEASE
2020-09-03-09:40:27.528 INFO [main]-org.springframework.boot.SpringApplication:675>>No active profile set, falling back to default profiles: default
经多次操作后,最终发现,前几次启动正常是因为,1\. 启动前删除了log文件所在目录 2\. client.log 的大小 < 50KB,两者均没有出发日志trigger的条件
解决问题
日志排查
根据日志显示“No active profile set, falling back to default profiles: default” 为spring boot 日志,且client jar 启动时,通过-Dspring.config.location参数指定了配置文件,因此,此日志不具备参考价值
logback 文档排查
(1)以下为官网中关于RollingFileAppender描述
可见RollingPolicy负责具体的rollover,TriggeringPolicy负责rollover的时机条件
在使用的时候,RollingFileAppender必须配置RollingPolicy和TriggeringPolicy,然而,如果RollingPolicy同时实现了TriggeringPolicy的接口,只配置RollingPolicy即可。
(2)关于SizeAndTimeBasedRollingPolicy的描述,fileNamePattern中的%i和%d是必须要配置的,且在当前的时间周期内日志文件的index从0开始递增
修改logback配置,进行尝试
查看SizeAndTimeBasedRollingPolicy的继承结构,发现实现了TriggeringPolicy接口,尝试去掉原始配置文件中的TriggeringPolicy。
重启验证,日志如期滚动和压缩
查看源码,找到根因
根据RollingFileAppender的描述,在trigger条件达到时,应该触发SizeAndTimeBasedRollingPolicy,且其本身实现的trigger也是对文件大小进行检查
logback版本:1.2.3
经过对源码的查看和跟踪发现:
虽然两种trigger下,rollover的策略都是使用的SizeAndTimeBasedFNATP的rollover,但
SizeBasedTriggeringPolicy检查rollover条件时,仅对文件大小进行比对
SizeAndTimeBasedFNATP检查rollover条件时,不仅对文件大小进行比对,同时还处理变量elapsedPeriodsFileName,即对上个滚动周期的日志文件名称进行处理,即对fileNamePattern进行处理,变量是进行日志rollover时的基础
所以当使用SizeBasedTriggeringPolicy触发时,此变量为空,导致日志不能正常rollover
结论
SizeAndTimeBasedRollingPolicy 和 SizeBasedTriggeringPolicy 不可同时使用,
SizeAndTimeBasedRollingPolicy内部依赖 SizeAndTimeBasedFNATP 已经实现了 TriggeringPolicy,无须单独配置
验证问题
最终配置如下图:
日志如期正常滚动