Logback FileAppender,它使用单个日志文件并删除旧的日志文件

时间:2017-01-31 16:25:09

标签: java logback logback-groovy

我正在使用logback.groovy文件中配置的logback来管理我的应用程序的日志。我想:

  1. 创建在应用程序启动时加上时间戳的日志文件,并在应用程序生命周期内保留为单个日志文件。 (我们可能有几个应用程序同时运行的实例,或者在一天中运行多个实例,并且它们可能运行了几天。)
  2. 保留一个干净的日志文件目录,以便删除超过给定时间段的日志。
  3. 实现第一个建议使用FileAppender,沿着以下行 - 但是,这不会删除旧的日志文件:

    appender("FILE", FileAppender) {
      file = "path/to/log/dir/log_file_${date}.log"
    }
    

    实现第二个建议使用RollingFileAppenderTimeBasedRollingPolicy,沿着以下行 - 将日志文件保留7天。但是,无论应用程序何时运行,它都将使用单个文件记录给定日期的应用程序的所有实例:

    appender("FILE", RollingFileAppender) {
        rollingPolicy(TimeBasedRollingPolicy) {
            fileNamePattern = "path/to/log/dir/log_file_%d{yyyyMMdd}.log"
            maxHistory = 7;
        }
    }
    

    如何获得蛋糕并吃掉它 - 即每个应用程序运行时获得单个日志文件的好处(具有启动时间戳),但具有RollingFileAppender / {{1}的历史清理优势}?

2 个答案:

答案 0 :(得分:0)

如果它可能有用,可以通过创建自定义FileAppender来实现此目的,如下所示:

public class TidyFileAppender<E> extends FileAppender<E> {

  protected File directory;

  @Override
  public void start() {
    if (conditions to determine historical files to be deleted) {
      File[] oldFiles = directory.listFiles(new FileFilter() {
        @Override
        public boolean accept(File file) {
          // return true if file is 'old'
        }
      });
      if (oldFiles != null) {
        for (File oldFile : oldFiles) {
          if (!oldFile.delete()) {
            addWarn("Failed to delete old log file: " + oldFile);
          }
        }
      }
    } else {
      addWarn("Cannot tidy historical logs...");
    }
    super.start();
  }
}

答案 1 :(得分:0)

扩展上一个答案,这是一个具体且有效的 Kotlin 实现:

import ch.qos.logback.core.FileAppender
import java.io.File

class TidyFileAppender<E>: FileAppender<E>() {
    /** Defaults to the parent dir of the current logfile. */
    var directory: String? = null
    /** How many previous files to keep, by last modified attribute. */
    var maxHistory: Int = 20
    /** Threshold for extra files that may be kept to reduce file system accesses. */
    var threshold: Int = 0
    
    override fun start() {
        if (directory == null)
            directory = File(fileName).parent
        File(directory).list()?.let { files ->
            if (files.size > maxHistory + threshold) {
                files.map { File(directory, it) }
                        .sortedBy { it.lastModified() }
                        .take(files.size - maxHistory)
                        //.also { println("Removing $it") }
                        .forEach(File::delete)
            }
        }
        super.start()
    }
}

用法示例:

  <timestamp key="time" datePattern="MM-dd'T'HHmm"/>
  <appender name="FILE" class="TidyFileAppender">
    <file>${LOG_DIRECTORY:-log}/game-server_${time}.log</file>
    <maxHistory>15</maxHistory>

    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>%d{HH:mm:ss} %-5level %36logger{36} - %msg%n</Pattern>
    </layout>
  </appender>