[slf4j-user] Idiom for declaring loggers

Simon Kitching skitching at apache.org
Wed Apr 30 09:42:40 CEST 2008


Ceki Gulcu schrieb:

> > Hello all,
> >
> >
> > A common idiom for logging is to create a logger in each class that is
> > based on the class name.
> >
> > package some.package;
> >
> > import org.slf4j.Logger;
> > import org.slf4j.LoggerFactory;
> > public class MyClass {
> >    final Logger logger = LoggerFactory.getLogger(MyClass.class);
> >    ... etc
> > }
> >
> > As Heinz Kabutz describes [1], the name of the class is then
> > duplicated in the class, both in the class definition and in the
> > logger field definition.
> >
> > The following logger declaration idiom is resistant to cut-and-pasting
> > between classes. However, it assumes that the logger variable is an
> > instance variable of the class.
> >
> > package some.package;
> >
> > import org.slf4j.Logger;
> > import org.slf4j.LoggerFactory;
> > public class MyClass {
> >    final Logger logger = LoggerFactory.getLogger(this.getClass());
> >    ... etc
> > }
> >
> > If the hosting class is serializable, then the logger variable needs
> > to be declared as transient.
> >
> > Does anyone know of a better alternative?
> >
> > [1] http://www.javaspecialists.co.za/archive/newsletter.do?issue=137
> >
> >   
>   

Yep, having to change the parameter to the getLogger method is a pain
when cutting-and-pasting. I'd love to hear of a good solution. But I
think that short of a Java language change to support a "thisClass"
keyword or similar we are stuck with it.

The "this.getClass()" approach has quite different behaviour from the
usual approach. When a base class logs messages, the category will not
be the name of the base class, but instead the name of the concrete
subclass type. I know of at least one library that does this
deliberately, but it seems to me that the traditional approach is
better, as it's useful to know exactly what source code file the message
is coming from.

Filtering of messages is also less predictable when using the runtime
type. Imagine:
  class example.VerboseBase logs lots of stuff
  class example.Concrete1 subclasses it.
  class example.Concrete2 subclasses it.
With category being the runtime-type, you cannot disable the problem
verbose output by setting a threshold on category "example.VerboseBase".
Instead, you need to set the threshold on every *subclass* of that type
which exists in the program. And there is no way to allow debug messages
for a subclass while excluding debug messages from the base class.

The reverse is technically true for the existing approach; you cannot
easily say "I don't care about logging for class Concrete1 at all, but
want everything (including messages from base classes) for Concrete2.
However in practice, this seems a less common requirement.

BTW, the last proposal in this article shows exactly the same flaw as
the log5j lib. The JVM makes no guarantee that Throwable.getStackTrace
returns valid info; it just makes a "best attempt". This is presumably
why the java.util.logging API takes "sourceClass" and "sourceMethod"
parameters for its logging calls; this info cannot reliably be deduced
from the runtime stack in optimised programs.

So, sorry but I cannot suggest any easy solution for cut/paste of
logging declarations.

Regards,
Simon





More information about the slf4j-user mailing list