在程序运行期间重命名Log4J日志文件

时间:2011-03-28 13:31:46

标签: java log4j

我们最近从JUL(java.util.Logging)切换到Log4J,因为我想为不同的日志记录级别添加其他日志文件。

我们在程序中有一个选项,可以选择在程序执行结束时(在所有意图和目的)将日期/时间戳附加到日志文件名。

因为JUL似乎根据需要打开和关闭文件来写入文件,所以它没有被锁定,我们可以简单地使用.renameTo()来更改文件名。

现在,使用Log4J,该文件保持打开并被锁定,阻止我们重命名文件。

在配置日志记录之前,我无法确定文件的名称,因为包含重命名选项的属性文件是在需要日志记录之后的一段时间(这就是我们在程序结束时重命名它的原因)。

您对如何实现这一目标有什么建议吗?

Logback和/或SLF4J会帮助还是阻碍它?


通过在log4j属性文件中使用系统参数,设置属性然后重新加载属性文件,我解决了这个问题。

这允许我在运行结束时将日志文件的名称更改为其他名称,然后重命名旧文件。

它不够优雅,而且非常多,所以我想避免这种情况,因为它也会在运行后留下这些临时文件。

2 个答案:

答案 0 :(得分:2)

一种万无一失的方法是实现自己的log4j Appender,可能基于FileAppender(http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/FileAppender.html)。添加您自己的专用API以请求重命名文件。

我还没有尝试过这个,但我要采取的机制是使用底层API setFile(...):http://www.jdocs.com/log4j/1.2.13/org/apache/log4j/FileAppender.html#M-setFile%28String,boolean,boolean,int%29

例如:

public class RenamingFileAppender extends FileAppender {

...

/** fix concurrency issue in stock implementation **/
public synchronized void setFile(String file) {
  super.setFile(file);
}

public synchronized void renameFile(String newName) {
  // whole method is synchronized to avoid losing log messages
  // implementation can be smarter in having a short term queue
  // for any messages that arrive while file is being renamed
  File currentFile = new File(this.fileName);
  File newFile = new File(newName);
  // do checks to ensure current file exists, can be renamed etc.
  ...
  // create a temp file to use while current log gets renamed
  File tempFile = File.createTempFile("renaming-appender", ".log");
  tempFile.deleteOnExit();
  // tell underlying impl to use temporary file, so current file is flushed and closed
  super.setFile(tempFile.getAbsolutePath(), false, this.bufferedIO, this.bufferSize);
  // rename the recently closed file
  currentFile.renameTo(newFile);
  // now go back to the original log contents under the new name. Note append=true
  super.setFile(newFile.getAbsolutePath(), true, this.bufferedIO, this.bufferSize);
}

答案 1 :(得分:0)