Migrating from JDK Logging to Log4J

by Dejan Bosanac

Recently, I had to fix some application that does a lot of logging. But not just a simple debug logging where all of your messages are going to one rotating file on the disk and are examined only when something goes terribly wrong.
Requirements for this application were to log all events of a certain type in a separate log (rotating file) and to send en email if an error condition is encountered.
The original application has used the JDK Logging API to cope with these requirements, but something has gone wrong in the implementation and I had to fix it.
First of all, I have to confess that my default choice for Java logging is certainly the log4j API since it is clean and is capable of doing everything that I've needed thus far. As far as commons logging library is in question, I don't see that this extra layer is useful in applications. Libraries are totally different story for that matter.
So, here's what I've found about JDK Logging API that convinced me to stay with log4j whenever I can:

  • There is no way to configure multiple instances of the logger handler class in the properties file - I've needed this to configure multiple FileHandler instances that would write to different log files. But unfortunately, it is impossible to do it through the properties file configuration mechanism.
    When you are using this mechanism, you first define handlers that you will be using, by specifying their classes.

    handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

    Next, you have to configure every class and set its properites.

    java.util.logging.FileHandler.pattern = %h/java%u.log
    java.util.logging.FileHandler.limit = 50000
    java.util.logging.FileHandler.count = 1
    java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

    So as you see, there is no standard way to configure multiple FileHandler instances that will write to different files.
    For that reason you can, for example, find a custom implementation of LogManager in Tomcat called JULI. JULI solves the problem by allowing you to add numbers in front of your class names and treats that "classes" as independent instances. While this is acceptable solution, I didn't want to go that way and introduce solution which is not standard and widely accepted.
    The other solution was to configure logging mechanism programmatically, but that was just out of question.
  • JDK Logging API cannot reliably log messages from the shutdown hook - while this is not as important limitation as the previous one, it could be restricting to some applications (like it was this specific application that I have worked on). It seems that the Logging API has its own shutdown hook and because: (quotation from the API)
    When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently
    you can't be sure that your messages will be logged.

At this moment I have started thinking of how hard would it be to migrate this application to log4j. And it turns out that it was the easiest solution to all of aforementioned problems.
Here are the steps needed to do this:

  • First of all you'll have to change the method that is used to obtain the appropriate log. So, instead

    Logger.getLogger("log_name")

    you'll have to use

    LogManager.getLogger("log_name")

    This may look like a hard manual task, but I'm sure that your IDE will help you in a great deal.
  • Next, you'll have to change names of the appropriate log methods, since fine() is now debug(), etc. With simple search-replace commands, this also won't take more then few minutes.
  • Now, you can configure your log4j logging mechanism by writing the log4j.xml (or log4j.properties) file. I will not elaborate here how to do it, since there are more than enough resources on the Web that explain every detail of log4j.
  • Finally, if you have used java switch to instruct your application where to look for the logging configuration, there is one more step you'll have to do in order to finish this transition.
    The typical switch example that is needed to configure JDK Logging API looks like this

    -Djava.util.logging.config.file="logging.properties"

    So now when we are using log4j.xml, it should be replaced with something like this

    -Dlog4j.configuration=file:log4j.xml


If your application has no special requirements for logging, then it really doesn't matter which of these two solutions you will use. But for any non-trivial logging the JDK Logging API is too limited to be useful. And as we have seen, even in existing applications it is just a matter of minutes to switch these two libraries.

Have you expirienced some of the limitations of the JDK Logging API? How did you overcome them?


4 Comments

oreilly@spychalski.de
2005-12-20 01:39:42
I agree, but...
why do you say you have to switch from Logger.getLogger("log_name") to LogManager.getLogger("log_name")? There's a Logger.getLogger in Log4j, too. Is anything wrong with it?
dejanb
2005-12-20 06:56:25
I agree, but...
You are right, it's just that I have used to obtain loggers through the LogManager so I did without much thinking.
Your solution makes this transition even easier since only the import statements should be modified.


Thanks.

boris_unckel
2005-12-23 05:35:52
No need to migrate for stated reasons
Hello Dejan,


your are correct of your analysis with the plain, default java.util.logging.


For all described problems are solutions available:


  • More than one handler

  • RollingFileHandler

  • PatternFormatter

  • Native JCL support

  • Native SLF4J support

  • Optimized for J2EE Containers (due to TCCL support)

  • - ...


But I strongly disagree to migrate to log4j, if there is not another reason.


Look at the Extensions for the Java Util Logging Implementation:
http://www.x4juli.org


Regards
Boris

stuartp
2006-03-30 15:37:17
Hi Everyone,


No one's probably reading this thread anymore, but I just found it ... Boris, why discourage moving to log4j when x4juli also requires its own jar file and configuration syntax? log4j is proven and in wide use, and all you need is ... a jar file and configuration syntax (two to choose from).


I've used log4j for many years, and disagree strongly with how JULI was implemented (FINE/FINER/FINEST?). This blog entry reassured me of log4j's value, as multiple appender support has often proven necessary in my use. Is there any reason to use JULI other than "it's in the API"?


Log4j on the other hand bases most of its assumptions and practices on solid research of logging practices. To this day I don't know why java nixed using log4j, or at least copying it more closely, I know they were considering it.