Java 扩展log4j/slf4j记录器

Java 扩展log4j/slf4j记录器,java,multithreading,logging,thread-safety,Java,Multithreading,Logging,Thread Safety,我遇到的情况是,多个线程(来自同一个JVM)正在写入同一个文件(使用Logger进行日志记录)。 我需要在某个时候删除此文件,下次使用logger将创建该文件和日志 日志库是同步的,因此我不需要担心并发日志记录到同一个文件 但是。。。我想添加一个操作此文件的外部操作,此操作是删除该文件,因此我必须以某种方式将日志记录(记录器)与此删除操作同步,因为我不想在记录器工作时删除该文件 我想到的事情: 使用FileChannel.lock来锁定文件,记录器也会这样做。我决定不这样做,因为: 文件锁代表整

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

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

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

我想到的事情:

  • 使用FileChannel.lock来锁定文件,记录器也会这样做。我决定不这样做,因为:
  • 文件锁代表整个Java虚拟机持有。他们 不适合控制多线程对文件的访问 在同一虚拟机中

    这意味着在我的情况下(同一个JVM,多个线程),这不会产生我想要的效果

    我的选择是什么?

    我是不是错过了一些重要的东西?


    也许有一种方法可以使用记录器中已经存在的东西来实现这一点?文件系统通常由操作系统同步,因此您可以简单地删除文件,而不必担心锁或任何问题。根据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应该优雅地处理该问题。最糟糕的情况是,我猜将要记录的消息将丢失,但考虑到您只是简单地删除日志文件,这可能不是问题


    有关更清晰的实现,请参见。

    您似乎正在寻找日志滚动和日志归档功能。日志滚动是Log4j和Logback(SLF4j)中的一个常见功能

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


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

    我过去在没有其他选项(请参阅Saptarshi Basu的日志滚动建议)时使用的一个技巧是只重命名当前日志文件

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


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

    查看log4j rolling file appender和其他appender-@Sergi请参阅Saptarshi Basu answer的评论。我希望在某个时候重新创建此文件。但是,这一点必须在项目中指定。更大的情况是,这个日志文件被合并到一个数据库中,然后它必须被删除,下一次达到这个点时,同样的情况也会发生,合并和删除。在此期间,应该可以写入日志文件。我不认为我可以使用您指定的内容,因为配置依赖于特定的内容,并且我不能引用代码手动删除。我隐藏大图是为了简化问题。@Hubbs我假设您的主要目标是在业务逻辑创建的某些事件中将日志存储在数据库中。在这种情况下,您可能会考虑配置附加的APPERMER来将日志消息张贴在JMS队列中,并有单独的java应用程序处理这些消息,并确定何时将数据插入数据库中。你可能还想探索类似Logstash的东西。至少,这样你就不必同步事情了。还可以异步发布到JMS以提高性能。用户无法删除该文件。这个文件是服务器端的。在这种情况下可能不是这样,但在其他情况下用户可以这样做,所以log4j必须确保它可以正常运行,即使有人删除了日志文件。