Brian Slesinsky's Weblog

Saturday, 22 Nov 2003

Event-Based Logging

Here's a trick I used to avoid depending on a particular logging library in Java: instead of calling the logger directly, I wrote an adapter class. For example, suppose you're writing a library that's implemented in terms of commands, and you want to log a message whenever a command is run. The logger might look like this:

public abstract class MyEventLogger {
  public void startedCommand(String commandName) {
    debug("started command: "+commandName);
  public void finishedCommand(String commandName) {
    debug("finished command: "+commandName;
  public void finishedCommand(String commandName, Exception ex) {
    error("error running command: "+commandName, ex);
  public abstract void error(String msg, Exception ex);
  public abstract void debug(String msg);

This solved my original problem by moving the dependency to a subclass of MyEventLogger, and the subclass was actually defined outside the library, resulting in one less jar needed to compile.

The new class opens up some other nice possibilities. It's a convenient place to put methods for application-specific events like startCommand(). These are often more useful than generic events like debug() and error(). For example, if the client is a Swing application, it's fairly easy to rig things up so the name of the currently-running command is displayed on a status line. Or a unit test might use a special-case logger to verify that a particular event occured. Application-specific methods can also be a convenient place to put breakpoints when in a debugger.

I'm not sure yet how it scales. If I added new features to the library and thought of more new things to monitor, the number of event methods might get too big for one class. Also, there's the potential for reduced performance whenever adding a layer like this. But I do think it's a better idea than using something like Apache's commons-logging component, which replaces one outside dependency with another, rather than removing one.