通用基本配置和说明
<!-- 定义一个名为 "RollingFile" 的 appender,用于滚动记录日志文件 -->
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定日志文件的路径和文件名 -->
<file>${log.path}/foo.log</file>
<!-- 配置日志文件的内容编码及格式 -->
<encoder>
<!-- 设置每条日志输出的具体格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %class{36} %L - %msg%n</pattern>
<!-- 设置日志文件的字符编码为 UTF-8 -->
<charset>UTF-8</charset>
</encoder>
<!-- 配置日志文件滚动的策略,支持基于时间和大小的滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件命名模式 -->
<fileNamePattern>${log.path}/%d{yyyy-MM-dd}/foo-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 单个日志文件的最大大小限制 -->
<maxFileSize>20MB</maxFileSize>
<!-- 保留历史日志文件的最大天数,执行删除的时候会从maxHistory天前开始 -->
<maxHistory>7</maxHistory>
<!-- 所有日志文件占用磁盘空间的最大容量 -->
<totalSizeCap>10GB</totalSizeCap>
<!-- 启动时清理不再需要的日志文件 -->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
</appender>
注意最后一个配置项
建议是配置为true,这样每次启动就会检测是否需要清理过期的日志文件。
<cleanHistoryOnStart>true</cleanHistoryOnStart>
清理的触发时机和策略
- 配置了前面的启动时检查清理的属性,那么在启动时就会做一次。
- 每次写入log文件的时候也会检查一次。什么意思呢,就是我们在调用log.info、debug等输出内容的时候,具体的XXAppender实现会依据条件满足时,调用rollover();
这个需要注意,下一次可用的清理时间时初始化时候就算好的,比如按天归档清理,那么这里就是下一天00:00:00,意味着什么呢,启动之后短时间内肯定不会执行清理,而是等运行到过了当天,对吧到凌晨0点之后才会触发。 那么如果你总是重启应用,然后又没配置cleanHistoryOnStart,你猜会不会给你清理,必然不会。
执行策略
依赖上面的rollingPolicy配置,其中清理会用到的属性是maxHistory:从多少天之前开始清理,比如配置为5,那就扫描是当前日期-5天的目录下的文件。totalSizeCap:大于这个总的容量,也会触发。
常见问题
- 为什么我配置了清理,并没有清理掉文件、文件夹呢?
首先需要明白如果没有配置每次启动都检测,那么就会依赖于执行周期,如果执行周期没有被触发就不会执行。
另外如果文件夹、文件的名字被动过,不符合规则当然也扫描不到。
还有一点,多个清理策略是针对rollingPolicy的,那么多个appender对应的每一个rollingPolicy中都得配置。《当然可以自定义通用策略来替换,配置一次,按需搞即可》 - 为什么还有很久之前的文件夹放在哪里
过了执行周期了,比如你之前并为正确配置清理,才刚配置成功。
文件夹的删除规则是,必须是空文件夹,意味着里面的文件必须都先执行删除了才会删除文件夹(默认规则)。
代码简要说明
//程序启动加载配置后会初始化线程池
public synchronized ScheduledExecutorService getScheduledExecutorService() {
if (scheduledExecutorService == null) {
scheduledExecutorService = ExecutorServiceUtil.newScheduledExecutorService();
}
return scheduledExecutorService;
}
//ExecutorServiceUtil.newScheduledExecutorService方法。默认线程池大小为8,名字为“logback-” 开头
//其实最终只是创建了一个自定义线程(logback公用,不是转给清理用)名称的线程池,虽然使用的是Scheduled,使用的默认初始化是0延迟,也就是立即调用执行的)
static public ScheduledExecutorService newScheduledExecutorService() {
return new ScheduledThreadPoolExecutor(CoreConstants.SCHEDULED_EXECUTOR_POOL_SIZE, THREAD_FACTORY);
}
//如果没有cleanHistoryOnStart就执行清理,俺么就依赖于滚动策略。
//RollingFileAppender中的方法,注意这里的rollover()就是清理入口,前提是满足triggeringPolicy.isTriggeringEvent条件。
//这里的triggeringPolicy就是TimeBasedRollingPolicy(依据时间滚动),currentlyActiveFile就是配置的日志文件,比如d:\logs\foo.log,event是ILoggingEvent的实现,这里默认就是LoggingEvent
//内部先按照配置的大小、日期去比较是否要触发清理。(文件大小超过maxFileSize、或者当前日期>=下一个检查日期【默认的次略日期是按天,比如每天00点】
/**
*
* This method differentiates RollingFileAppender from its super class.
*/
@Override
protected void subAppend(E event) {
// The roll-over check must precede actual writing. This is the
// only correct behavior for time driven triggers.
// We need to synchronize on triggeringPolicy so that only one rollover
// occurs at a time
synchronized (triggeringPolicy) {
if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) {
rollover();
}
}
super.subAppend(event);
}
标签:配置,log,清理,triggeringPolicy,文件夹,归档,日志,执行,logback
From: https://www.cnblogs.com/Nuwa/p/18439453