I am working on a project, and am currently working on implementing some logging with log4j and I was curious about how I should go about implementing the logs. The two implementations I am kicking around are as follows:
First Option
Use single log from super class for that class and all sub classes:
public abstract class AbstractFoo {
protected static Log LOG = LogFactory.getLog(AbstractFoo.class);
...
}
public class Foo extends AbstractFoo {
public void someMethod() {
LOG.info("Using abstract log");
}
}
Second Option
Use individual logs for each class, super and subs:
public abstract class AbstractFoo {
private static Log LOG = LogFactory.getLog(AbstractFoo.class);
...
}
public class Foo extends AbstractFoo {
private static Log LOG = LogFactory.getLog(Foo.class);
public void someMethod() {
LOG.info("Using own log");
}
}
What makes more sense and why?
I wouldn't do either. Instead I would make it use the correct class in both cases.
If you are not doing lots of logging (which is a good idea anyway) you can use a method instead.
If there is a class which calls this a lot you can override it to give you a cached instance.
The same can be achieved by playing with constructors. Add logger at the Base class level and set it from every Derived class using super(). There is the code :
This is my solution (final static logger):
There are 2 reasons (that I can think of) for having a Logger in the abstract class:
If you prefer static loggers (that's my preferred choice too), then n1cr4m's answer solves #1 and #2 very well.
However, if you're more interested in #2 and dislike the fact, that each concrete class needs to implement
getLogger()
, then you could do the following. As an example I'll use a converter:The logger can be a static logger from a concrete class. Now anytime you log, you will uniformally print the prefix, which also forces the identification of the object it converts.
The drawback of this solution, is that if
AbstractConverter
needs to use the logger himself in one of its methods, it wont be able to use the logger from the concrete class, unless you also make this a parameter, which I highly discourage. If you need this kind of functionality, use n1cr4m's solution.If you create the logger in the abstract class, the logs will all come out tagged as originating from AbstractFoo. If you want/need to see logs tagged with the child class from which the log occurred, create loggers for the children classes.
Both make sense. It depends on your application.
I think that more often used practice is to have private logger for each class. This allows you to configure logging both per class and per package. Remember, that
AbstractFoo
andFoo
may belong to different packages and probably you want to see logs fromFoo
only.Moreover always think twice if you want to write
protected
field. It is not completely forbidden but a well known bad practice. It makes your code less readable and difficult to maintain.