log4j常用的两种日志模式是RollingFileAppender和DailyRollingFileAppender,下面介绍一下这两种模式的基本实现原理。
RollingFileAppender
RollingFileAppender是可以根据文件的大小设置,然后切割文件,设置保留文件的数量,可以很好的保证日期文件的总大小,不会出现非常多的读写导致文件撑爆了磁盘的情况。
protected
void subAppend(LoggingEvent event) {
super.subAppend(event);
if(fileName != null && qw != null) {
long size = ((CountingQuietWriter) qw).getCount();
if (size >= maxFileSize && size >= nextRollover) {
rollOver();
}
}
}
当文件大小超过了设定的文件大小时,就开始做rollOver的操作。
rollOver主要负责文件数量的控制。
file = new File(fileName + '.' + maxBackupIndex);
if (file.exists())
renameSucceeded = file.delete();
先要判定一下,是否存在文件的最大的后缀,如果出现的话,就删除文件。这里就是删除了达到限制的文件。
for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) {
file = new File(fileName + "." + i);
if (file.exists()) {
target = new File(fileName + '.' + (i + 1));
LogLog.debug("Renaming file " + file + " to " + target);
renameSucceeded = file.renameTo(target);
}
后续就需要维护现有的文件的名字格式,这里是直接做的rename,例如文件4变成了文件5。
target = new File(fileName + "." + 1);
this.closeFile(); // keep windows happy.
file = new File(fileName);
LogLog.debug("Renaming file " + file + " to " + target);
renameSucceeded = file.renameTo(target);
此时出现的文件就是2到x,还有最初始的文件,所以把初始文件换成1.
this.setFile(fileName, false, bufferedIO, bufferSize);
nextRollover = 0;
public
synchronized
void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
throws IOException {
super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
if(append) {
File f = new File(fileName);
((CountingQuietWriter) qw).setCount(f.length());
}
}
最后新建一个新的文件,然后开始继续写内容。
DailyRollingFileAppender
DailyRollingFileAppender是按照日期来做文件的,每天都会产生一个新的文件。
long n = System.currentTimeMillis();
if (n >= nextCheck) {
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try {
rollOver();
}
在当前时间超过了检测时间的时候,就开始做rollOver。
File target = new File(scheduledFilename);
if (target.exists()) {
target.delete();
}
程序会先检测文件名是否被占用了,如果占用了就直接删除了。
File file = new File(fileName);
boolean result = file.renameTo(target);
继续做文件的重命名,因为这里是按照日期重命名,所以,他没有控制数量的地方。
try {
// This will also close the file. This is OK since multiple
// close operations are safe.
this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
}
catch(IOException e) {
errorHandler.error("setFile("+fileName+", true) call failed.");
}
scheduledFilename = datedFilename;
开始写入新的文件,并且把当前时间作为下次重命名的文件名。
小结
通过上面的逻辑,我们发现rollOver的部分写的回滚和文件控制的策略。DailyRollingFileAppender的策略如果不及时清理的话也会造成文件撑爆的情况,毕竟没有控制大小的策略在里面,所以使用的时候要慎重,RollingFileAppender是有很强的大小控制,只不过没有对应的时间策略,在找具体某个时间点的时候,需要花点时间,不能快速定位。
共同学习,写下你的评论
评论加载中...
作者其他优质文章