I've been fighting with Java logging alot today. I've found
out some interesting, if not disturbing things. I'm also very
disappointed. I'm currently working on a project that must comply
with certain customer standards. The customer has standardized on
Java 1.3 for their VM. They have also standardized on the Java
logging API for logging, but since they are using 1.3, they have
decided to implement the logging API using Lumberjack. This gives them the logging API while still using Java 1.3. I thought this was a bit unusual, so I thought I would use the Jakarta Commons Logging
API to abstract the logging interface. This would allow either
the Java logging API or log4j to be used as the logging implementation
without changing code. A very good thing. This is where the
fun began. It turns out that although the Commons Logging API
will front either JDK 1.4 logging API or log4j, it will not front
Lumberjack. Why? Well, it's simple. Commons Logging
makes a call to getStackTrace on the Exception class if you are using
JDK 1.4 style logging. This method is not available prior to JDK
1.4! Since Lumberjack can only be used with JDK 1.2 and 1.3,
Commons Logging cannot front Lumberjack! ACK! So, I
punted. I decided I would just use the Java logging API without
an abstraction on top of it. Fine. I created a base class
for several of my classes that contained methods for handling
exceptions. These methods made the appropriate call to log the
exception and then threw an application specific exception. This
provides an easy and centralized method of logging and wrapping
exceptions. Enter my disappointment. Upon testing I found
that the Java logging API was reporting the class logging the messages
as my abstract base class! I thought this might be something
peculiar with Lumberjack, so I switched to JDK 1.4 and re-ran my
tests. Nope. It still does it. I figured there had to
be a way out of this nightmare. I went to the API Javadoc.
I found that there is a logp method that takes the class name and the
method name of the class logging the message. Perfect! I
could just pass in the class name and method name, and I could probably
get those dynamically... WRONG! As it turns out it's easy
enough to get the class name - we've all done it. Do something
like this.getClass().getName(). Simple. However, in JDK 1.3
there doesn't appear to be a way to dynamically (and generically)
derrive the current method name. Surely not! I went to
Google. I found this page
which shows a way to get the current method name. But wait!
What's that call? Is that a call to getStackTrace on
Exception? Oh nuts. SO, here's where I am. In the
interest of time (on this project there is not alot) I decided to bite
the bullet and take the inaccuracy of having the log reflect the
abstract base class when logging. It was a trade off between log
accuracy and ease of code maintenance. Maintenance won. I'm
going to consider putting the class name as part of the logging message
so that the reader will get closer to the problem faster. I'm beat.
5:56:28 PM
|