Promoting Genetics Awareness for a Healthier Society

Home
   KromoNews
   GeneMatics
   About Us

Members Area
   Genetics Articles
   Pathology Central
   Genetics News
   Genetics Events
   Organizations
   My Dashboard
   Genetics Terms
   Genetics Trivia
   Mobile Access
   Resources
   Videos

Feeds

Using Log4j appenders with JDK logging

List of downloads

Amrinder Arora

1. Introduction

Log4j, a logging framework of Apache's Jakarta project provides a simple, yet extremely powerful logging framework. Log4j is currently in use by many commercial clients, as well as many open source projects. Since version 1.2, Log4j also comes with a GUI application (Chainsaw) that is very helpful in filtering the logs when the application is running. JDK 1.4 introduces logging API as a step to standardize logging into Java applications. However, JDK logging API and Log4j API differ to some extent that makes interoperability slightly tricky. In particular, an application using JDK logging cannot directly use Chainsaw to dynamically filter the logs during runtime.

2. Scope of this article

This article is directed towards developers, who want to use existing Log4j appenders (primarily Chainsaw) for application that uses JDK logging. This article is not meant for team/project leads as a comparison between JDK logging and Log4j logging API. Articles doing comparisons of the two frameworks can be found at http://www.ingrid.org/jajakarta/log4j/jakarta-log4j-1.1.3/docs/critique.html and in "Logging in Java with the JDK1.4 Logging API and Apache Log4j", a book by Samudra Gupta. Also, this article does not provide any introduction on logging and its importance, nor does it not advocate any logging infrastructure over another. It merely allows you to use existing Log4j appenders for code that uses JDK logging.

3. Problem Definition: How to use Chainsaw with JDK logging?

To better define the scope of the problem, we will concentrate on Chainsaw as the target Log4j appender. The process for other Log4j appenders is similar, but an introduction to the entire framework (for all appenders) is outside the scope of this article. To better understand the problem, let us evaluate the pertinent operational differences between the two logging frameworks.

3.1 Basic Difference: LoggingEvent vs. LogRecord

Log4j uses concept of LoggingEvent, while JDK internally uses concept of LogRecord. These two classes are very similar, but the appenders (in Log4j) and handlers (in JDK) are thus defined to catch the appropriate classes. Thus, the JDK attempts to pass LogRecord to handlers, while Chainsaw, being a Log4j appender, only accepts instances of LoggingEvent class.

3.2 Levels are different in the two systems

The Log4j and JDK systems use different levels. While Log4j uses 5 levels, JDK uses 7 levels (besides ALL and OFF), and it is not clear if there is an intuitive translation between the levels.

4. Solution: ChainsawHandler

This section contains the crux of this article. We propose ChainsawHandler as a custom handler within JDK logging framework. ChainsawHandler is initialized with other JDK handlers. It receives instances of LogRecord class, converts the LogRecord instances into LoggingEvent instances and passes them to the Log4j log viewer Chainsaw. Essentially, it is an implementation of the common Adapter pattern.

4.1 ChainsawHandler in the logging architecture

The accompanying figure displays the role of ChainsawHandler and where it fits in the overall logging architecture.

4.2 Downloading ChainsawHandler

The JAR containing the ChainsawHandler adapter class file can be downloaded from here. You can also download the source code and compile it yourself, if you so prefer. Fair use is permitted for the source code. Credits may be given by linking back to http://www.kromosoft.com.

List of downloads:

4.3 Installing ChainsawHandler (Modifying logging.properties)

In the JDK logging framework, custom handlers can be declared in the logging.properties file that can be found in the JRE_HOME\lib folder. Modify the "handlers" property as shown in example below:

# "handlers" specifies a comma-separated list of log Handler classes that are installed during VM startup
handlers= java.util.logging.ConsoleHandler, java.util.logging.FileHandler, edu.gwu.logging.ChainsawHandler

Note that the JAR file containing the ChainsawHandler class must be on the system classpath.

4.4 Customizing behavior using ChainsawHandler.initialize

Different configurations may have the Chainsaw GUI running at different machines, on different ports, and may even require different translation schemes between for converting the levels between the JDK and log4j systems. Therefore, ChainsawHandler provides an initialize method to change these settings. Sample code and a sample properties file are outlined in the next two sections.

4.4.1 Sample code

The method initialize can be used as follows from anywhere in the code. Changes will take effect right after the initialize method is called.

// your other code
f.setSize (600,400);

// from now on, ChainsawHandler should use these properties:
ChainsawHander.initialize ("/tmp/chainsawHandler.properties");
// initialization has been done for all classes (entire JVM)

// continue your code
f.setVisible (true);

Please note that since each JVM will initialize its own handlers, if you system involves multiple JVMs, this code will only modify the behavior of one ChainsawHandler. On the same note, since there is only one instance of ChainsawHandler per JVM, a single client call to initialize will affect logging of all clients/classes running on that VM.

4.4.2 Converting between JDK and log4j levels

You can specify your own level translation scheme in a properties file, and then invoke the ChainsawHandler.initialize to configure the ChainsawHandler to translate the levels from JDK to Log4j in a customized manner. The client code can use the different JDK levels, and they will be converted to Log4j level before the logging event is passed to the chainsaw GUI. This step is optional, and the following defaults are used by the ChainsawHandler.

# conversion of levels between JDK and log4j logging systems
# jdk severe -> log4j fatal
level.jdk.1000 = level.log4j.50000
# jdk warning -> log4j warn
level.jdk.900 = level.log4j.30000
# jdk info/config -> log4j info
level.jdk.800 = level.log4j.20000
level.jdk.700 = level.log4j.20000
# jdk fine/finer/finest -> log4j debug
level.jdk.500 = level.log4j.10000
level.jdk.400 = level.log4j.10000
level.jdk.300 = level.log4j.10000

4.5 Exception handling in ChainsawHandler

Configuration errors may prevent ChainsawHandler from correctly passing logging events to Chainsaw. When an error occurs, ChainsawHandler will log the exception to standard error, print the stack trace (for the first exception only) and attempt to renew the socket channel to the Chainsaw. If it consecutively fails for a fixed number of times (as set by MAX_ERRORS), ChainsawHandler will automatically disable itself. The ChainsawHandler does not throw any exception back at the user while publishing a record. It can, however throw an exception in the initialize method, to point out an error condition, such as malformatted URI or an unreadable file.

5. Conclusion

In this article, I propose a chainsaw handler to allow classes that use JDK logging API to be logged into Chainsaw application, which is a part of log4j logging framework.

References

1. Log4j 1.2 API from Jakarta (http://jakarta.apache.org/log4j/docs/api/).
2. JDK 1.4 API from Sun (http://java.sun.com/j2se/1.4.2/docs/api/).