我们最近从JUL(java.util.Logging)切换到Log4J,因为我想为不同的日志记录级别添加其他日志文件。
我们在程序中有一个选项,可以选择在程序执行结束时(在所有意图和目的)将日期/时间戳附加到日志文件名。
因为JUL似乎根据需要打开和关闭文件来写入文件,所以它没有被锁定,我们可以简单地使用.renameTo()来更改文件名。
现在,使用Log4J,该文件保持打开并被锁定,阻止我们重命名文件。
在配置日志记录之前,我无法确定文件的名称,因为包含重命名选项的属性文件是在需要日志记录之后的一段时间(这就是我们在程序结束时重命名它的原因)。
您对如何实现这一目标有什么建议吗?
Logback和/或SLF4J会帮助还是阻碍它?
通过在log4j属性文件中使用系统参数,设置属性然后重新加载属性文件,我解决了这个问题。
这允许我在运行结束时将日志文件的名称更改为其他名称,然后重命名旧文件。
它不够优雅,而且非常多,所以我想避免这种情况,因为它也会在运行后留下这些临时文件。
答案 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)