log4j2的Strategy、log4j2的DefaultRolloverStrategy、删除过期文件
文章目录
- 一、DefaultRolloverStrategy
- 1.1、DefaultRolloverStrategy节点
- 1.1.1、filePattern属性
- 1.1.2、DefaultRolloverStrategy删除原理
- 1.2、Delete节点
- 1.2.1、maxDepth属性
- 二、知识扩展
- 2.1、DefaultRolloverStrategy与Delete会冲突吗?
- 2.1.1、场景一:DefaultRolloverStrategy先满足条件
- 2.1.2、场景二:DefaultRolloverStrategy保留3个,Delete删除所有
- 2.2、testMode不生效?
- 三、总结
日志文件中比较重要的就是日志文件的拆分、日志文件的删除功能。
- 日志文件拆分:按大小拆分(如每10M生成一份文件)、按时间拆分(如按日拆分)
- 日志文件删除:指定日志文件保留或删除策略,如删除100天之前的文件。
关于日志文件拆分,我们在上一篇文章《Log4j2的Policies详解》中已经说明了,接下来讲一下日志文件删除策略
一、DefaultRolloverStrategy
DefaultRolloverStrategy的主要作用是在日志文件达到一定大小或时间间隔时,自动创建新的日志文件,并对旧的日志文件进行归档或删除
。
总结一下就是:DefaultRolloverStrategy是对日志文件的归档、删除策略
<RollingFile name="RollInfo"fileName="${LOG_HOME}/info.log"filePattern="${LOG_HOME}/info_%d{yyyy-MM-dd}_%i.log.gz"><ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout pattern="${LOG_PATTERN}"/><Policies><SizeBasedTriggeringPolicy size="100K"/></Policies><DefaultRolloverStrategy fileIndex="nomax"><Delete basePath="${LOG_HOME}" maxDepth="2"><IfFileName glob="*.log.gz"><IfAny><IfAccumulatedFileSize exceeds="100M"/><IfAccumulatedFileCount exceeds="100"/><IfLastModified age="30d"/></IfAny></IfFileName></Delete></DefaultRolloverStrategy>
</RollingFile>
1.1、DefaultRolloverStrategy节点
官网地址:https://logging.apache.org/log4j/2.x/manual/appenders/rolling-file.html#DefaultRolloverStrategy
DefaultRolloverStrategy指定了当触发rollover时的默认策略。
DefaultRolloverStrategy是Log4j2提供的默认的rollover策略,即使在log4j2.xml中没有显式指明,也相当于为RollingFile配置下添加了如下语句。DefaultRolloverStrategy默认的max为7。
<DefaultRolloverStrategy max="7"/>
参数 | Type | Description |
---|---|---|
fileIndex | String | 默认值为max 。可选值为:min 、max 、nomax 。 |
min | integer | 计数器的最小值。默认值为1 |
max | integer | 计数器的最大值。默认值为7 。一旦达到这个值,旧的存档将在随后的滚动中被删除。此参数与filePattern中的计数器 %i 配合使用 |
compressionLevel | integer | 设置压缩级别,0-9,其中0 =无,1 =最佳速度,到9 =最佳压缩。仅对ZIP文件实现。默认级别7 |
tempCompressedFilePattern | String | 归档日志文件在压缩过程中的文件名模式。 |
1、max属性
max
参数指定了计数器的最大值。一旦计数器达到了最大值,过旧的文件将被删除。
注意:不要认为max参数是需要保留的日志文件的最大数目。
max
参数是与filePattern
中的计数器%i
配合起作用的,其具体作用方式与filePattern的配置密切相关。
- 如果filePattern中仅含有date/time pattern,每次rollover时,将用当前的日期和时间替换文件中的日期格式对文件进行重命名。max参数将不起作用。
如,filePattern="logs/app-%d{yyyy-MM-dd}.log"
- 如果filePattern中仅含有整数计数器(即%i),每次rollover时,文件重命名时的计数器将每次加1(初始值为1),若达到max的值,将删除旧的文件。
如,filePattern="logs/app-%i.log"
- 如果filePattern中既含有date/time pattern,又含有%i,每次rollover时,计数器将每次加1,若达到max的值,将删除旧的文件,直到data/time pattern不再符合,被替换为当前的日期和时间,计数器再从1开始。
如,filePattern="logs/app-%d{yyyy-MM-dd HH-mm}-%i.log"
比如以下设置
<RollingFile name="RollingFileInfo" fileName="/logs/info.log" filePattern="/logs/info_%i.log"><DefaultRolloverStrategy max="3"/>
</RollingFile>
这表示/logs目录下最多只能保留3个info_*.log
日志文件,当生成第四个文件时会按%i
大小顺序删除第一个文件。具体步骤可看下面的fileIndex属性示例。
2、fileIndex属性
fileIndex
设值不同,则文件归档及新文件创建及计数器递增方法都不同,计数器递增有三种方式,如下:
- 方式一:
fileIndex="max"
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="info_%i.log"><DefaultRolloverStrategy max="3"/>
</RollingFile><DefaultRolloverStrategy max="3"/> 等同于 <DefaultRolloverStrategy fileIndex="max" max="3" min="1"/>只保留3个日志文件,当到归档第4个文件时,
info-1.log 被删除,
info-2.log 被重命名为 info-1.log,
info-3.log 被重命名为 info-2.log,
info.log 被重命名为 info-3.log。
创建新的 info.log文件并继续写入。
- 方式二:
fileIndex="min"
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="info_%i.log"><DefaultRolloverStrategy fileIndex="min" max="3"/>
</RollingFile>只保留3个日志文件,当到归档第4个文件时,
info-3.log 被删除,
info-2.log 重命名为info-3.log,
info-1.log 重命名为info-2.log,
info.log 重命名为info-1.log。
创建新的 info.log文件并继续写入。
- 方式三:
fileIndex="nomax"
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="info_%i.log"><DefaultRolloverStrategy fileIndex="nomax"/>
</RollingFile>这里的fileIndex="nomax"属性值表示文件索引没有最大限制换句话说,当使用%i作为文件名中的占位符时,日志文件将无限滚动,不会因为索引达到某个上限而停止创建新的日志文件。
nomax为2.8新增属性,设置为nomax
时,将忽略DefaultRolloverStrategy的最大值和最小值,每次归档生成的新文件相对于前一个文件编号加1,没有最大文件数限制。
1.1.1、filePattern属性
官网地址:https://logging.apache.org/log4j/2.x/manual/appenders/rolling-file.html#attr-filePattern
filePattern
属性在log4j2框架中起了至关重要的作用,日志文件的重命名、删除策略都是依赖该配置。
filePattern
是RollingFile Appender的一个属性,用于指定根据何种模式生成归档滚动日志文件的名称。filePattern可以使用一些特定的占位符,以便在滚动时自动生成新的日志文件名
filePattern占位符:
%d
:日期格式化器的格式化日期。例如:2018-09-19%i
:滚动文件的索引编号,从1开始。$${date:}
:系统的当前时间
比如我们设置的
filePattern="logs/app-%d{yyyy-MM-dd-HH}-%i.log"
filePattern中的时间占位符%d在滚动时会自动更新为当前时间,索引号%i也会自动递增以避免覆盖先前的日志,所以最终会生成以下的归档文件名
app-2024-12-24-15-1.log
app-2024-12-24-15-2.log
app-2024-12-24-15-3.log
当系统时间过了2024-12-24-15点的时候,计数器又会重新开始。如:
app-2024-12-24-16-1.log
app-2024-12-24-16-2.log
1.1.2、DefaultRolloverStrategy删除原理
问题: DefaultRolloverStrategy是怎么找到文件并删除的?
DefaultRolloverStrategy主要是根据filePattern属性匹配文件并删除文件的。如
filePattern="${LOG_HOME}/$${date:yyyy-MM-dd}/info_%d{yyyy-MM-dd}_%i.log"
假设当前日期是2024-12-30,则会匹配/LOG_HOME/2024-12-30/info_2024-12-30_*.log的文件,然后按时间顺序删除。所以该策略的缺点就是不会删除其他目录下的文件。
缺点: 从上述原理中我们发现DefaultRolloverStrategy只能根据filePattern属性进行匹配删除,不会删除其他目录下的文件。
因此Log4j 2.5引入了DeleteAction,支持删除其他目录下的文件。
源码分析:
org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy.java
// org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy#rollover
/*** Performs the rollover.** @param manager The RollingFileManager name for current active log file.* @return A RolloverDescription.* @throws SecurityException if an error occurs.*/
@Override
public RolloverDescription rollover(final RollingFileManager manager) throws SecurityException {int fileIndex;// 默认 minIndex=1if (minIndex == Integer.MIN_VALUE) {final SortedMap<Integer, Path> eligibleFiles = getEligibleFiles(manager);fileIndex = eligibleFiles.size() > 0 ? eligibleFiles.lastKey() + 1 : 1;} else {if (maxIndex < 0) {return null;}final long startNanos = System.nanoTime();// 删除case1: 获取符合条件的文件数,同时清理掉大于 max 配置的日志文件// 如配置 max=5, 当前只有4个满足时, 不会立即清理文件, 但也不会阻塞后续流程// 只要没有出现错误, fileIndex 不会小于0fileIndex = purge(minIndex, maxIndex, manager);if (fileIndex < 0) {return null;}if (LOGGER.isTraceEnabled()) {final double durationMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);LOGGER.trace("DefaultRolloverStrategy.purge() took {} milliseconds", durationMillis);}}// 进入此区域即意味着,必然有文件需要滚动,重新命名了final StringBuilder buf = new StringBuilder(255);manager.getPatternProcessor().formatFileName(strSubstitutor, buf, fileIndex);final String currentFileName = manager.getFileName();String renameTo = buf.toString();final String compressedName = renameTo;Action compressAction = null;FileExtension fileExtension = manager.getFileExtension();if (fileExtension != null) {renameTo = renameTo.substring(0, renameTo.length() - fileExtension.length());compressAction = fileExtension.createCompressAction(renameTo, compressedName,true, compressionLevel);}// 未发生文件重命名情况,即文件未被重命名未被滚动// 该种情况应该不太会发生if (currentFileName.equals(renameTo)) {LOGGER.warn("Attempt to rename file {} to itself will be ignored", currentFileName);return new RolloverDescriptionImpl(currentFileName, false, null, null);}// 新建一个重命令的 action, 返回待用final FileRenameAction renameAction = new FileRenameAction(new File(currentFileName), new File(renameTo),manager.isRenameEmptyFiles());// 异步处理器,会处理用户配置的异步action,如本文配置的 DeleteAction// 它将会在稍后被提交到异步线程池中运行final Action asyncAction = merge(compressAction, customActions, stopCustomActionsOnError);// 封装Rollover返回, renameAction 是同步方法, 其他用户配置的动态action 则是异步方法// 删除case2: 封装异步返回actionreturn new RolloverDescriptionImpl(currentFileName, false, renameAction, asyncAction);
}
private int purge(final int lowIndex, final int highIndex, final RollingFileManager manager) {// 默认使用 accending 的方式进行清理文件return useMax ? purgeAscending(lowIndex, highIndex, manager) : purgeDescending(lowIndex, highIndex, manager);
}
// org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy#purgeAscending
/*** Purges and renames old log files in preparation for rollover. The oldest file will have the smallest index, the* newest the highest.** @param lowIndex low index. Log file associated with low index will be deleted if needed.* @param highIndex high index.* @param manager The RollingFileManager* @return true if purge was successful and rollover should be attempted.*/
private int purgeAscending(final int lowIndex, final int highIndex, final RollingFileManager manager) {final SortedMap<Integer, Path> eligibleFiles = getEligibleFiles(manager);final int maxFiles = highIndex - lowIndex + 1;boolean renameFiles = false;// 依次迭代 eligibleFiles, 删除while (eligibleFiles.size() >= maxFiles) {try {LOGGER.debug("Eligible files: {}", eligibleFiles);Integer key = eligibleFiles.firstKey();LOGGER.debug("Deleting {}", eligibleFiles.get(key).toFile().getAbsolutePath());// 调用nio的接口删除文件Files.delete(eligibleFiles.get(key));eligibleFiles.remove(key);renameFiles = true;} catch (IOException ioe) {LOGGER.error("Unable to delete {}, {}", eligibleFiles.firstKey(), ioe.getMessage(), ioe);break;}}final StringBuilder buf = new StringBuilder();if (renameFiles) {// 针对未完成删除的文件,继续处理// 比如使用 匹配的方式匹配文件, 则不能被正常删除// 还有些未超过maxFiles的文件for (Map.Entry<Integer, Path> entry : eligibleFiles.entrySet()) {buf.setLength(0);// LOG4J2-531: directory scan & rollover must use same formatmanager.getPatternProcessor().formatFileName(strSubstitutor, buf, entry.getKey() - 1);String currentName = entry.getValue().toFile().getName();String renameTo = buf.toString();int suffixLength = suffixLength(renameTo);if (suffixLength > 0 && suffixLength(currentName) == 0) {renameTo = renameTo.substring(0, renameTo.length() - suffixLength);}Action action = new FileRenameAction(entry.getValue().toFile(), new File(renameTo), true);try {LOGGER.debug("DefaultRolloverStrategy.purgeAscending executing {}", action);if (!action.execute()) {return -1;}} catch (final Exception ex) {LOGGER.warn("Exception during purge in RollingFileAppender", ex);return -1;}}}// 此处返回的 findIndex 一定是 >=0 的return eligibleFiles.size() > 0 ?(eligibleFiles.lastKey() < highIndex ? eligibleFiles.lastKey() + 1 : highIndex) : lowIndex;
}
1.2、Delete节点
Log4j 2.5引入了DeleteAction,允许用户自定义删除文件的策略,而不仅仅是通过DefaultRolloverStrategy默认的删除最旧文件的策略。使用DeleteAction时需要注意谨慎,以避免误删重要文件。
注意:可以删除任何文件,而不仅仅是删除日志文件,因此请谨慎使用此操作!使用testMode
参数,可以测试配置,而不会意外删除错误的文件。
参数 | Type | Description |
---|---|---|
basePath | String | 必传. 从哪里开始扫描要删除的文件的基本路径。 |
maxDepth | int | 要扫描的最大目录级别数。值为0表示仅访问basePath指定的文件本身,除非安全管理器拒绝。Integer.MAX_VALUE的值指示应访问所有级别。默认值为1,表示仅扫描basePath下的文件。 |
testMode | boolean | 如果为true,则不会删除文件,而是在INFO级别打印一条消息到状态记录器。使用此功能可以测试配置是否按预期工作。默认为false 。 |
pathConditions | PathCondition[] | 如果未指定ScriptCondition ,则为必需。可以指定一个或多个PathCondition元素。如果指定了多个PathCondition元素,则需要所有的PathCondition结果都为true才会进行删除。 PathCondition也可以嵌套。如果进行嵌套,则是先判断外层的PathCondition,然后进行内层的判断。如果没有嵌套,则是按顺序进行判断。 也可以创建自定义条件或使用内置条件 |
scriptCondition | Script, ScriptFile or ScriptRef | 如果未指定PathConditions,则为必需。指定脚本的ScriptCondition元素。ScriptCondition应该包含一个Script,ScriptRef或ScriptFile元素,该元素指定要执行的逻辑。(有关配置ScriptFiles和ScriptRefs的更多示例,另请参阅ScriptFilter文档。)该脚本传递了许多参数,包括在basePath下找到的路径列表(最大maxDepth),并且必须返回包含要删除的路径的列表。 |
maxDepth
用于指定清理或删除日志文件时搜索的目录深度,值是一个整数,表示从basePath开始向下搜索的目录层级数
- 如果maxDepth=“0”,则只会考虑basePath所指向的目录本身,不包括任何子目录。
- 如果maxDepth=“1”,则会考虑basePath所指向的目录及其直接子目录。
- 如果maxDepth=“2”,则会考虑basePath所指向的目录、其直接子目录以及这些子目录下的子目录(即二级子目录)。
内置的PathCondition条件
IfFileName
如果文件名与此参数匹配则结果为true,此参数为正则表达式或 glob的文件。IfLastModified
最后修改时间早于或等于此参数则结果为true,此参数为duration。IfAccumulatedFileCount
文件数超过指定个数则结果为true,此参数为整型。IfAccumulatedFileSize
所有文件总大小达到此参数则结果为true,此参数为KB、MB、GB。IfAll
如果此标签下的所有条件都配置成功(逻辑与),则结果为true。IfAny
如果此标签下的任何一个条件匹配成功(逻辑或),则结果为true。IfNot
如果此标签下的所有条件都不匹配(逻辑非),则结果为true。
以下是几个示例:
<RollingFile name="RollInfo"fileName="${LOG_HOME}/info.log"filePattern="${LOG_HOME}/$${date:yyyy-MM-dd}/info_%d{yyyy-MM-dd}_%i.log.gz"><DefaultRolloverStrategy fileIndex = "nomax"><Delete basePath="${LOG_HOME}" maxDepth="2"><!--由于filePattern中的格式是${baseDir}/$${date:yyyy-MM-dd},所以glob前面必须有*/相当于日期这一层级--><IfFileName glob="*/*.log.gz"/><IfLastModified age="7d"/> </Delete></DefaultRolloverStrategy>
</RollingFile>
删除7天前的${LOG_HOME}文件夹下,两层路径以内的所有.log.gz文件。其中,Delete子标签中的IfFileName和IfLastModified子标签用于指定删除条件,只有同时满足两个条件才进行删除操作
注意:
- 当maxDepth设置的深度是2时,需要注意下边删除规则glob中日志名字前需要加
*/
,表示外一层目录,不加的话日志滚动时不会删除过期日志文件。相反,如果深度是1,删除当前目录时是不需要加的。
<RollingFile name="RollInfo"fileName="${LOG_HOME}/info.log"filePattern="${LOG_HOME}/info_%d{yyyy-MM-dd}_%i.log.gz"><DefaultRolloverStrategy fileIndex = "nomax"><Delete basePath="${LOG_HOME}" maxDepth="1"><IfFileName glob="*.log.gz"><IfLastModified age="7d"><IfAny><!--文件总大小超过100M,进行删除--><IfAccumulatedFileSize exceeds="100M"/><!--文件总数量超过100,进行删除--><IfAccumulatedFileCount exceeds="100"/></IfAny></IfLastModified></IfFileName></Delete></DefaultRolloverStrategy>
</RollingFile>
<DefaultRolloverStrategy fileIndex="nomax"><!--basePath:从此处扫描需要删除的日志基本路径,maxDepth:要访问的日志目录最大级别数,默认是1 --><!--例如我们的日志是/data/logs/app/app-info.log,basePath=/data/logs,maxDepth=2 恰好能访问到app-info.log --><Delete basePath="${BASE_LOG_PATH}/${SERVER_NAME}" maxDepth="2"><!--删除,正则匹配到文件名--><IfFileName glob="*-info.*.log.gz"/><!--删除,日志距离现在多长事件,P1D代表是1天--><!--http://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/appender/rolling/action/Duration.html--><IfLastModified age="P1D"/></Delete>
</DefaultRolloverStrategy>
下面是多个Delete配置示例:
<!-- 删除策略配置 -->
<DefaultRolloverStrategy max="5000"><Delete basePath="logs/app/history" maxDepth="1"><!-- 配置且关系 --><IfFileName glob="*.log.gz"/><IfLastModified age="7d"/></Delete><!-- 配置或关系 --><Delete basePath="logs/app/history" maxDepth="1"><IfFileName glob="*.docx"/></Delete>
</DefaultRolloverStrategy>
1.2.1、maxDepth属性
maxDepth
用于指定清理或删除日志文件时搜索的目录深度,值是一个整数,表示从basePath开始向下搜索的目录层级数
- 如果maxDepth=“0”,则只会考虑basePath所指向的目录本身,不包括任何子目录。
- 如果maxDepth=“1”,则会考虑basePath所指向的目录及其直接子目录。
- 如果maxDepth=“2”,则会考虑basePath所指向的目录、其直接子目录以及这些子目录下的子目录(即二级子目录)。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration ><Properties><Property name="baseDir">logs</Property></Properties><Appenders><RollingFile name="RollingFile" fileName="${baseDir}/app.log"filePattern="${baseDir}/$${date:yyyy-MM-dd}/app-%d{yyyy-MM-dd}_%i.log.gz"><PatternLayout pattern="%d %p %c{1.} [%t] %m%n" /><CronTriggeringPolicy schedule="0 0 0 * * ?"/><DefaultRolloverStrategy><Delete basePath="${baseDir}" maxDepth="2"><!--由于filePattern中的格式是${baseDir}/$${date:yyyy-MM-dd},所以glob前面必须有*/相当于日期这一层级--><IfFileName glob="*/app-*.log.gz" /><IfLastModified age="60d" /></Delete></DefaultRolloverStrategy></RollingFile></Appenders><Loggers><Root level="error"><AppenderRef ref="RollingFile"/></Root></Loggers>
</Configuration>
上述配置文件中,Delete部分便是配置DeleteAction的删除策略,指定了当触发rollover时,删除baseDir文件夹或其子文件下面的文件名符合app-*.log.gz且距离最后的修改日期超过60天的文件。
其中,basePath指定了扫描开始路径,为baseDir文件夹。maxDepth指定了目录扫描深度,为2表示扫描baseDir文件夹及其子文件夹。
注意: 上述示例中IfFileName的glob
属性前面一定要加*/
, 因为日志文件的存储格式是/logs/2024-12-30/app-2024-12-30_1.log.gz, 如果glob属性前面没有*/
,则只会匹配/logs/app-2024-12-30_1.log.gz文件,缺少了日期这一层级。
二、知识扩展
2.1、DefaultRolloverStrategy与Delete会冲突吗?
我们知道DefaultRolloverStrategy是有自己的删除策略的,Delete标签也是删除策略,假设同时配置了DefaultRolloverStrategy与Delete属性,当两者冲突时,谁会生效?
2.1.1、场景一:DefaultRolloverStrategy先满足条件
1、场景说明
假如我们配置了DefaultRolloverStrategy的max属性最多保留3个文件,同时配置了Delete属性总文件超过15GB进行删除。当文件已经超过3个但是大小未超过15G(DefaultRolloverStrategy先满足条件),即两者的策略冲突,最后谁会生效?
<!--配置当前目录下最多留3个文件 --><DefaultRolloverStrategy max="3"><Delete basePath="${FILE_PATH}"><!--FILE_PATH下文件总大小超过15GB,进行删除--><IfAccumulatedFileSize exceeds="15GB"/></Delete>
</DefaultRolloverStrategy>
2、测试结果
上述这个场景中,DefaultRolloverStrategy属性会生效,即只保留3个文件,当归档文件超过3个时按fileIndex="max"策略进行删除
2.1.2、场景二:DefaultRolloverStrategy保留3个,Delete删除所有
1、场景说明
当DefaultRolloverStrategy设置了最多保留3个文件,Delete标签中设置了删除所有文件,那么是会保留3个文件,还是删除所有文件?
<DefaultRolloverStrategy max="3" ><Delete basePath="${FILE_PATH}" maxDepth="2" ><IfFileName glob="*/info*.log"/></Delete>
</DefaultRolloverStrategy>
注意:不要有这种配置。
在测试环境用了这种配置,发现文件有可能会增长到第三个,然后当第四个文件归档时删除之前所有的文件。
2.2、testMode不生效?
测试环境配置如下,本来以为配置了testMode="true"之后会开启测试模式,日志文件不会删除,但是最后发现当前日期目录下还是只有3个文件,即<DefaultRolloverStrategy max="3">
属性生效了,那么testMode真的没效果么?
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}_%i.log.gz"><!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--><ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayout pattern="${LOG_PATTERN}"/><Policies><SizeBasedTriggeringPolicy size="2KB"/></Policies><DefaultRolloverStrategy max="3"><Delete basePath="${FILE_PATH}" maxDepth="2" testMode="true"><IfFileName glob="*/*.log.gz"/></Delete></DefaultRolloverStrategy>
</RollingFile>
上述配置的效果是:
- 假设当前日期是2024-12-30,那么当前日期目录下最多只会保留3个文件(
<DefaultRolloverStrategy max="3">
生效了)。 - 但是其他日期目录下的文件不会删除(
testMode=true
生效了)。
DefaultRolloverStrategy
<DefaultRolloverStrategy max="5"/>DefaultRolloverStrategy表示log4j2每单位时间内最多能保存多少个日志切割文件,一般与SizeBasedTriggeringPolicy结合使用;max:表示保存的最大值,默认为7;例如:你的log4j2.xml设置如下:fileName="e:/log.out" filePattern="e:/app-%d{yyyy-MM-dd_HH-mm}-%i.out"
那么在每分钟内,你可以保留2个日志切割文件,多余的日志进行覆盖;
三、总结
DefaultRolloverStrategy: 删除策略单一,只能基于filePattern属性保证当前这个目录下的文件数量,不能删除其他文件夹的文件
Delete: 可以删除任意目录下的文件,并提供多种条件配置方式。
参考、推荐文章:
https://blog.csdn.net/bluuusea/article/details/104763368
https://www.cnblogs.com/yougewe/p/13407812.html
https://www.jianshu.com/p/c13ba3f5dd99
创作不易,欢迎打赏,你的鼓励将是我创作的最大动力。
相关文章:
log4j2的Strategy、log4j2的DefaultRolloverStrategy、删除过期文件
文章目录 一、DefaultRolloverStrategy1.1、DefaultRolloverStrategy节点1.1.1、filePattern属性1.1.2、DefaultRolloverStrategy删除原理 1.2、Delete节点1.2.1、maxDepth属性 二、知识扩展2.1、DefaultRolloverStrategy与Delete会冲突吗?2.1.1、场景一:…...
macos 支持外接高分辩率显示器开源控制软件
macos 支持外接高分辩率显示器开源控制软件 软件(app应用)名:BetterDisplay 官方地址: https://github.com/waydabber/BetterDisplay...
HTML5实现好看的喜庆圣诞节网站源码
HTML5实现好看的喜庆圣诞节网站源码 前言一、设计来源1.1 主界面1.2 圣诞介绍界面1.3 圣诞象征界面1.4 圣诞活动界面1.5 圣诞热度界面1.6 圣诞纪念界面1.7 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看的喜庆圣诞节网站源码,圣…...
鸿蒙 NEXT 开发中,使用公共事件进行进程间通信
大家好,我是 V 哥,在鸿蒙 NEXT 开发中,使用公共事件进行进程间通信(IPC)是一种常见的做法。下面我将提供一个完整的业务代码示例,并解释逻辑关系,以便即使是初学者也能按照步骤进行实操…...
算法-excel表头位置转成对应数字 26进制转10进制
给你一个字符串 columnTitle ,表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如: A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ... 示例 1: 输入: columnTitle "A" 输出: 1示例 2: 输入: colu…...
清华发布Hyper-YOLO:超图计算+目标检测!捕捉高阶视觉关联
目录 论文信息 引言 背景 算法概括 超图计算 Hyper-YOLO整体架构 基于超图的跨层次和跨位置表示网络 Coovally AI模型训练与应用平台 实验结论 总结 论文信息 题目:Hyper-YOLO: When Visual Object Detection Meets Hypergraph Computation Hyper-YOLO&a…...
如何使用网络工具进行网络性能评估
网络评估是对IT基础设施的系统评估,以确保它能够很好地满足企业的核心运营需求,确定了基础设施中需要改进的领域,并定义了改进的范围。 网络评估工具分析IT基础设施的各个方面,它通过评估网络设备、网络性能和安全威胁来仔细检查…...
MyBatis执行一条sql语句的流程(源码解析)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 MyBatis执行一条sql语句的流程(源码解析) MyBatis执行sql语句的流程加载配置文件加载配置文件的流程 创建sqlsessionFactory对象解析Mapper创建sqlses…...
使用three.js 实现vr全景图展示,复制即可用
1.实现效果 2.代码 1.npm安装three.js npm install three 2.引入three.js import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls 3.初始化模型 init(val) {this.container document.querySelector(.container)// 初始…...
MATLAB关于集合的运算(部分)
集合运算比较两个集合中的元素,以找出共性或差异 i n t e r s e c t intersect intersect表示两组数据的交集 i s m e m b e r ismember ismember表示查找数据的集合成员 u n i o n union union表示两个数据集的并集 u n i q u e unique unique表示查找数据集的…...
谈谈数据产品开发流程
数据产品开发流程涵盖以下关键步骤:首先是需求调研与规划,通过与业务部门等沟通,明确产品定位、受众及功能,制定项目计划。接着进行数据采集与处理,确定数据源,运用合适工具采集并清洗、转换数据后存储。然…...
Unity3D仿星露谷物语开发12之创建道具列表
1、目标 道具是游戏的核心部分,道具包括你可以拾取的东西,你可以使用的工具和你能种的东西等。 本节就是创建道具的信息类。同时了解ScriptableObject类的使用。 2、创建道具枚举类 修改Assets -> Scripts -> Enums.cs脚本, 新增如…...
Linux(Centos 7.6)常见基础配置
1.网络配置 网络配置详见:VMware安装Linux(Centos 7.6)后网络配置 2.yum源配置 yum源配置详见:Linux(Centos 7.6)yum源配置 3.主机名配置 1.Linux(Centos 7.6)系统安装后,没有配置主机名时,root用户登录后,是如下…...
2024年底关于期货的工作总结
十几年程序猿出身,因几年前的懵懂无畏闯入期货市场,盈了,感觉期货太简单,飘然裸辞,想当财务自由者,全职做交易。当深入学习时,却亏了,原来市场是让人敬畏的,也是反人性的…...
python 插入排序(Insertion Sort)
插入排序(Insertion Sort) 插入排序是一种简单的排序算法。它的基本思想是:将数组分为已排序部分和未排序部分,然后逐个将未排序部分的元素插入到已排序部分的正确位置。插入排序类似于整理扑克牌的过程。 插入排序的步骤&#…...
数据库自增 id 过大导致前端时数据丢失
可以看到,前端响应参数是没有丢失精度的 但是在接受 axios 请求参数时出现了精度丢失 解决方案一:改变 axios 字符编码 axios.defaults.headers[Content-Type] application/json;charsetUTF-8; 未解决 解决方案二:手动使用 json.parse() …...
优化租赁小程序提升服务效率与用户体验的策略与实践
内容概要 在这个快速发展的商业环境中,租赁小程序成为了提升服务效率和用户体验的重要工具。通过对用户需求的深入挖掘,我们发现他们对于功能的便捷性、响应速度和界面的友好性有着极高的期待。因此,针对这些需求,完善租赁小程序…...
nvm node.js 版本管理工具
nvm 介绍 nvm 全称 Node Version Manager 顾名思义它是用来管理 node 版本的工具,方便切换不同版本的Node.js 使用 nvm 的使用非常的简单,跟 npm 的使用方法类似 下载安装 首先先下载 nvm,下载地址 https://github.com/coreybutler/nvm…...
使用Locust对Redis进行负载测试
1.安装环境 安装redis brew install redis 开启redis服务 brew services start redis 停止redis服务 brew services stop redis 安装Python库 pip install locust redis 2.编写脚本 loadTest.py # codingutf-8 import json import random import time import redis …...
计算机网络与通信复习
因特网的核心部分(电路交换与分组交换的不同点,分组交换的优点) 核心部分:路由器、交换机 我们假如数据就是一个货物,比如说一千公斤的大米,电路交换要有专用通道,不管从起点到终点经过多少个…...
WAV文件双轨PCM格式详细说明及C语言解析示例
WAV文件双轨PCM格式详细说明及C语言解析示例 一、WAV文件双轨PCM格式详细说明1. WAV文件基本结构2. PCM编码方式3. 双轨PCM格式详细说明二、C语言解析WAV文件的代码示例代码说明一、WAV文件双轨PCM格式详细说明 WAV文件是一种用于存储未压缩音频数据的文件格式,广泛应用于音频…...
【华为OD-E卷 - 网上商城优惠活动 100分(python、java、c++、js、c)】
【华为OD-E卷 - 网上商城优惠活动 100分(python、java、c、js、c)】 题目 某网上商场举办优惠活动,发布了满减、打折、无门槛3种优惠券,分别为: 每满100元优惠10元,无使用数限制,如100 ~ 199元…...
c# Record关键字
在 C# 9.0 中引入了 record 关键字,用于定义记录类型(Record Types)。记录类型是一种轻量级的数据载体,专注于表示数据,它提供了内置的相等性比较、生成属性和方法等功能,使得编写数据类更加简洁和高效。 …...
Windows 10 自带功能实现大屏、小屏无线扩展
一、添加可选功能 在作为无线投屏对象的「第二屏」设备上,打开 Windows 10 设置并定位至「应用 > 应用和功能」界面,然后点击右侧界面中的「可选功能」选项。 点击可选功能界面顶部的「添加功能」按钮,搜索「无线显示器」模块并选择添加。…...
Python内存管理揭秘:有效避免内存泄漏,提升程序稳定性
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代软件开发中,内存管理是确保程序高效、稳定运行的关键因素之一。尽管Python凭借其自动垃圾回收机制简化了内存管理,但内存泄漏问题仍…...
论文分享 | PromptFuzz:用于模糊测试驱动程序生成的提示模糊测试
大语言模型拥有的强大能力可以用来辅助多种工作,但如何有效的辅助仍然需要人的精巧设计。分享一篇发表于2024年CCS会议的论文PromptFuzz,它利用模型提示生成模糊测试驱动代码,并将代码片段嵌入到LLVM框架中执行模糊测试。 论文摘要 制作高质…...
网工日记:FTP两种工作模式的区别
FTP 的主动模式和被动模式在连接建立的发起方、数据传输端口以及对网络环境的适应性等方面存在明显区别: 1. 连接发起方 主动模式:数据连接由服务器主动发起。在控制连接建立后,客户端通过 PORT 命令告知服务器自己用于接收数据的临时端口号…...
clickhouse-backup配置及使用(Linux)
一、下载地址 Releases Altinity/clickhouse-backup GitHub 二、上传到服务器解压安装 自行上传至服务器,解压命令: tar xvf clickhouse-backup-linux-amd64.tar.gz 三、创建软连接 sudo ln -sv build/linux/amd64/clickhouse-backup /usr/local/bin/…...
【每日学点鸿蒙知识】模拟器开启网络、长时任务、兼容性测试支持、丢帧定位、SO中访问rawfile等
1、模拟器如何开启网络? 模拟器使用的是电脑本身的网络,不通过代理即可访问网络。 2、创建子window后,锁屏很短时间内,应用会被杀死? 没开长时任务,锁屏和退后台保活要开长时任务。 应用退至后台后&…...
Python 将文字和二维码 生成到BMP上 可以做标签打印等
直接上代码吧,都有注释,看得明白 将代码复制到main.py文件中,就可以调试了 from PIL import Image, ImageDraw, ImageFont import matplotlib.font_manager as fm from matplotlib.font_manager import FontProperties import os import qr…...
pat 乙级1096 大美数
若正整数 N 可以整除它的 4 个不同正因数之和,则称这样的正整数为“大美数”。本题就要求你判断任一给定的正整数是否是“大美数”。 输入格式: 输入在第一行中给出正整数 K(≤10),随后一行给出 K 个待检测的、不超过…...
INT303 Big Data Analytics 笔记
Lecture1 Introduction 不考! “Data Mining is the study of collecting, processing, analyzing, and gaining useful insights from data” EXPLORATORY ANALYSIS Make measurements to understand what the data looks like first steps when collecting da…...
Git 解决 everything up-to-date
首先使用git log查看历史提交,找到最新一次提交,比如: PS D:\Unity Projects\CoffeeHouse\CoffeeHouse_BurstDebugInformation_DoNotShip> git log commit a1b54c309ade7c07c3981d3ed748b0ffac2759a3 (HEAD -> master, origin/master)…...
初级算法 - 数组简介
数组简介 在TypeScript中,数组是一种存储同一类型数据的集合类型。数组可以动态调整长度,支持对元素进行增删改查等操作。通过类型注解,可以更清晰地约束数组中元素的类型,提升代码的可维护性。 创建数组的方式 1. 使用字面量方式…...
【毕业设计选题】目标检测方向毕业设计选题推荐 2025
目录 前言 毕设选题 开题指导建议 更多精选选题 选题帮助 最后 前言 大家好,这里是海浪学长毕设专题! 大四是整个大学期间最忙碌的时光,一边要忙着准备考研、考公、考教资或者实习为毕业后面临的升学就业做准备,一边要为毕业设计耗费大量精力。学长给大家整…...
适配器模式详解
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换成客户所期望的另一个接口,使得原本不兼容的类能够协同工作。这种模式的主要目的是解决接口不匹配的问题,它通过创建一个适配器类ÿ…...
基于 Spring 的自定义注解和请求拦截器实现认证机制
基于 Spring 的自定义注解和请求拦截器实现认证机制 一、基于 Spring 的自定义注解和请求拦截器实现认证机制1. 背景2. 业务场景3. 核心实现3.1 定义自定义注解 IgnoreAuth3.2 定义请求拦截器 AuthInterceptor3.3 配置拦截器3.4 登录接口 4. 小结 一、基于 Spring 的自定义注解…...
Java编程规约:集合处理
文章目录 I 集合处理【强制】【推荐】II 知识扩展I 集合处理 【强制】 不要在 foreach 循环里进行元素的 remove / add 操作。remove 元素请使用 iterator 方式,如果并发操作,需要对 iterator 对象加锁。// 正例: List<String> list = new ArrayList<>(...
python使用PyQt5,整套,桌面应用
安装 安装 pip install PyQt55.7.1 pip install PyQtWebEngine1、创建窗口,按百分比划分 from PyQt5.QtGui import QGuiApplication from PyQt5.QtWidgets import QApplication, QWidget # 创建应用程序实例 app QApplication([]) # 创建主窗口 window QWidget(…...
机械臂的各种标定
文章目录 1. 工具坐标系标定2. 工具手标定3. 手眼标定联系 在工程中,同时使用工具坐标系标定、工具手标定和手眼标定的概念、目的和作用如下: 1. 工具坐标系标定 概念: 工具坐标系标定是指确定工具相对于机器人坐标系的位置和姿态关系的过程…...
金融租赁系统助力企业转型与市场竞争力提升
内容概要 在现代商业环境中,金融租赁系统不仅是一个简单的工具,而是企业转型的重要推动力。通过优化业务流程,提升自动化水平,它帮助企业在复杂的市场中找到自己的立足之地。想象一下,一个企业在使用传统方法时&#…...
正则表达式 - 运算符优先级
正则表达式 - 运算符优先级 正则表达式(Regular Expression,简称Regex)是一种用于处理字符串的强大工具,它通过特定的语法规则来匹配、查找和替换文本中的特定模式。在正则表达式中,运算符的优先级决定了表达式各部分的处理顺序,这对于正确理解和编写正则表达式至关重要…...
【python】unittest单元测试
文章目录 基本使用不同启动方式的区别 基本使用 下面是根据文档写的一个demo,主要的内容基本都包含了,使用时导入自己的业务类测试类中的方法就行。 import unittest# 测试类不强制test开头,仅作为规范。但必须继承unittest.TestCase class…...
【YashanDB知识库】如何使用jdbc向YashanDB批量插入gis数据
本文内容来自YashanDB官网,原文内容请见 https://www.yashandb.com/newsinfo/7817897.html?templateId1718516 以gis表为例: drop table gis; create table gis(id number not null, pos st_geometry not null); 使用如下的java代码片断,…...
基于 LangChain 实现数据库问答机器人
基于 LangChain 实现数据库问答机器人 一、简介二、应用场景三、实战案例1、需求说明2、实现思路3、对应源码 一、简介 在 Retrieval 或者 ReACT 的一些场景中,常常需要数据库与人工智能结合。而 LangChain 本身就封装了许多相关的内容,在其官方文档-SQ…...
XIAO ESP32 S3网络摄像头——2视频获取
本文主要是使用XIAO Esp32 S3制作网络摄像头的第2步,获取摄像头图像。 1、效果如下: 2、所需硬件 3、代码实现 3.1硬件代码: #include "WiFi.h" #include "WiFiClient.h" #include "esp_camera.h" #include "camera_pins.h"// 设…...
图像描述/字幕开源模型与数据集全览
图像描述/字幕(Image Captioning)是用文字描述图像内容的任务,属于计算机视觉和自然语言处理的交叉领域。大多数图像描述系统采用编码器-解码器(encoder-decoder)框架,其中输入图像被编码为中间表示形式&am…...
关于UE加载osgb数据的研究(一)
最近关于倾斜数据在UE中加载显示的问题,直接转换格式本地加载的方式避免了数据延迟加载、缓存加载,动态刷新等问题,但是也暴露了突出的问题:常规的模型格式会丢失掉倾斜数据的lod,致使效果缺失。 故而需要深入研究一下UE加载osgb数据的方式方法。 首先,我们需得学习一下…...
Hypervisor 的两种类型
文章目录 一、定义 Hypervisor(也被称为虚拟机监视器,即Virtual Machine Monitor,VMM)是一种创建和运行虚拟机的软件、固件或硬件。它可以在物理主机上划分出多个虚拟的计算环境,使得多个操作系统(Guest Op…...
07-ArcGIS For JavaScript--隐藏参数qualitySettings(memory和lod控制)
目录 1、综述2、sceneview.qualitySettings2.1、sceneview.qualitySettings.memoryLimit2.2、lodFactor2.3 additionalCacheMemory 3、结论 1、综述 先上重点,SceneView.qualitySettings为隐藏对象参数,该对象的memoryLimit和lodFactor等值,…...