聊聊logback的TimeBasedRollingPolicy
序
本文主要研究一下logback的TimeBasedRollingPolicy
TimeBasedRollingPolicy
public class TimeBasedRollingPolicy<E> extends RollingPolicyBase implements TriggeringPolicy<E> {static final String FNP_NOT_SET = "The FileNamePattern option must be set before using TimeBasedRollingPolicy. ";// WCS: without compression suffixFileNamePattern fileNamePatternWithoutCompSuffix;private Compressor compressor;private RenameUtil renameUtil = new RenameUtil();Future<?> compressionFuture;Future<?> cleanUpFuture;private int maxHistory = UNBOUNDED_HISTORY;protected FileSize totalSizeCap = new FileSize(UNBOUNDED_TOTAL_SIZE_CAP);private ArchiveRemover archiveRemover;TimeBasedFileNamingAndTriggeringPolicy<E> timeBasedFileNamingAndTriggeringPolicy;boolean cleanHistoryOnStart = false;//......
}
TimeBasedRollingPolicy继承了RollingPolicyBase,它定义了maxHistory、cleanHistoryOnStart、timeBasedFileNamingAndTriggeringPolicy等属性
start
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 DefaultTimeBasedFileNamingAndTriggeringPolicy<>();}timeBasedFileNamingAndTriggeringPolicy.setContext(context);timeBasedFileNamingAndTriggeringPolicy.setTimeBasedRollingPolicy(this);timeBasedFileNamingAndTriggeringPolicy.start();if (!timeBasedFileNamingAndTriggeringPolicy.isStarted()) {addWarn("Subcomponent did not start. TimeBasedRollingPolicy will not start.");return;}// 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 != UNBOUNDED_HISTORY) {archiveRemover = timeBasedFileNamingAndTriggeringPolicy.getArchiveRemover();archiveRemover.setMaxHistory(maxHistory);archiveRemover.setTotalSizeCap(totalSizeCap.getSize());if (cleanHistoryOnStart) {addInfo("Cleaning on start up");Instant now = Instant.ofEpochMilli(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime());cleanUpFuture = archiveRemover.cleanAsynchronously(now);}} else if (!isUnboundedTotalSizeCap()) {addWarn("'maxHistory' is not set, ignoring 'totalSizeCap' option with value [" + totalSizeCap + "]");}super.start();}
start方法根据fileNamePatternStr创建FileNamePattern,根据compressionMode创建Compressor,对于zip压缩的创建zipEntryFileNamePattern,另外默认设置了DefaultTimeBasedFileNamingAndTriggeringPolicy,然后执行其start,对于maxHistory不为0的,则设置archiveRemover
stop
public void stop() {if (!isStarted())return;waitForAsynchronousJobToStop(compressionFuture, "compression");waitForAsynchronousJobToStop(cleanUpFuture, "clean-up");super.stop();}private void waitForAsynchronousJobToStop(Future<?> aFuture, String jobDescription) {if (aFuture != null) {try {aFuture.get(CoreConstants.SECONDS_TO_WAIT_FOR_COMPRESSION_JOBS, TimeUnit.SECONDS);} catch (TimeoutException e) {addError("Timeout while waiting for " + jobDescription + " job to finish", e);} catch (Exception e) {addError("Unexpected exception while waiting for " + jobDescription + " job to finish", e);}}}
stop方法执行waitForAsynchronousJobToStop,主要是等待compressionFuture及cleanUpFuture
rollover
public void rollover() throws RolloverFailure {// when rollover is called the elapsed period's file has// been already closed. This is a working assumption of this method.String elapsedPeriodsFileName = timeBasedFileNamingAndTriggeringPolicy.getElapsedPeriodsFileName();String elapsedPeriodStem = FileFilterUtil.afterLastSlash(elapsedPeriodsFileName);if (compressionMode == CompressionMode.NONE) {if (getParentsRawFileProperty() != null) {renameUtil.rename(getParentsRawFileProperty(), elapsedPeriodsFileName);} // else { nothing to do if CompressionMode == NONE and parentsRawFileProperty ==// null }} else {if (getParentsRawFileProperty() == null) {compressionFuture = compressor.asyncCompress(elapsedPeriodsFileName, elapsedPeriodsFileName,elapsedPeriodStem);} else {compressionFuture = renameRawAndAsyncCompress(elapsedPeriodsFileName, elapsedPeriodStem);}}if (archiveRemover != null) {Instant now = Instant.ofEpochMilli(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime());this.cleanUpFuture = archiveRemover.cleanAsynchronously(now);}}
rollover方法通过timeBasedFileNamingAndTriggeringPolicy获取elapsedPeriodsFileName,然后将当前文件重命名为elapsedPeriodsFileName,对于archiveRemover不为null的则执行cleanAsynchronously
ArchiveRemover
ch/qos/logback/core/rolling/helper/ArchiveRemover.java
public interface ArchiveRemover extends ContextAware {void clean(Instant instant);void setMaxHistory(int maxHistory);void setTotalSizeCap(long totalSizeCap);Future<?> cleanAsynchronously(Instant now);
}
ArchiveRemover定义了clean、setMaxHistory、setTotalSizeCap、cleanAsynchronously方法
TimeBasedArchiveRemover
ch/qos/logback/core/rolling/helper/TimeBasedArchiveRemover.java
public class TimeBasedArchiveRemover extends ContextAwareBase implements ArchiveRemover {static protected final long UNINITIALIZED = -1;// aim for 32 days, except in case of hourly rollover, see// MAX_VALUE_FOR_INACTIVITY_PERIODSstatic protected final long INACTIVITY_TOLERANCE_IN_MILLIS = 32L * (long) CoreConstants.MILLIS_IN_ONE_DAY;static final int MAX_VALUE_FOR_INACTIVITY_PERIODS = 14 * 24; // 14 days in case of hourly rolloverfinal FileNamePattern fileNamePattern;final RollingCalendar rc;private int maxHistory = CoreConstants.UNBOUNDED_HISTORY;private long totalSizeCap = CoreConstants.UNBOUNDED_TOTAL_SIZE_CAP;final boolean parentClean;long lastHeartBeat = UNINITIALIZED;public TimeBasedArchiveRemover(FileNamePattern fileNamePattern, RollingCalendar rc) {this.fileNamePattern = fileNamePattern;this.rc = rc;this.parentClean = computeParentCleaningFlag(fileNamePattern);}//......
}
TimeBasedArchiveRemover定义了fileNamePattern、rollingCalendar、maxHistory、totalSizeCap属性
clean
public void clean(Instant now) {long nowInMillis = now.toEpochMilli();// 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;Instant instantOfPeriodToClean = rc.getEndOfNextNthPeriod(now, offset);cleanPeriod(instantOfPeriodToClean);}}public void cleanPeriod(Instant instantOfPeriodToClean) {File[] matchingFileArray = getFilesInPeriod(instantOfPeriodToClean);for (File f : matchingFileArray) {addInfo("deleting " + f);f.delete();}if (parentClean && matchingFileArray.length > 0) {File parentDir = getParentDir(matchingFileArray[0]);removeFolderIfEmpty(parentDir);}}
clean方法主要是计算periodsElapsed,然后通过rollingCalendar获取instantOfPeriodToClean,再执行cleanPeriod方法;cleanPeriod方法则通过getFilesInPeriod获取对应的文件,然后挨个执行delete,最后再判断下parentDir是否为空,为空则删除
cleanAsynchronously
public Future<?> cleanAsynchronously(Instant now) {ArhiveRemoverRunnable runnable = new ArhiveRemoverRunnable(now);ExecutorService executorService = context.getExecutorService();Future<?> future = executorService.submit(runnable);return future;}public class ArhiveRemoverRunnable implements Runnable {Instant now;ArhiveRemoverRunnable(Instant now) {this.now = now;}@Overridepublic void run() {clean(now);if (totalSizeCap != UNBOUNDED_TOTAL_SIZE_CAP && totalSizeCap > 0) {capTotalSize(now);}}}
cleanAsynchronously主要是创建ArhiveRemoverRunnable,然后提交到context的executorService;ArhiveRemoverRunnable实现了Runnable接口,其run方法执行clean,对于totalSizeCap大于0的执行capTotalSize
小结
TimeBasedRollingPolicy包含了RollingPolicy及TriggeringPolicy,其rollover方法主要是委托给timeBasedFileNamingAndTriggeringPolicy获取elapsedPeriodsFileName然后去rename,对于maxHistory不是无限制的设置timeBasedFileNamingAndTriggeringPolicy的archiveRemover的maxHistory及totalSizeCap,执行其cleanAsynchronously方法;其isTriggeringEvent方法也是委托给了timeBasedFileNamingAndTriggeringPolicy。
相关文章:
聊聊logback的TimeBasedRollingPolicy
序 本文主要研究一下logback的TimeBasedRollingPolicy TimeBasedRollingPolicy public class TimeBasedRollingPolicy<E> extends RollingPolicyBase implements TriggeringPolicy<E> {static final String FNP_NOT_SET "The FileNamePattern option must…...
numpy 基础使用
NumPy是Python中科学计算的基础包。它是一个Python库,提供多维数组对象,各种派生对象(如掩码数组和矩阵),以及用于数组快速操作的各种API,有包括数学、逻辑、形状操作、排序、选择、输入输出、离散傅立叶变…...
sqlite3编译脚本
../configure --hostarm --buildx86 CC/opt/sdk/gcc-arm-8.3-arm-armv5t-linux-gnueabi/bin/arm-armv5t-linux-gnueabi-gcc --prefix/opt/sdk/gcc-arm-8.3-arm-armv5t-linux-gnueabi/arm-armv5t-linux-gnueabi/sysroot/usr...
环形链表解析(c语言)c语言版本!自我解析(看了必会)
目录 1.判断一个表是否是环形链表! 代码如下 解析如下 2.快指针的步数和慢指针的步数有什么影响(无图解析) 3.怎么找到环形链表的入环点 代码如下 解析如下 1.判断一个表是否是环形链表! 代码如下 bool hasCycle(struct L…...
科技云报道:数智化升级,如何跨越数字世界与实体产业的鸿沟?
科技云报道原创。 数智化是当下商业环境下最大的确定性。 2022年,中国数字经济规模达50.2万亿元,占国内生产总值比重提升至41.5%,数字经济成为推动经济发展的重要引擎。从小型创业公司到跨国巨头,数字化转型在企业发展历程中彰显…...
Rt-Thread 移植6--多线程(KF32)
6.1 就绪列表 6.1.1 线程就绪优先级组 线程优先级表的索引对应的线程的优先级。 为了快速的找到线程在线程优先级表的插入和移出的位置,RT-Thread专门设计了一个线程就绪优先级组。线程就绪优先组是一个32位的整型数,每一个位对应一个优先级ÿ…...
HarmonyOS应用开发-首选项与后台通知管理
首选项 在移动互联网蓬勃发展的今天,移动应用给我们生活带来了极大的便利,这些便利的本质在于数据的互联互通。因此在应用的开发中数据存储占据了非常重要的位置,HarmonyOS应用开发也不例外。本章以HarmonyOS的首选项为例,介绍了…...
通过easyexcel导出数据到excel表格
这篇文章简单介绍一下怎么通过easyexcel做数据的导出,使用之前easyui构建的歌曲列表crud应用,添加一个导出按钮,点击的时候直接连接后端接口地址,在后端的接口完成数据的导出功能。 前端页面完整代码 let editingId; let request…...
Android---MVP 中 presenter 声明周期的管理
我们经常在 Android MVP 架构中的 Presenter 层做一些耗时操作,比如请求网络数据,然后根据请求后的结果刷新 View。但是,如果按返回结束 Activity,而 Presenter 依然在执行耗时操作。那么就有可能造成内存泄漏,严重时甚…...
Oracle中的索引碎片
索引碎片是指索引在存储空间上不连续的分布情况,它可能会影响到数据库性能和查询效率。索引碎片化主要由以下几个原因导致: 插入、更新和删除操作:当对表中的数据进行插入、更新或删除操作时,索引也需要相应地更新。这些DML操作可…...
Java必刷入门递归题×5(内附详细递归解析图)
目录 1.求N的阶乘 2.求12...N的和 3.顺序打印数字的每一位 4.求数字的每一位之和 5.求斐波拉契数列 1.求N的阶乘 (1)解析题目意思 比如求5的阶乘,符号表示就是5!;所以5!5*4*3*2*1我们下面使用简单的…...
android 闪屏图适配尺寸
不同的 Android 设备可能具有不同的屏幕尺寸和分辨率,因此最好提供不同尺寸的启动画面图像,以确保与各种设备的兼容性。 以下是 Android 启动画面图像的一些最常见尺寸: 320 x 480像素(肖像) 480 x 320像素࿰…...
正则表达式中(?s)与(?m)的区别
理论: (?m) 和 (?s) 是正则表达式中的两个模式标志,它们具有不同的作用: (?m) 多行模式标志(也称为 “multiline” 模式): 默认情况下,正则表达式将整个输入字符串视为单行多行文本中使用…...
Clickhouse学习笔记(11)—— 数据一致性
使用合并树引擎时,无论是ReplacingMergeTree还是SummingMergeTree,都只能保证数据的最终一致性,因为数据的去重、聚合等操作会在数据合并的期间进行,而合并会在后台以一个不确定的时间进行,因此无法预先计划࿱…...
【uniapp】六格验证码输入框实现
效果图 代码实现 <view><view class"tips">已发送验证码至<text class"tips-phone">{{ phoneNumber }}</text></view><view class"code-input-wrap"><input class"code-input" v-model"…...
【react hook】在react hook组件中,使用Antd Table组件,columns数据异步获取,list数据更新但没有rerender解决办法
情景描述 我们有一个react组件,显示了一个Antd Table组件,设置了一个columns变量并复制给Table的columns属性,由于我们请求的datasource来源是异步的,示例伪代码如下: const [columns, setColumns] useState([]); /…...
ChatGPT的图识别来了
前几天ChatGPT推出了Dall-E 3功能,可以根据文字和描述一段话来生成一个或者一组图。 这次又来重磅了,图识别又来了!换句话说,也即是文生图,图生文都可以实现了,一起来试试 1、解释图中的意思 ࿰…...
java Stream编程笔记
文章目录 Stream介绍什么是 Stream? Stream中间操作过滤操作(filter)映射操作(map)排序操作(sorted)截断操作(limit 和 skip) Stream 的终止操作forEach 和 peek聚合操作…...
顶顶通语音识别使用说明
介绍 顶顶通语音识别软件(asrproxy)是一个对接了多种语音识别接口的语音识别系统。可私有化部署(支持中文英文和方言等,支持一句话识别、实时流识别、多声道录音文件识别。 原理 asrproxy内嵌了阿里达摩院的开源语音识别工具包FunASR,后续我们也会使用自有的预料…...
重磅发布 OpenAI 推出用户自定义版 ChatGPT
文章目录 重磅发布 OpenAI 推出用户自定义版 ChatGPT个人简介 重磅发布 OpenAI 推出用户自定义版 ChatGPT OpenAI 首届开发者大会 (OpenAI DevDay) 于北京时间 11 月 7 日凌晨 02:00 开始,大会上宣布了一系列平台更新。其中一个重要更新是用户可以创建他们自己的自定…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
