配置Java FileHandler日志记录以创建不存在的目录

Dou*_*kem 14 java logging log4j

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

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

java.util.logging.FileHandler
java.util.logging.FileHandler.pattern=%h/app-logs/MyApplication/MyApplication_%u-%g.log
Run Code Online (Sandbox Code Playgroud)

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

当我在log4j.properties中指定时,Log4j支持这个:

log4j.appender.rolling.File=${user.home}/app-logs/MyApplication-log4j/MyApplication.log
Run Code Online (Sandbox Code Playgroud)

看起来Logging FileHandler存在一个错误: 错误6244047:除非它们存在,否则无法指定driectorys来记录FileHandler

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

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

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

Aru*_*hny 8

似乎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");
}
Run Code Online (Sandbox Code Playgroud)

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

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

EDITED

如果你想要一些额外的功能,你可以随时扩展RollingFileAppender并覆盖setFile()方法.

  • 如果我在log4j框架内但是我正在使用Java Logging框架,并且没有钩子来拦截FileHandler创建调用(除了在第一次访问Logger时捕获异常,例如logger.info( "测试"). (3认同)
  • 用户没有询问Log4J. (2认同)

Aru*_*hny 5

你可以写这样的东西.

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

然后在您的配置中

log4j.appender.fileAppender=org.log.MyRollingFileAppender
Run Code Online (Sandbox Code Playgroud)

这对我来说非常适合.