配置 Java 文件处理程序日志记录以创建目录(如果它们不存在)

2022-09-04 02:07:02

我正在尝试配置Java日志记录API的FileHandler,以将我的服务器记录到我的主目录中的文件夹中的文件中,但我不想在它正在运行的每台计算机上创建这些目录。

例如,在我指定的 logging.properties 文件中:

java.util.logging.FileHandler
java.util.logging.FileHandler.pattern=%h/app-logs/MyApplication/MyApplication_%u-%g.log

这将允许我在 MyApplication 的主目录 (%h) 中收集日志,并轮换它们(使用 %u 和 %g 变量)。

Log4j支持这一点,当我在我的log4j.properties中指定:

log4j.appender.rolling.File=${user.home}/app-logs/MyApplication-log4j/MyApplication.log

看起来有一个针对日志文件处理程序的错误:错误6244047:除非它们存在,否则无法指定记录FileHandler的driectorys。

听起来他们不打算修复它或公开任何属性来解决此问题(除了让您的应用程序解析loging.properties或硬编码所需的路径):

看起来 java.util.logging.FileHandler 并不期望指定的目录可能不存在。通常,无论如何,它都必须检查此条件。此外,它还必须检查目录写入权限。另一个问题是,如果其中一项检查未通过,该怎么办。

一种可能性是,如果用户具有适当的权限,则在路径中创建缺少的目录。另一种方法是抛出一个IOException,清楚地传达错误的信息。后一种方法看起来更一致。


答案 1

看起来log4j版本1.2.15做到了。

这是执行该操作的代码片段

public
 synchronized
 void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
                                                        throws IOException {
    LogLog.debug("setFile called: "+fileName+", "+append);

    // It does not make sense to have immediate flush and bufferedIO.
    if(bufferedIO) {
      setImmediateFlush(false);
    }

    reset();
    FileOutputStream ostream = null;
    try {
          //
          //   attempt to create file
          //
          ostream = new FileOutputStream(fileName, append);
    } catch(FileNotFoundException ex) {
          //
          //   if parent directory does not exist then
          //      attempt to create it and try to create file
          //      see bug 9150
          //
          String parentName = new File(fileName).getParent();
          if (parentName != null) {
             File parentDir = new File(parentName);
             if(!parentDir.exists() && parentDir.mkdirs()) {
                ostream = new FileOutputStream(fileName, append);
             } else {
                throw ex;
             }
          } else {
             throw ex;
          }
    }
    Writer fw = createWriter(ostream);
    if(bufferedIO) {
      fw = new BufferedWriter(fw, bufferSize);
    }
    this.setQWForFiles(fw);
    this.fileName = fileName;
    this.fileAppend = append;
    this.bufferedIO = bufferedIO;
    this.bufferSize = bufferSize;
    writeHeader();
    LogLog.debug("setFile ended");
}

这段代码来自FileAppender,RollingFileAppender扩展了FileAppender。

在这里,它不是检查我们是否有权创建父文件夹,但如果父文件夹不存在,那么它将尝试创建父文件夹。

编辑

如果你想要一些额外的功能,你总是可以扩展RollingFileAppender并重写setFile()方法。


答案 2

你可以写这样的东西。

package org.log;

import java.io.IOException;
import org.apache.log4j.RollingFileAppender;

public class MyRollingFileAppender extends RollingFileAppender {

    @Override
    public synchronized void setFile(String fileName, boolean append,
        boolean bufferedIO, int bufferSize) throws IOException {
        //Your logic goes here
        super.setFile(fileName, append, bufferedIO, bufferSize);
    }

}

然后在您的配置中

log4j.appender.fileAppender=org.log.MyRollingFileAppender

这对我来说非常有效。


推荐