7

I am stuck at understanding a concept related to Logger creation, especially in the context of Java EE.

In my experience, I nearly always used one logger per application, with few cases when I needed a specific logger for a specific part of the application. Only in these cases I was creating through my wrapper a new logger. And, if we talk about identifying the class which called the logger, I was doing a simple thing:

public const String ThisIdentifier = "MyLoggerCallingClass";

And I was passing this as a parameter to the logger method, even if there were some additional keystrokes I needed to do.

Now I'm facing a conceptual problem: Why create logger per class, and not one per application.
I have found the following answers:

Best way to initialize loggers

Why loggers per class recommended

However, if I get this info from apache documentation on getLogger:

Retrieve a logger named according to the value of the name parameter. If the named logger already exists, then the existing instance will be returned. Otherwise, a new instance is created.

I understand that if I do the per class way, and let's say that I have 50 packages in a Java EE application, and 10 classes per package, I will have 500 logger instances in my app!

I come from a C, C++ and C# perspective, and always in my mind I have the following:
"Use memory sparingly, create instances only as needed, cleanup after yourself, don't abuse etc..."

I don't know the actual details of the logger creation, and I understand the idea of being able to better filter log results, but can anyone explain me why to go that way and how useful it is in the end, to create instance per class, why waste memory and have many instances, instead of just calling a logger method with a parameter?

EDIT

While maybe it's true, that in general people do not care about the many so called "lightweight" logger instances created, I ended up with my colleagues on the project to create a wrapper class for log4j, that I instance in every class where I want to use logger. This wrapper class contains a reference to a single instance of logger by default

Logger.getLogger(Wrapperclass.getName())

and also the name of the class where this specific logger is called, so to log the logging class name. In the case when I will need specific classes to be logged, I will just change the

Logger.getLogger(Wrapperclass.getName())

to

Logger.getLogger(Callingclass.getName())

rebuild the app and run it. In my opinion this solution seems more clean and neat.

EDIT 2:

Found out this:

Based on our previous work on log4j, logback internals have been re-written to perform about ten times faster on certain critical execution paths. Not only are logback components faster, they have a smaller memory footprint as well

Based on the quote above, in which we can clearly see the phrase containing "smaller memory footprint", I can make the conclusion that my suspicions weren't so false. With the team we now take into the consideration the idea of switching to logback if we will be able to achieve the same logging functionality we need and do with log4j.

Hope that this question helps others make the right decision!

2
  • 2
    With loggers you have to find a tradeoff between what you gain (more flexible runtime way to decide what you want to see in the log) and what you loose (memory). If there is one static logger per class you loose the more memory the more classes you have. Whould you eleminate classes and readable namespace/class names to save some extra bytes? why to waste space for a class java.util.ArrayList when j.AL whould be enough? For me this debate sounds like premature optimisation
    – k3b
    Commented Mar 2, 2016 at 8:12
  • In my opinion, this approach you state is the reason why all Java applications are so memory hungry, because all think this way :) And it is not premature optimization. I've lost 2 days of investigation to spare the memory, at the same time leaving me the opportunity to change anytime to the "standard" solution that you support. I think this is way better than the case when you create loggers per class and you can't get rid of them easily :)
    – XMight
    Commented Mar 2, 2016 at 8:22

1 Answer 1

7

There seems to be a mismatch between what you mean by the word "logger" and what the Log4J framework means with "logger".

Within the Log4J framework, a logger is a very lean class. It is not much more than a wrapper around the ThisIdentifier that you use and an container for functions that generate logging statements.
All the heavy lifting of the logging happens in the Appenders, Filters and Layouts.

As stated in the Log4J architecture

Logger

As stated previously, Loggers are created by calling LogManager.getLogger. The Logger itself performs no direct actions. It simply has a name and is associated with a LoggerConfig. It extends AbstractLogger and implements the required methods. As the configuration is modified Loggers may become associated with a different LoggerConfig, thus causing their behavior to be modified.

So, having several hundreds of Logger instances does not put any burden of consequence on your system.

2
  • Well, what I see from the source code is the following: Logger, having roughly 150 lines of code, extending Category, having roughly 1000 lines of code. This will be compiled in some kilos I suppose. So, if I need only ThisIdentifier, and to leave out the only benefit that I see, the "per class filtering" idea, I don't see why I would go that way (currently, as I see it).
    – XMight
    Commented Feb 25, 2016 at 11:05
  • 7
    How many lines of code there are doesn't say anything about the memory consumption of instances. Regardless of if you have 1 or 10.000 instances, there will be only a single copy of the function implementations. It is only the data members that get allocated per instance, all the rest exists only in a single shared copy. That would be the same for a "one per application" logging framework. Commented Feb 25, 2016 at 12:38

Not the answer you're looking for? Browse other questions tagged or ask your own question.