使用单个日志文件并删除旧日志文件的 Logback FileAppender
A Logback FileAppender that uses a single log file and deletes old log files
我正在使用在 logback.groovy
文件中配置的 logback 来管理我的应用程序的日志。我想:
- 创建在应用程序启动时加上时间戳的日志文件,并在应用程序的整个生命周期内作为单个日志文件保留。 (我们可能同时有一个应用程序的多个实例 运行ning,或者在一天中有多个实例 运行,并且它们可能会 运行ning 好几天。)
- 保持一个干净的日志文件目录,以便删除超过给定时间段的日志。
实现第一个建议使用 FileAppender
,遵循以下几行 - 但是,这不会删除旧的日志文件:
appender("FILE", FileAppender) {
file = "path/to/log/dir/log_file_${date}.log"
}
实现第二个建议使用 RollingFileAppender
和 TimeBasedRollingPolicy
,沿着以下几行 - 将日志文件保留 7 天。但是,这将使用单个文件记录给定日期的应用程序的所有实例,而不管应用程序何时 运行:
appender("FILE", RollingFileAppender) {
rollingPolicy(TimeBasedRollingPolicy) {
fileNamePattern = "path/to/log/dir/log_file_%d{yyyyMMdd}.log"
maxHistory = 7;
}
}
我怎样才能吃到蛋糕 - 即获得每个应用程序单个日志文件的好处 运行(具有启动时间戳),但具有 [=14= 的历史清理好处]/TimeBasedRollingPolicy
?
在可能有用的范围内,可以通过创建自定义 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();
}
}
扩展上一个答案,这是一个具体且有效的 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>
我正在使用在 logback.groovy
文件中配置的 logback 来管理我的应用程序的日志。我想:
- 创建在应用程序启动时加上时间戳的日志文件,并在应用程序的整个生命周期内作为单个日志文件保留。 (我们可能同时有一个应用程序的多个实例 运行ning,或者在一天中有多个实例 运行,并且它们可能会 运行ning 好几天。)
- 保持一个干净的日志文件目录,以便删除超过给定时间段的日志。
实现第一个建议使用 FileAppender
,遵循以下几行 - 但是,这不会删除旧的日志文件:
appender("FILE", FileAppender) {
file = "path/to/log/dir/log_file_${date}.log"
}
实现第二个建议使用 RollingFileAppender
和 TimeBasedRollingPolicy
,沿着以下几行 - 将日志文件保留 7 天。但是,这将使用单个文件记录给定日期的应用程序的所有实例,而不管应用程序何时 运行:
appender("FILE", RollingFileAppender) {
rollingPolicy(TimeBasedRollingPolicy) {
fileNamePattern = "path/to/log/dir/log_file_%d{yyyyMMdd}.log"
maxHistory = 7;
}
}
我怎样才能吃到蛋糕 - 即获得每个应用程序单个日志文件的好处 运行(具有启动时间戳),但具有 [=14= 的历史清理好处]/TimeBasedRollingPolicy
?
在可能有用的范围内,可以通过创建自定义 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();
}
}
扩展上一个答案,这是一个具体且有效的 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>