手记

log4j常用的两种日志模式

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是有很强的大小控制,只不过没有对应的时间策略,在找具体某个时间点的时候,需要花点时间,不能快速定位。

0人推荐
随时随地看视频
慕课网APP