Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring Java FileHandler Logging to create directories if they do not exist

I'm trying to configure the Java Logging API's FileHandler to log my server to a file within a folder in my home directory, but I don't want to have to create those directories on every machine it's running.

For example in the logging.properties file I specify:

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

This would allow me to collect logs in my home directory (%h) for MyApplication and would rotate them (using the %u, and %g variables).

Log4j supports this when I specify in my log4j.properties:

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

It looks like there is a bug against the Logging FileHandler: Bug 6244047: impossible to specify driectorys to logging FileHandler unless they exist

It sounds like they don't plan on fixing it or exposing any properties to work around the issue (beyond having your application parse the logging.properties or hard code the path needed):

It looks like the java.util.logging.FileHandler does not expect that the specified directory may not exist. Normally, it has to check this condition anyway. Also, it has to check the directory writing permissions as well. Another question is what to do if one of these check does not pass.

One possibility is to create the missing directories in the path if the user has proper permissions. Another is to throw an IOException with a clear message what is wrong. The latter approach looks more consistent.

like image 596
Dougnukem Avatar asked Aug 12 '09 01:08

Dougnukem


People also ask

How do you put logs in Java?

The process of creating a new Logger in Java is quite simple. You have to use Logger. getLogger() method. The getLogger() method identifies the name of the Logger and takes string as a parameter.

What is log configuration?

The log configuration for the container. This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run . By default, containers use the same logging driver that the Docker daemon uses.

What is the use of FileHandler in Java?

The FileHandler can either write to a specified file, or it can write to a rotating set of files. For a rotating set of files, as each file reaches a given size limit, it is closed, rotated out, and a new file opened. Successively older files are named by adding "0", "1", "2", etc. into the base filename.

What is Java logging package?

Java Log Manager logging package. It keeps track the global logging configuration, creates, and maintains the logger instances. We can also use it to set its own application-specific configuration. It includes the following two things: The hierarchical namespace of named Logger.


1 Answers

It seems like log4j version 1.2.15 does it.

Here is the snippet of the code which does it

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

This piece of code is from FileAppender, RollingFileAppender extends FileAppender.

Here it is not checking whether we have permission to create the parent folders, but if the parent folders is not existing then it will try to create the parent folders.

EDITED

If you want some additional functionalily, you can always extend RollingFileAppender and override the setFile() method.

like image 85
Arun P Johny Avatar answered Oct 23 '22 00:10

Arun P Johny