Search code examples
javaclassloggingformattingfilehandler

Getting caller class name for Formatter [Java Logging with File Handler]


I want to add a FileHandler to my logger. And I am also creating a new Formatter(java.util.logging.Formatter) for my FileHandler

In the format method https://docs.oracle.com/javase/7/docs/api/java/util/logging/Formatter.html#format(java.util.logging.LogRecord), is it possible to get the class which called the log https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#log(java.util.logging.Level,%20java.lang.String)method?

Edit: I wrapped my logger in a class, so getSourceClassName() will not work


Solution

  • ...is it possible to get the class which called the log? Note that LogRecord.getSourceClassName() returns the Logger class.

    LogRecord.getSourceClassName() does exactly what you want it to do. Here is an example:

    import java.io.File;
    import java.io.IOException;
    import java.util.logging.FileHandler;
    import java.util.logging.Formatter;
    import java.util.logging.Level;
    import java.util.logging.LogRecord;
    import java.util.logging.Logger;
    
    public class FileHandlerTest {
    
        private static final Logger logger = Logger.getLogger("tester");
    
        static {
            try {
                FileHandler h = new FileHandler();
                logger.addHandler(h);
                h.setFormatter(new TestFormatter());
            } catch (IOException ex) {
                throw new ExceptionInInitializerError(ex);
            }
        }
    
        private static class TestFormatter extends Formatter {
    
            @Override
            public String format(LogRecord record) {
                return record.getSourceClassName();
            }
    
        }
    
        public static void main(String[] args) throws Exception {
            System.out.println(new File(".").getCanonicalPath());
            System.out.println(System.getProperty("user.home"));
            logger.log(Level.INFO, "This not a test. This is the real thing!");
        }
    }
    

    When I run this on my machine it creates a file called java0.log in my user home containing the text FileHandlerTest which is the name of the source class.

    There are a few reason I can think as to why it wouldn't work:

    1. There was a hand off to another thread and you didn't call LogRecord.getSourceClassName() before the hand off. This causes the log record to infer the wrong caller.
    2. You created a 'wrapper' class to perform your logging and the logger reports the 'wrapper' class as the caller. Don't do this. Use the logger directly or use a logging framework. There are plenty of logging bridges out there and anything you will create is going to be a pirate ship plank. That said, the com.sun.mail.util.MailLogger contains the code that all of the user comments have been trying to explain to you.
    3. The record was generated with logp or setSourceClassName and the source class was faked.
    4. There was a problem with your JVM generating exceptions with stack traces.

    You need to include more source code and example log file output data.