views:

1410

answers:

3

Hi Everyone!

Sometimes when i see my logging code i wonder if i do it right. There might be no definitive answer to that, but i've folling concerns:

Library Classes: I have several library classes wich might log some INFO messages. Fatal Errors are reported as exceptions. Currently i have a static logger instance in my classes with the class name as the logging name. (Log4j's: Logger.getLogger(MyClass.class))

Is this the right way? Maybe the user of this library class dont want any messages from my implementation or want to redirect them to an application specific log. Should i allow to set a logger from the "outside world"? How do you handle such cases?

General logs: In some applications my classes might want to write a log message to a specific log, not identified by the classes name. (I.e.: HTTP Request log) What is the best way to do such a thing? A loopup service comes to mind...

+7  A: 

Your conventions are pretty standard and quite fine (imho).

The one thing to watch is memory fragmentation from excessive unnedded debug calls so, with Log4J (and most other Java logging frameworks), you end up with something like this:

if (log.isDebugEnabled()) {
  log.debug("...");
}

because constructing that log message (that you probably aren't using) could be expensive, especially if done thousands or millions of times.

Your INFO level logging shouldn't be too "chatty" (and from what you say, it sounds like it isn't). INFO messages should be generally meaningful and significant, like the application being started and stopped. Things that you might want to know if you encounter a problem. Debug/fine level logging is more used for when you actually have a problem you're trying to diagnose. Debug/fine logging is typically only turned on when needed. Info is typically on all the time.

If someone doesn't want specific INFO messages from your classes, they are of course free to change your log4j configuration to not get them. Log4j is beautifully straightforward in this department (as opposed to Java 1.4 logging).

As for your HTTP thing, I've generally not found that to be an issue with Java logging because typically a single class is responsible for what you're interested in so you only need to put it in one place. In the (rare in my experience) when you want common log messages across seemingly unrelated classes, just put in some token that can easily be grepped for.

cletus
As an fyi, in Scala one can write a debug method that does exactly that code without the verbosity using by-name parameters. The compiler automatically converts the code in the debug() argument into a function that is only evaluated if debug() decides to call it. So wouldn't concatenate the string unless the isDebugEnabled() true.Example code that implements this: override def debug(msg: => AnyRef) = if (isDebugEnabled) logger.debug(msg)http://github.com/dpp/liftweb/blob/338119b8d7a76adcb9f45e9aa8a2b946d9c81118/lift-util/src/main/scala/net/liftweb/util/Log.scala
Blair Zajac
This is yet another good reason to use the {}-construct provided by slf4j.
Thorbjørn Ravn Andersen
+3  A: 

The preferred option for the kind of log4j configuration you're describing is to use the log4j configuration file. This allows users of your implementation to do exactly what you're asking for, since they can override your configuration later on with something more suitable for their own implementation. See here for a very thorough primer.

John Feminella
...there is also a non-xml format which is slightly more readable.
KarlP
A: 

I have probably stolen this from somewhere, but it's nice.

It reduces the risk of mixing up loggers when copying and pasti^h^h^h refactoring, and its less to type.

In your code:

private final static logger = LoggerFactory.make();

...and in LoggerFactory:

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

(Note that the stackdump is done during initialisation.)

KarlP
* ...most probably stolen from Dr Heinz M. Kabutz. But I am not sure
KarlP
Keep in mind that a VM is free to omit stack frames or perform other optimizations so that you might end up with an empty array of StackTraceElements. See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html#getStackTrace() for more information.
Bombe