简体   繁体   English

扩展log4j / slf4j记录器

[英]Extending log4j/slf4j Logger

I am in a situation where multiple threads (from the same JVM) are writing to the same file (logging by using Logger). 我处于多个线程(来自同一JVM)正在写入同一文件(使用Logger进行记录)的情况。 I need to delete this file at some point, and next use of logger will create the file and log. 我需要在某个时候删除该文件,下次使用logger会创建该文件并进行日志。

The logging library is synchronized, therefore I do not need to worry about concurrent logging to the same file. 日志记录库是同步的,因此我不必担心并发日志记录到同一文件。

But... I want to add an external operation which operates this file, and this operation is to delete the file, therefore I have to somehow synchronize the logging (Logger) with this delete operation because I do not want to delete the file while the Logger is doing work. 但是...我想添加一个操作该文件的外部操作,并且此操作是删除文件,因此我必须以某种方式将日志记录(记录器)与此删除操作进行同步,因为我不想在删除文件的同时记录仪正在工作。

Things I thought of: 我想到的事情:

  1. Use FileChannel.lock to lock the file, something Logger does, as well. 使用FileChannel.lock可以锁定文件,Logger也可以这样做。 I decided against this, because of this: 由于这个原因,我决定反对:

File locks are held on behalf of the entire Java virtual machine. 文件锁代表整个Java虚拟机保留。 They are not suitable for controlling access to a file by multiple threads within the same virtual machine. 它们不适用于控制同一虚拟机中的多个线程对文件的访问。

Which means in my case (same JVM, multiple threads) this will not cause the effect I want. 这意味着在我的情况下(相同的JVM,多个线程)这不会导致我想要的效果。

What are my options? 我有什么选择?

Am I missing something vital here? 我在这里缺少重要的东西吗?

Perhaps there is a way to do this using the already existing stuff in the Logger? 也许有一种方法可以使用Logger中已经存在的东西来做到这一点?

It seems you are looking for log rolling and log archiving functionalities. 看来您正在寻找日志滚动和日志归档功能。 Log rolling is a common feature in Log4j and Logback (SLF4j also). 日志滚动是Log4j和Logback(也包括SLF4j)的常见功能。

You can configure the logging library to create a new log file based on size of the current file or the time of day. 您可以将日志记录库配置为根据当前文件的大小或一天中的时间创建一个新的日志文件。 You can configure the file name format for the rolled file and then have the external process archive or delete old rolled log files. 您可以为滚动文件配置文件名格式,然后进行外部进程归档或删除旧的滚动日志文件。

You can refer to the Log4j 2 configuration given in this answer. 您可以参考答案中给出的Log4j 2配置。

Filesystems are generally synchronized by the OS, so you can simply delete the file without having to worry about locks or anything. 文件系统通常由OS同步,因此您可以简单地删除文件而不必担心锁或其他问题。 Depending on how log4j locks the file that delete process might fail though, and you need to add a retry-loop. 但是,根据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;
  }
}

This isn't exactly clean code, but then what you do isn't clean anyways. 这不是完全干净的代码,但是您所做的仍然不是干净的。 ;) ;)

You interfere with the logging process rather rudely, but since also a user could delete that file at any time, log4j should handle that gracefully. 您相当粗鲁地干扰了日志记录过程,但是由于用户也可以随时删除该文件,因此log4j应该能够正常处理该文件。 Worst case my guess is that a message that was about to be logged will get lost, but that's probably not an issue considering that you simply delete the log-file anyways. 最糟糕的情况是,我将要记录的消息会丢失,但是考虑到您只是简单地删除日志文件,这可能不是问题。

For a cleaner implementation see this question . 对于更清洁的实现,请参阅此问题

A trick I've used in the past when there is no other option (see Saptarshi Basu's log-rolling suggestion https://stackoverflow.com/a/53011323/823393 ) is to just rename the current log file. 在过去没有其他选择时,我曾经使用过一个窍门(请参阅Saptarshi Basu的日志滚动建议https://stackoverflow.com/a/53011323/823393 ),只是重命名当前日志文件。

After the rename, any outstanding logging that is queued up for it continues into the renamed one. 重命名后,排队等待进行的所有未完成日志将继续进入重命名的日志。 Usually, any new log requests will create a new file. 通常,任何新的日志请求都将创建一个新文件。

All that remains is to clean up the renamed one. 剩下的就是清理重命名的文件了。 You can usually manage this using some external process or just delete any old log files whenever this process triggers. 通常,您可以使用一些外部进程来管理此问题,或者只要此进程触发,就可以删除任何旧的日志文件。

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

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