views:

65

answers:

2

Hi folks. How can I write caller location information (Java source file and line), in a log file using Java and log4j, but without hurting performance? log4j allow you to write such information in the log file, but it uses the stack trace to get that it information, every time a log statement is issued, what causes performance degradation. I'm looking for a performance friendly alternative, like getting the location information at compile time instead at runtime. It is possible to use annotations to accomplish that? Or maybe some other technique?

A: 

I agree with Rob that it is generally unnecessary. Usually there's some distinct string in a log message, searching for it will get to the source. With a good IDE this is really fast.

Now, given the question as is, this is a possible solution:

Class Foo
    void bar()
        new Logger(){} . warn("blah");

for each log action at runtime, a new object is created - that's not a problem.

for each line of source containing such log statement, a new class is created. that can be too many.

here's how the magic works:

abstract public class Logger
    static Map<Class, String> sourceInfo = new ...
    public Logger()
        Class thisClass = this.getClass();
        String info = sourceInfo.get(thisClass);
        if(info==null)
             info = ... // init from stack trace
             sourceInfo.put(thisClass,info)
        this.info = info

     public void warn(msg)
        log(WARN, this.info,msg)
irreputable
+1  A: 

How about making it part of the build process to replace certain placeholders, like $filename$ and $linenumber$ in this snippet.

logger.info("The original message... $filename$ $linenumber$");

To replace the filename, it may suffice to have keyword substitution with your revision control system. Disclaimer: this is just from the top of my head, I never tried it myself.

Adam Schmideg
Although I have not tested this approach, it seems a suitable solution for use in a production enviroment.
Renan Vinícius Mozone