AndyJ
AndyJ

Reputation: 1314

How can I output the name of the current java.util.logging.Logger log file name?

I have a tool that is ran in multiple JVMs but logs to the same %t (temp) directory. I am using the %u (unique) pattern variable in the logging.properties file so that each instance logs to a different log file.

If the process identifies a failure (this is a monitoring tool) it sends an email and I want to attach the log file of the particular instance that encountered the failure. But how do I get the log file path? Also gladly accepted would be a better approach if this is not a good one.

Upvotes: 1

Views: 3259

Answers (1)

jmehrens
jmehrens

Reputation: 11045

There is an RFE filed with Oracle under JDK-4798814 getFiles() needed for java.util.logging.FileHandler that covers this.

You can resort to reflection if you are not using a security manager.

public class GetFileHandler extends FileHandler {

    public GetFileHandler() throws IOException {
        super();
    }

    /**
     * Gets the files used by this handler.  Index zero is the file that is
     * in use.
     *
     * @return a array of files.
     * @throws IOException if there is an error.
     * @throws SecurityException if not allowed.
     */
    public File[] getFiles() throws IOException {
        return GetFileHandler.getFiles(this);
    }

    /**
     * Gets the files used by this handler.  Index zero is the file that is
     * in use.
     *
     * @param h any non null FileHandler.
     * @return a array of files.
     * @throws NullPointerException if the given FileHandler is null.
     * @throws IOException if there is an error.
     * @throws SecurityException if not allowed.
     */
    public static File[] getFiles(FileHandler h) throws IOException {
        try {
            Field f = FileHandler.class.getDeclaredField("files");
            f.setAccessible(true);
            synchronized (h) {
                return ((File[]) f.get(h)).clone();
            }
        } catch (ReflectiveOperationException roe) {
            throw new IOException(roe);
        }
    }
}

Keep in mind that this solution might race against file rotation. It also might break if the FileHandler source code is changed.

If you don't need rotation then you can always extend the StreamHandler and provide a known file location.

public class KnownFileHandler extends StreamHandler {

    private final File file;

    public KnownFileHandler() throws IOException {
        String v = LogManager.getLogManager().getProperty(getClass().getName() +".name");
        if(v == null) {
            v = "knownfilehandler.log";
        }
        file = new File(v);
        this.setOutputStream(new FileOutputStream(file));
    }


    public File getFile() {
        return this.file;
    }
}

If the monitoring tool supports incoming TCP connections then the java.util.logging.SocketHandler would be a way to send all of the log information to the monitoring tool and then you could have the monitoring tool decide where to store or send the log data.

Upvotes: 2

Related Questions