繁体   English   中英

扩展log4j / slf4j记录器

[英]Extending log4j/slf4j Logger

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

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

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

我想到的事情:

  1. 使用FileChannel.lock可以锁定文件,Logger也可以这样做。 由于这个原因,我决定反对:

文件锁代表整个Java虚拟机保留。 它们不适用于控制同一虚拟机中的多个线程对文件的访问。

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

我有什么选择?

我在这里缺少重要的东西吗?

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

看来您正在寻找日志滚动和日志归档功能。 日志滚动是Log4j和Logback(也包括SLF4j)的常见功能。

您可以将日志记录库配置为根据当前文件的大小或一天中的时间创建一个新的日志文件。 您可以为滚动文件配置文件名格式,然后进行外部进程归档或删除旧的滚动日志文件。

您可以参考答案中给出的Log4j 2配置。

文件系统通常由OS同步,因此您可以简单地删除文件而不必担心锁或其他问题。 但是,根据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应该能够正常处理该文件。 最糟糕的情况是,我将要记录的消息会丢失,但是考虑到您只是简单地删除日志文件,这可能不是问题。

对于更清洁的实现,请参阅此问题

在过去没有其他选择时,我曾经使用过一个窍门(请参阅Saptarshi Basu的日志滚动建议https://stackoverflow.com/a/53011323/823393 ),只是重命名当前日志文件。

重命名后,排队等待进行的所有未完成日志将继续进入重命名的日志。 通常,任何新的日志请求都将创建一个新文件。

剩下的就是清理重命名的文件了。 通常,您可以使用一些外部进程来管理此问题,或者只要此进程触发,就可以删除任何旧的日志文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM