tags:

views:

108

answers:

5

Should logger be declared static or not? Usually I've seen two types of declaration for a logger :

    protected Log log = new Log4JLogger(aClass.class);

or

    private static Log log = new Log4JLogger(aClass.class);

Which one should be used? what are the pro's and con's of both?

Thank you.

+7  A: 

The advantage of the non-static form is that you can declare it in an (abstract) base class like follows without worrying that the right classname will be used:

protected Log log = new Log4JLogger(getClass());

However its disadvantage is obviously that a whole new logger instance will be created for every instance of the class. This may not per se be expensive, but it adds a significant overhead. If you'd like to avoid this, you'd like to use the static form instead. But its disadvantage is in turn that you have to declare it in every individual class and take care in every class that the right classname is been used during logger's construction because getClass() cannot be used in static context. However, in the average IDE you can create an autocomplete template for this. E.g. logger + ctrl+space.

On the other hand, if you obtain the logger by a factory which in turn may cache the already-instantiated loggers, then using the non-static form won't add that much overhead. Log4j for example has a LogManager for this purpose.

protected Log log = LogManager.getLogger(getClass());
BalusC
+1  A: 

I would stick with private, and static for sure. If you opt for protected, the same logger is used for all your subclasses, too (or you have the parent's logger hidden by a child's logger of the same name). With private, you get a different logger for each class, and that gives you finer granularity for enabling logging. That's a good thing.

Carl Manaster
A: 

Use inversion of control and pass the logger into the constructor. If you create the logger inside the class you are going to have a devil of a time with your unit tests. You are writing unit tests aren't you?

Wayne Allen
A: 

Usually we always use static loggers. This is the way a logger to be used. As you see in all of the popular logging API like log4j provide a way to add threadlocal info to log entries like sessionid, threadid and so on (it is called MDC). So the API itself tells you to use static logger. Your problem is mainly that you do not want to write things like this:

public class A
{
      private static logger = new Logger( A.class );
}

Since writing classname everywhere is boring and not copy-paste safe. The solution is simply call something that fills an exception to see stack, and simply pick the first item to get the caller class. Read this to see how it works. Then you will get the standard "copyandpasteable" line, that can be put everywhere. It can be even an extra method in a childclass of standard logger class like this: MyLogger.getDefaultLogger().

Gábor Lipták
A: 

The most important difference is how it affects your log files: in which category do logs go?

  • In your first choice, the logs of a subclass end up in the category of the superclass. That seem very counter-intuitive to me.
  • There is a variant of your first case:

    protected Log log = new Log4JLogger(getClass());

    In that case, your log category says which object the code that logged was working on.

  • In your second choice (private static), the log category is the class that contains the logging code. So normally the class that is doing the thing that is being logged.

I would strongly recommend that last option. It has these advantages, compared to the other solutions:

  • There is a direct relation between the log and the code. It is easy to find back where a log message came from.
  • If someone has to tune logging levels (which is done per category), it is usually because they are interested (or not) in some particular messages, written by a particular class. If the category is not the class that is writing the messages, it is harder to tune the levels.
  • You can log in static methods
  • Loggers only need to be initialized (or looked up) once per class, so at startup, instead of for every instance created.

It also has disadvantages:

  • It needs to be declared in every class where you log messages (no reuse of superclass loggers).
  • You need to take care to put the right classname when initializing the logger. (But good IDE's take care of that for you).
Wouter Coekaerts