扩展 log4j/slf4j 记录器

我处于多个线程(来自同一个 JVM)正在写入同一个文件(使用 Logger 进行日志记录)的情况。我需要在某个时候删除这个文件,下次使用 logger 将创建文件和日志。

日志库是同步的,因此我不需要担心并发日志记录到同一个文件。

但是......我想添加一个操作这个文件的外部操作,这个操作是删除文件,因此我必须以某种方式将日志记录(Logger)与这个删除操作同步,因为我不想同时删除文件记录器正在工作。

我想到的事情:

  1. 使用FileChannel.lock锁定文件,Logger 也会这样做。我决定反对这个,因为这个:

代表整个 Java 虚拟机持有文件锁。它们不适合控制同一虚拟机内的多个线程对文件的访问。

这意味着在我的情况下(相同的 JVM,多线程)这不会导致我想要的效果。

我有哪些选择?

我在这里错过了一些重要的东西吗?

也许有一种方法可以使用 Logger 中已有的东西来做到这一点?


白衣非少年
浏览 237回答 3
3回答

慕森卡

您似乎正在寻找日志滚动和日志归档功能。日志滚动是 Log4j 和 Logback(SLF4j 也是)的一个共同特性。您可以配置日志库以根据当前文件的大小或一天中的时间创建新的日志文件。您可以为滚动文件配置文件名格式,然后让外部进程存档或删除旧的滚动日志文件。您可以参考此答案中给出的 Log4j 2 配置。

繁华开满天机

我过去在没有其他选择的情况下使用的一个技巧只是重命名当前日志文件。重命名后,排队等待它的任何未完成的日志记录都会继续进入重命名的日志记录。通常,任何新的日志请求都会创建一个新文件。剩下的就是清理重命名的。您通常可以使用一些外部进程来管理它,或者只要这个进程触发就删除任何旧的日志文件。

子衿沉夜

文件系统通常由操作系统同步,因此您可以简单地删除文件而不必担心锁定或任何事情。根据 log4j 锁定文件的方式,删除过程可能会失败,您需要添加一个重试循环。int attempts = 3;final File logfile = new File(theLogFilePath);while ((attempts > 0) && logfile.exists() && !logfile.delete()) {  --attempts;  try {    Thread.sleep(1000);  } catch (InterruptedException e) {    attempts = 0;  }}这不是完全干净的代码,但是无论如何你所做的都不干净。;)您相当粗鲁地干扰了日志记录过程,但由于用户也可以随时删除该文件,因此 log4j 应该优雅地处理它。最坏的情况是,我的猜测是即将被记录的消息会丢失,但考虑到您无论如何都只是删除了日志文件,这可能不是问题。有关更清晰的实现,请参阅此问题。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java