1. 描述
logback的滚动策略中配置了 maxHistory 之后,日志目录下依旧存在很多(超出策略时间之外)日志。
- 环境
IDE: 2021.3
spring boot: 2.5.6 (spring-boot-starter-logging: 2.5.6 --- logback-classic: 1.2.6)
- logback配置:
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_PATH}/error/${LOG_NAME}_error.%d{yyyy-MM-dd}.part_%i.log.zip</FileNamePattern>
<!--日志文件保留天数(maxHistory属性优先级高于totalSizeCap)-->
<maxHistory>3</maxHistory>
<!-- 总文件超出大小删除老文件(需要设置maxHistory后生效) -->
<totalSizeCap>20KB</totalSizeCap>
<maxFileSize>10KB</maxFileSize>
<!-- appender启动时,进行一次日志文件清理(作用:有些存活很短时间的应用,没机会进行文件清理) -->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
2. 问题
-
配置策略,根据时间滚动,保留3天内的日志,如图,依然存在很多以前的日志文件。
-
原因: 默认第一次只清理32天内的日志内容,之后清理上一次处理之后的。超过时间之前的日志文件,不在清理范围内,所以没被清理。
3. 日志清理流程
1. 获取时间段(当前时间到上一次清理时间):日志文件清理仅限于此时间范围。
2. 计算周期(时间段内有多少个周期):如:第一次,按天就是32,按小时就是 32 * 24。
3. 找出每个周期内的日志文件。
4. 删除日志文件。
- eg:SizeAndTimeBasedRollingPolicy策略,代码如下
// 文件删除策略:TimeBasedArchiveRemover
public void clean(Date now) {
long nowInMillis = now.getTime();
// for a live appender periodsElapsed is expected to be 1
// 计算周期
int periodsElapsed = computeElapsedPeriodsSinceLastClean(nowInMillis);
lastHeartBeat = nowInMillis;
if (periodsElapsed > 1) {
addInfo("Multiple periods, i.e. " + periodsElapsed + " periods, seem to have elapsed. This is expected at application start.");
}
// 遍历清理,每个周期内文件,并删除
for (int i = 0; i < periodsElapsed; i++) {
int offset = getPeriodOffsetForDeletionTarget() - i;
Date dateOfPeriodToClean = rc.getEndOfNextNthPeriod(now, offset);
cleanPeriod(dateOfPeriodToClean);
}
}
// 计算周期
int computeElapsedPeriodsSinceLastClean(long nowInMillis) {
long periodsElapsed = 0;
if (lastHeartBeat == UNINITIALIZED) {
addInfo("first clean up after appender initialization");
periodsElapsed = rc.periodBarriersCrossed(nowInMillis, nowInMillis + INACTIVITY_TOLERANCE_IN_MILLIS);
periodsElapsed = Math.min(periodsElapsed, MAX_VALUE_FOR_INACTIVITY_PERIODS);
} else {
periodsElapsed = rc.periodBarriersCrossed(lastHeartBeat, nowInMillis);
// periodsElapsed of zero is possible for size and time based policies
}
return (int) periodsElapsed;
}