Should logger be private static or not - java

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?

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());

I used to think that all loggers should be static; however, this article at wiki.apache.org brings up some important memory concerns, regarding classloader leaks. Declaring a logger as static prevents the declaring class (and associated classloaders) from being garbage collected in J2EE containers that use a shared classloader. This will result in PermGen errors if you redeploy your application enough times.
I don't really see any way to work around this classloader leak issue, other than declaring loggers as non-static.

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).

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?

Related

Initialising the logger in each and every class in java of sl4j

'
I am using sl4j for logging in my java classes although I have added the dependency too, my question is that if I have lots of java classes say a count of 50 classes in different packages, then for logging do I need to add the below statement in my every class, rite now suppose below code is for my main class is
final Logger LOG = LoggerFactory.getLogger(Main.class);
Is there any way through which I do not need to initialize the logger of sl4j in each and every class explicitly
It is always recommended to use the following code.
final Logger LOG = LoggerFactory.getLogger(Main.class);
It is required because, all the log statements are specific to specific classes and methods for log analysis. If we create a separate alternative to the above statement, then also we need to define in each class. Think of a situation, we have System.out.println statement which we write everywhere for analysis. Can we think of alternative to the above ? I don't think.
If your project is spring based, you can use AOP to log the messages.

use of singleton design pattern in real time java applications

I understand the singleton design pattern concept, but I never really come across implementing singleton pattern in java applications or web based applications.
So tell me where we are using this approach in real time applications.
As described by the pattern, any time you want there to exist only a single instance of something, you would use the Singleton Pattern.
A common example might be a Logger object. There could be many places throughout the system where one would invoke a logger to, well, log something. But you may only ever need one such instance. This can be particularly true if constructing the instance is a heavy operation.
Something like this:
public class Logger {
private static final Logger INSTANCE = new Logger();
private Logger() {
// do something to initialize the logger
}
public static Logger getInstance() {
return INSTANCE;
}
// implementation ...
}
Then any code which needs to reference the logger doesn't need to instantiate it (can't, in fact), and instead just uses the singleton:
Logger.getInstance().Log("some message");
Other real-world examples might include a dependency injection container, a read-only data access service (such as a lookup service which caches results), etc. Generally anything where initialization or repeated operations can be heavy and which is thread-safe.
Singleton always makes sense when dealing with heavy objects where it makes no sense to have more than one instance across the whole application.
Since you are dealing with Web-Applications you should have been dealt with objects which are the same for each user/session/request. Database-Connection-Pool is probably a good example, or a Servlet. It doesn't make sense to create a new Pool for each request. One Pool for the whole application should be sufficient. Other examples are probably Loggers, Email-Client, Global-Settings, those things should be the same instances for each user otherwise you will run out of resources. Or did i get something wrong?

Implementing logger for java application

I am trying to implement logger using apache commonn logging and log4j.xml file as configuration file .
So in the actual java code i am writing log as
I am using appache common logging
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
and i am logging information such as in . I am creating a instance of log for each class
private static Log logger = LogFactory.getLog( MyClass.class );
private static final String name ="SAM";
logger.info("name= "+name);
So now my question is does implementing logger like this create a performanace issue?
Is it necessary to check log like
if ( log.isInfoEnabled( ) )
{
log.info( "Info message" );
}
The confusion is mainly because in Apache common logging they have mentioned to do this and in log4j they have mentioned it is unnecessary.
Each time when we write log in the files?
-Sam
yes and no, logging always reduces your performance, but some functions are more expensive then others, e.g. getting the calling class/method-Name uses reflection and is very slow. But a normal logfuntion is not that expensive if you do not have an expensive statement in the calling logging function (this will be evaluated every time before the log-Level is checked. In this case you can use the .isLevelEnabledcheck to prevent the evaluation). Also logging to the console takes longer for the output than logging to a file. You will find more information about this by googling and in the FAQ/manual of log4j.
You do not have to check the Log-Level before logging. This is done within the log-function itself. Therefore are the different methods for every Level or the Level-Argument in the generic log-Method.
A big potential performance problem with logging is usually if you have something passed into the log method that is very expensive to convert to a string. That's why you have methods like isInfoEnabled(), so that the code can avoid creating the message string from the parameter (otherwise the check within the info() method is too late, the conversion is already done). If your objects passed into the log methods are strings or are not very involved then the is*Enabled() methods won't be that useful.
SLF4J is worth checking out. It doesn't depend on classloader tricks (which is a big part of why commons-logging is reviled), and it has a different way of creating log messages which delays when the message string gets created so that the enabled check can take place within the logging method.
There's a better way to do all of this. You can get really great performance without having to add the clutter of ifDebugEnabled, etc methods. Check out something like Logback (or SLF4J). Here's the great documentation about what kind of an API you want. Note that Log4J and Commons-Logging doesn't have an API like this. Use Parameterized Logging.

Static vs. instance method for shared use

