Log4j2 2.20.2:XML配置下如何捕获日志滚动事件并实现定时滚动
在Log4j2 2.20.2中捕获日志滚动事件并实现定时滚动
一、先修复每分钟滚动的问题
你自定义的XXXX_TriggeringPolicy存在逻辑瑕疵,导致滚动不生效,可按以下方式调整,或直接使用官方内置策略简化实现:
1. 修正自定义触发策略的逻辑
调整initialize和isTriggeringEvent方法,确保时间计算准确:
@Override public void initialize(final RollingFileManager aManager) { this.manager = aManager; long current = aManager.getFileTime(); if (current == 0) { current = System.currentTimeMillis(); } PatternProcessor patternProcessor = aManager.getPatternProcessor(); patternProcessor.setTimeBased(true); // 根据filePattern的分钟粒度计算下一次滚动时间 nextRolloverMillis = patternProcessor.getNextTime(current, interval, modulate); // 按需添加随机延迟 if (maxRandomDelayMillis > 0) { nextRolloverMillis += ThreadLocalRandom.current().nextLong(0, maxRandomDelayMillis + 1); } } @Override public boolean isTriggeringEvent(final LogEvent event) { final long nowMillis = event.getTimeMillis(); if (nowMillis >= nextRolloverMillis) { PatternProcessor patternProcessor = manager.getPatternProcessor(); // 用当前事件时间计算下一次滚动点,避免时间偏差 nextRolloverMillis = patternProcessor.getNextTime(nowMillis, interval, modulate); if (maxRandomDelayMillis > 0) { nextRolloverMillis += ThreadLocalRandom.current().nextLong(0, maxRandomDelayMillis + 1); } patternProcessor.setCurrentFileTime(nowMillis); return true; } return false; }
2. 简化方案:使用官方TimeBasedTriggeringPolicy
无需自定义触发策略,官方组件已支持按时间粒度滚动,结合你的filePattern(分钟级),配置如下即可实现每分钟滚动:
<Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> </Policies>
二、捕获日志滚动事件的可靠方法
要在滚动完成后执行业务逻辑,推荐以下两种方式:
方法1:自定义RolloverStrategy
继承DefaultRolloverStrategy,在滚动完成后注入业务逻辑:
@Plugin(name = "CustomRolloverStrategy", category = Core.CATEGORY_NAME, printObject = true) public class CustomRolloverStrategy extends DefaultRolloverStrategy { protected CustomRolloverStrategy(Builder builder) { super(builder); } @Override public RolloverResult rollover(RollingFileManager manager) { // 先执行默认滚动流程 RolloverResult result = super.rollover(manager); // 滚动成功后执行业务逻辑 if (result.getSuccess()) { String rolledFilePath = manager.getPatternProcessor().getCurrentFileName(); // 示例:处理滚动后的文件(压缩、上传等) handleRolledFile(rolledFilePath); } return result; } private void handleRolledFile(String filePath) { System.out.println("日志文件已滚动:" + filePath); // 这里添加你的业务逻辑 } @PluginBuilderFactory public static Builder newBuilder() { return new Builder(); } public static class Builder extends DefaultRolloverStrategy.Builder<Builder> { @Override public CustomRolloverStrategy build() { return new CustomRolloverStrategy(this); } } }
在XML配置中指定该策略:
<RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/app-%d{yyyy-MM-dd-HH-mm}.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> </Policies> <CustomRolloverStrategy/> </RollingFile>
方法2:添加RollingFileManager监听器
在应用初始化完成后,给滚动文件管理器添加监听器,监听滚动前后事件:
// 获取目标Appender RollingFileAppender appender = (RollingFileAppender) LogManager.getContext(false) .getConfiguration().getAppender("RollingFile"); // 获取滚动管理器 RollingFileManager manager = appender.getManager(); // 添加滚动监听器 manager.addRolloverListener(new RolloverListener() { @Override public void beforeRollover(RollingFileManager rollingFileManager) { // 滚动前逻辑(可选) } @Override public void afterRollover(RollingFileManager rollingFileManager) { String rolledFile = rollingFileManager.getPatternProcessor().getCurrentFileName(); handleRolledFile(rolledFile); } });
三、最终推荐配置
结合官方触发策略和自定义滚动策略,完整XML配置如下:
<Configuration status="warn" name="MyApp"> <Appenders> <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/app-%d{yyyy-MM-dd-HH-mm}.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> </Policies> <CustomRolloverStrategy/> </RollingFile> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </Configuration>
内容的提问来源于stack exchange,提问作者Programer86
相关产品推荐
相关产品推荐

