为了实现我们的需求,我们先看一下原始的Log4j 是如何实现日志文件的管理的。
RollingFileAppender
-
在log4j中Appender 负责将日志写入日志文件中,实际生产环境中服务长期运行,日志文件会非常多,所以我们一般使用
RollingFileAppender
来将日志根据规则进行切割,写入不同的日志文件中。 -
在log4j内置的类是
org.apache.log4j.RollingFileAppender
,这个类默认功能比较单一,通过参数 maxBackupIndex 配置Rolling File的个数,maxFileSize 配置每个日志文件的大小,然后滚动输出日志。 -
在
log4j:apache-log4j-extras:1.2.17
这个扩展包中,又重新扩展了一个新的类org.apache.log4j.rolling.RollingFileAppender
。这个RollingFileAppender
可以根据检查文件大小或者打印日志的时间不同参数进行Rolling File,但是这个这个Appender 丢失了删除日志文件的功能(完全没有maxBackupIndex 参数了…)。
TriggeringPolicy
org.apache.log4j.rolling.RollingFileAppender
中TriggeringPolicy
来表示进行Rolling Log File的策略。官方提供了两种org.apache.log4j.rolling.SizeBasedTriggeringPolicy
和org.apache.log4j.rolling.TimeBasedRollingPolicy
两种策略实现,用户也可以根据自己的需求扩展新的Policy。
TriggeringPolicy.isTriggeringEvent()
- 当
TriggeringPolicy.isTriggeringEvent()
方法判断为true时,进行Rolling File操作; o.g.l.r.SizeBasedTriggeringPolicy
中的isTriggeringEvent()
的判断条件是日志文件大小大于 maxFileSize。o.g.l.r.TimeBasedRollingPolicy
中的isTriggeringEvent()
是根据系统时间和FileNamePattern 参数来计算Rolling File的文件名,当Rolling File的文件名发生变化,进行Rolling File操作;
rollover
- 当
TriggeringPolicy
的isTriggeringEvent()
方法返回True后,o.a.l.rolling.RollingFileAppender
开始执行rollover()
方法 rollover()
方法先等待上一次的rollover正常执行结束- 通过policy 的
rollingPolicy.rollover(getFile())
方法,返回 RolloverDescription对象,表示Rolling File的一系列动作。 - 同步执行
RolloverDescription
中的 Synchronous Action操作(例如重明命名文件)并等待成功。 - 启动异步线程,执行
RolloverDescription
中的 Asynchronous Action操作(例如压缩日志文件等)。 - Action的概念可以是一个单独的任务操作,也可以是一组任务操作(
CompositeAction
)
总结
对于Long Running的Java进程,我们不仅仅需要进行Rolling File的操作,还需要对历史Log File进行清理。所以我参考了 TimeBasedRollingPolicy
代码,实现了ExtendedTimeBasedRollingPolicy
类。原来的类中,asynchronous 就是单独的 compressAction 负责对日志文件进行压缩(满足条件时),我们将这个对象换成 CompositeAction,再加入我们想要的负责清理文件的 PurgeExpiredLogsAction 即可。在 PurgeExpiredLogsAction 中,我们可以灵活的根据日志的文件名,日志的文件的个数,文件的大小等条件,进行历史日志文件的删除。