jueves, 21 de julio de 2011

Choosing a Java logger, never use System.out in web applications!

Almost without notice it, loggers appeared everywhere, under that stone, behing the tree, look, another one! As an example, here we can find a handful of them (implementations, facades and factories).

Until now, we had a good reference implementation, log4j, and JUL (java.util.logging), although I always used log4j. An article talking about them. Something is clear, never use System.out in web applications, because it all goes down the drain of catalina.out, that useful file full of garbaje when other thing but server information is written.

But today we are here to talk about loggers. What should I choose? It is not as important as.. what the fuck should I do if some library uses log4j, another JUL, other MyNiceLogger, and so on...?
Two solutions for this agony, "apache commons logging" (JCL) is designed to be used as a thin bridge to the final runtime-chosen logger.

"When writing a library it is very useful to log information. However there are many logging implementations out there, and a library cannot impose the use of a particular one on the overall application that the library is a part of.

The Logging package is an ultra-thin bridge between different logging implementations. A library that uses the commons-logging API can be used with any logging implementation at runtime. Commons-logging comes with support for a number of popular logging implementations, and writing adapters for others is a reasonably simple task.

Applications (rather than libraries) may also choose to use commons-logging. While logging-implementation independence is not as important for applications as it is for libraries, using commons-logging does allow the application to change to a different logging implementation without recompiling code.

 Note that commons-logging does not attempt to initialise or terminate the underlying logging implementation that is used at runtime; that is the responsibility of the application. However many popular logging implementations do automatically initialise themselves; in this case an application may be able to avoid containing any code that is specific to the logging implementation used."


JCL has to be chosen to be effective, if a library chooses the JCL, then its logging is going to pass through your logger and you will be able to control those messages. But no solution if that library chose log4j for its messages.

Another solution, Simple Log Facade for Java (Slf4j) has the same goal, but going even further. It brings two bridges instead of one.
- You are supposed to use Slf4j, that is an interface/facade, and logger can be finally chosen at runtime.
- If your library uses log4j, a bridge called log4j-over-slf4j should be provided, it replaces log4j library, then those messages are driven through Slf4j, and finally redirected to your runtime-chosen logger again.
- An implementation should be finally included, for example, if you want your Slf4j to log into SimpleLog4j, provide slf4j-simplelog4j to drive your messages to that logger, and the runtime library simplelog4j.

Obviously, you didn't understand me.. check this out here.

Finally, by now, Slf4j is better for simplicity and flexibility, it adapts to the main log implementations, even JCL!! you don't have to change your libraries implementation whenever possible. Provide the bridges and all messages goes to your logger automatically.

Now let's dive into the final logger, now you have all your messages driven through Slf4j.
In my company, we had two main options, log4j and logback. It is funny to discover that both were created by the same person, as Slf4j was! This mess is the opus of the same unique person!!

Log4j is a good library, but Logback is better, called for replace the former, and it is said by the author of both. A list of improvements here. Mainly, it is a Slf4j native implementation, no more bridge needed, it is faster, more robust, it smells better... I knew this library, and this mess, only few weeks ago, and I have to admit my error on ignoring the "logger" mess, ignoring the libraries log and not managing it well.

My recommendation, code for Slf4j, use Logback in runtime, and use as much bridges as you need for your libraries to Slf4j. Log4j is deprecated by Logback.

See you soon...

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.