views:

251

answers:

3

Often I will send debugging info to my log file from within Java, and it helps to give decent information as to where in the code the log message was generated so I can quickly refer back to it. I don't want to hard-code anything in the log message about its location, because I have to remember to update the log message if I rename its method or otherwise refactor the code into a different structure. I'd love to have a static function that simply returns the calling function's class and method name. For example, if I have a class called Machine and a method called doStuff, I'd like my log message generation code in that method to look something like this:

String log_msg = Blah.getClassAndMethodName()+" did the wrong thing!";

The static method getClassAndMethodName() in class Blah would return "Machine.doStuff". That way, when I look at the log file, I can easily tell where in the code the message was generated. I realize this is a bit tricky, since I need this method in Blah to return information about its calling function in a separate class, Machine, but this would make it easy to just use this static call anywhere.

I don't know if this is possible, but I'd appreciate any pointers towards an answer! Also, assuming it is possible, is this a particularly high overhead kind of operation? (I'm assuming reflection would be needed, not my strong suit)

Thanks!

+7  A: 

If you call Thread.getStackTrace(), you can determine your call stack from there.

Returns an array of stack trace elements representing the stack dump of this thread. This method will return a zero-length array if this thread has not started or has terminated. If the returned array is of non-zero length then the first element of the array represents the top of the stack, which is the most recent method invocation in the sequence. The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.

Re. performance. I can't advise beyond suggesting that you measure it. If your debug output can be enabled/disabled, I would ensure that you only do the above when debug output is enabled, so you only take the performance hit when required.

Brian Agnew
+2  A: 

Try this:

    public static Log make() {
 Throwable t = new Throwable();
 StackTraceElement directCaller = t.getStackTrace()[1];
 return LogFactory.getLog(directCaller.getClassName());
}

The first entry in in the stacktrace, is the calling class

raoulsson
That's perfect! Thanks very much!
ZenBlender
To reveal the sources, Heinz Kabutz wrote about it once on his "Java Specialist Newsletter" years ago. Mainly to avoid the "hardcoded" MyClass.class argument in the log4j logger instantiation. With this, you can just type MyLoggerFactory.make(). Used it ever since.
raoulsson
+1  A: 

Consider using a logging framework to do this.

I believe that the standard Java 1.4 java.util.logging.* allow what you want.

Thorbjørn Ravn Andersen