有什么网站可以下做闭软件,黄骅港务集团,建筑公司企业宗旨,滕州外贸网站建设logback无法删除太久远的日志文件#xff1f;logback删除日志文件源码分析
最近发现logback配置滚动日志#xff0c;但是本地日志文件甚至还有2年前的日志文件#xff0c;服务器是却是正常的#xff01; 网上搜索了一波没有发现#xff0c;只找到说不能删除太久远的旧日志…logback无法删除太久远的日志文件logback删除日志文件源码分析
最近发现logback配置滚动日志但是本地日志文件甚至还有2年前的日志文件服务器是却是正常的 网上搜索了一波没有发现只找到说不能删除太久远的旧日志文件
我的配置
!-- 基于时间和空间的滚动日志单个文件最大10MB保留天数最大30天所以日志保留最大空间是20GB --
rollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicyfileNamePattern/root/demo/logs/hornet_%d{yyyyMMdd}.%i.log/fileNamePatternmaxFileSize10mb/maxFileSizemaxHistory30/maxHistorytotalSizeCap20GB/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 SizeAndTimeBasedRollingPolicyE extends TimeBasedRollingPolicyE {FileSize maxFileSize;Overridepublic void start() {SizeAndTimeBasedFNATPE sizeAndTimeBasedFNATP new SizeAndTimeBasedFNATPE(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 parentsuper.start();}public void setMaxFileSize(FileSize aMaxFileSize) {this.maxFileSize aMaxFileSize;}Overridepublic String toString() {return c.q.l.core.rolling.SizeAndTimeBasedRollingPolicythis.hashCode();}
}这个类什么也没写那逻辑肯定在父类 TimeBasedRollingPolicy.class
public void start() {// set the LR for our utility objectrenameUtil.setContext(this.context);// find out period from the filename patternif (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 suffixfileNamePatternWithoutCompSuffix 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 DefaultTimeBasedFileNamingAndTriggeringPolicyE();}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;}Overridepublic void run() {clean(now);if (totalSizeCap ! UNBOUNDED_TOTAL_SIZE_CAP totalSizeCap 0) {capTotalSize(now);}}}重点在 clean() 清理得到 periodsElapsed 天数然后遍历清理 (-maxHistory1)i 天 public void clean(Date now) {long nowInMillis now.getTime();// for a live appender periodsElapsed is expected to be 1int 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只能删除最近-maxHistory天到-maxHistory-32天的日志文件
补充
logback默认不会在项目启动时清理旧日志文件如果需要启动执行则需配置
cleanHistoryOnStarttrue/cleanHistoryOnStart