赞
踩
最近发现logback配置滚动日志,但是本地日志文件甚至还有2年前的日志文件,服务器是却是正常的!
网上搜索了一波没有发现,只找到说不能删除太久远的旧日志文件
<!-- 基于时间和空间的滚动日志,单个文件最大10MB,保留天数最大30天,所以日志保留最大空间是20GB -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>/root/demo/logs/hornet_%d{yyyyMMdd}.%i.log</fileNamePattern>
<maxFileSize>10mb</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
从配置可以看出,可以从 SizeAndTimeBasedRollingPolicy.class 着手
package ch.qos.logback.core.rolling; import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP.Usage; import ch.qos.logback.core.util.FileSize; public class SizeAndTimeBasedRollingPolicy<E> extends TimeBasedRollingPolicy<E> { FileSize maxFileSize; @Override public void start() { SizeAndTimeBasedFNATP<E> sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP<E>(Usage.EMBEDDED); if(maxFileSize == null) { addError("maxFileSize property is mandatory."); return; } else { addInfo("Archive files will be limited to ["+maxFileSize+"] each."); } sizeAndTimeBasedFNATP.setMaxFileSize(maxFileSize); timeBasedFileNamingAndTriggeringPolicy = sizeAndTimeBasedFNATP; if(!isUnboundedTotalSizeCap() && totalSizeCap.getSize() < maxFileSize.getSize()) { addError("totalSizeCap of ["+totalSizeCap+"] is smaller than maxFileSize ["+maxFileSize+"] which is non-sensical"); return; } // most work is done by the parent super.start(); } public void setMaxFileSize(FileSize aMaxFileSize) { this.maxFileSize = aMaxFileSize; } @Override public String toString() { return "c.q.l.core.rolling.SizeAndTimeBasedRollingPolicy@"+this.hashCode(); } }
这个类什么也没写,那逻辑肯定在父类 TimeBasedRollingPolicy.class
public void start() { // set the LR for our utility object renameUtil.setContext(this.context); // find out period from the filename pattern if (fileNamePatternStr != null) { fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); determineCompressionMode(); } else { addWarn(FNP_NOT_SET); addWarn(CoreConstants.SEE_FNP_NOT_SET); throw new IllegalStateException(FNP_NOT_SET + CoreConstants.SEE_FNP_NOT_SET); } compressor = new Compressor(compressionMode); compressor.setContext(context); // wcs : without compression suffix fileNamePatternWithoutCompSuffix = new FileNamePattern(Compressor.computeFileNameStrWithoutCompSuffix(fileNamePatternStr, compressionMode), this.context); addInfo("Will use the pattern " + fileNamePatternWithoutCompSuffix + " for the active file"); if (compressionMode == CompressionMode.ZIP) { String zipEntryFileNamePatternStr = transformFileNamePattern2ZipEntry(fileNamePatternStr); zipEntryFileNamePattern = new FileNamePattern(zipEntryFileNamePatternStr, context); } if (timeBasedFileNamingAndTriggeringPolicy == null) { timeBasedFileNamingAndTriggeringPolicy = new DefaultTimeBasedFileNamingAndTriggeringPolicy<E>(); } timeBasedFileNamingAndTriggeringPolicy.setContext(context); timeBasedFileNamingAndTriggeringPolicy.setTimeBasedRollingPolicy(this); timeBasedFileNamingAndTriggeringPolicy.start(); if (!timeBasedFileNamingAndTriggeringPolicy.isStarted()) { addWarn("Subcomponent did not start. TimeBasedRollingPolicy will not start."); return; } //*********** 可以看到这里有 maxHistory,也就是最大保留天数 //*********** 可以看到这里有 maxHistory,也就是最大保留天数 //*********** 可以看到这里有 maxHistory,也就是最大保留天数 //*********** 大概意思就是判断是否初始化,然后把参数设置到archiveRemover中, //*********** 后面调用archiveRemover.cleanAsynchronously方法进行清理!!! // the maxHistory property is given to TimeBasedRollingPolicy instead of to // the TimeBasedFileNamingAndTriggeringPolicy. This makes it more convenient // for the user at the cost of inconsistency here. if (maxHistory != UNBOUND_HISTORY) { archiveRemover = timeBasedFileNamingAndTriggeringPolicy.getArchiveRemover(); archiveRemover.setMaxHistory(maxHistory); archiveRemover.setTotalSizeCap(totalSizeCap.getSize()); if (cleanHistoryOnStart) { addInfo("Cleaning on start up"); Date now = new Date(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime()); cleanUpFuture = archiveRemover.cleanAsynchronously(now); } } else if (!isUnboundedTotalSizeCap()) { addWarn("'maxHistory' is not set, ignoring 'totalSizeCap' option with value ["+totalSizeCap+"]"); } super.start(); }
进入 TimeBasedArchiveRemover.class,可以看到这是一个异步任务,重点在 clean()
public Future<?> cleanAsynchronously(Date now) { ArhiveRemoverRunnable runnable = new ArhiveRemoverRunnable(now); ExecutorService executorService = context.getScheduledExecutorService(); Future<?> future = executorService.submit(runnable); return future; } public class ArhiveRemoverRunnable implements Runnable { Date now; ArhiveRemoverRunnable(Date now) { this.now = now; } @Override public void run() { clean(now); if (totalSizeCap != UNBOUNDED_TOTAL_SIZE_CAP && totalSizeCap > 0) { capTotalSize(now); } } }
重点在 clean() ,清理,得到 periodsElapsed 天数,然后遍历清理 (-maxHistory+1)+i 天
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);
}
}
重要 computeElapsedPeriodsSinceLastClean() 计算 periodsElapsed 天数
UNINITIALIZED 先判断是否初始化
periodBarriersCrossed 计算过期出天数
INACTIVITY_TOLERANCE_IN_MILLIS 默认是32天(不知道为什么???)
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;
}
logback默认不会在项目启动时清理旧日志文件,如果需要启动执行则需配置
<cleanHistoryOnStart>true</cleanHistoryOnStart>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。