Here's what I am trying to determine...
I have a utility class to append lines to a text file.
This must be used by a number of other classes, like
a common logging file.
In my first implementation, I had all the classes
that wanted to use it make a reference-less instance, e.g.
new Logger(logline,logname);
The constructor creates a PrintWriter, appends the line
and closes the file.
This seemed wasteful, since a new instance gets made for
every line appended.
The alternative was to use a static method, called "writeln"
in this common class, since I had understood that static
methods and data re-use the same memory over & over...but
this static method creates an instance of PrintWriter
to do its job, so doesn't that mean that a new instance
of PrintWriter is created for every line, like #1?
Anyway, (I am relatively new to Java ) is there a
well-known, approved way of doing this, or do we
just create away, and let the garbage-collector
clean up after us?
Thanks
The sensible answer is that you should use a "serious" logging package, such as Commons Logging.
However, to answer your question, in this case you should use a static method (unless you're wanting to maintain logging class instances in your code, in which case you should follow the other answers in this thread). Additionally, you should have a static field that's initialised to, say, a Map<String, PrintWriter>. (You don't have to use String as the key: if you want a finite number of logging target types, use an enum.)
Then, when your method sees a key that's not existent in the map yet, it'd create the PrintWriter on the spot, and sticks it in the map. You probably want to use a ConcurrentHashMap as the backing map type, so it's thread-safe.
You also need to provide a way to close a logging target (which will also clear the associated entry from the map).
Good luck!
You shouldn't be doing any work in your contructor.
Constructors are for object setup.
You should create a Log() method to do the actual logging.
Logger l = new Logger();
l.Log(logline,logname);
l.Log(logline,logname);
or you can setup the logger as a Singleton.
Logger.getInstance().Log(logline, logname);
Singleton Pattern in Java:
http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html
There are several kinds of state that this object might want to hold onto, particularly the PrintWriter. If your Logger class were to store these as instance data, then the method for doing the logging needs to be an instance method, not a static method. Hence you need to separate out the logging from the construction:
// Pass only the PrintWriter into the constructor, not the line to be logged.
Logger myLogger = new Logger(filename);
...
// Log a message
myLogger.log("This is a message to be logged.");
// Log another message, just for kicks.
myLogger.log("this shows that myLogger can be used repeatedly.");
I haven't shown any of the implementation details, but I hope this is enough to get you going.

Cons for defining logger non-static

Comments for this answer How do you reduce Java logging boilerplate code? strongly suggest not to use loggers as instance member variables. I can think of two negative side-effects:
1) superclass logs with the subclass's logger
2) object cannot be serialized (unless marked transient)
But if serializing is not necessary and logging with subclass name is not a problem, is there anything else why it should be avoided? I think it reduces boilerplate code and avoids copy-paste errors while copying logger variable definition from one class to another. Even Spring framework (which I believe has very good coding standards) uses this method.
If your Logger is an instance member instead of static, the Logger has to be retrieved every time a new object is created. Albeit this overhead is probably insignificant, but it's one disadvantage.
From a design perspective, Loggers aren't really a property of an object, since they're usually meta-information about your system rather than business information within the system itself. A Logger isn't really part of something like a Car object in the same way an Engine or a Transmission is. Tying Loggers to objects as members (in most cases) doesn't make sense semantically more than anything.
You might want to have a look at these pages discussing the subject:
SLF4j FAQ: Should Logger members of a class be declared as static?
Commons Wiki: When Static References to Log objects can be used
The major difference asides from the Superclass logging with subclass name, of course, is that you'll have one Logger object per member of your class. Depending on how many classes are using logging, this can be a huge amount of Loggers, so memory bloat may be an issue.
Plus from an abstract point of view, the logger really does belong to the class and can be shared between all instances, rather than each instance needing its own private copy, so it makes sense to declare it as static. Flipping your question around, what advantages does it have to making it non-static? (Being able to pass getClass() into the getLogger() call instead of passing in the class constant is the only thing I can think of, and that's such a tiny thing).
Another, probably minor con: wasted memory, especially when you have lots of instances, each one with its own logger
Try debugging an error where you see a message generated by the SuperClass class when the error is really being logged in the SubClass class. I've seen several situations where developers create a LoggingUtils class which generates messages which generally duplicate the things which are already baked-in by the logging framework.
The only real situation I see for using a shared logging instance is something like the Apache commons HttpClient logger httpclient.wire which is shared between several classes for logging the contents of the requests and responses sent through the client. This particular logging situation does not log information for the actual implementation of the package, it logs information about the whole http "transaction".
One of the main concerns are at cleaning memory instances. Even you don't create objects of a class, since you use static instances of logger there will be references to those objects.
Also as apache says, this keeps references so they won't freed once after used.
Apache Wiki says like this
The use of the static qualifier can be beneficial in some circumstances. However in others it is a very bad idea indeed, and can have unexpected consequences.
The technical result of using static is obvious: there is only one Log reference shared across all instances of the class. This is clearly memory efficient; only one reference(4 or 8 bytes) is needed no matter how many instances are created. It is also CPU-efficient; the lookup required to find the Log instance is only done once, when the class is first referenced.

Categories