Logahawk Logo
Logahawk
Logging should be easy - Easy to code and easy to read
Integration

Integration means getting Logahawk's output to log files (or devices). This means either having Logahawk write to log files itself or sending Logahawk's output to another logging framework.

To use an existing logger framework to handle the final stages of logging, you will need to use (or build) a special adapter class to move Logahawk's formatted messages to that underlying logger framework. Thankfully doing that is very easy.

Determine Logging Framework

The first step to do is to determine (or decide) which underlying logging framework you use. The integration class we will build (later on in this document) will be the glue that connects Logahawk to the underlying framework.

Which framework you choose depends personal preference or the type of application you are writing. Or you may already have an existing logging framework that you wish to keep using.

Popular logging frameworks
Create Adapter

One you have choosen the underlying logging framework, you need to create the Adapter class. There are two kinds adapters you can build; the first is a Listener Adapter and is required. The second is an Appender Adapter and is optional. They are both described below.

Listener Adapter

The first Adapter is a Listener that sends the results of Logahawk to the underlying logging framework you choose earlier. It is required and (thankfully) is the simplest to implement.

You need to implement the Listener interface and send the parameters of the log method to underlying logging framework. Below is an example:

	public class MyListener implements Listener
	{
	  public void log( LogMeta meta, String text )
	  {
	     // write to underlying loggering framework
	  }
	}
      

See listeners, the Supplemental section for links to pre-built implementations for various logging frameworks.

Appender Adapter

The second Adapter allows Logahawk to process log messages from third-party libraries. Its useful when some third-party library's logging needs formatting or additional information added by Logahawk. This generally not necessary and is completely optional.

The process for doing this is specific to each logging framework. Logahawk provides pre-built implementations for log4j. Implementations for other logging frameworks should be possible using the same techniques explained below. Its called an "Appender Adapter" because the interface we need to implement is called an Appender in log4j. (Other logging frameworks will have similar, but possibly differently named interfaces.)

First you must create a log4j Appender implementation that will append to either a Logger or Listener (depending on how much control you need). For our example we will use a Listener because it is (slightly) simpler.

	public class AppenderAdapter extends AppenderSkeleton
	{
	  public void close() { closed = true; } // abstract in parent
	  public boolean requiresLayout() { return false; } // abstract in parent

	  private Listener listener = new NullListener();

	  public void setListener( Listener l ) { listener = l; } // getter not shown

	  protected void append( LoggingEvent loggingEvent )
	  {
	    Severity severity = ... // get Severity from loggingEvent's Level
	    String msg = loggingEvent.getRenderedMessage();

	    // ... do whatever processing is needed

	    listener.get().log( severity, msg );
	  }
	}
      

Our Appender implementation must also provide some way for your code to find the Appender once it is created by the logging framework. The static "appenders" property allows us to do this. When the Appender is given its name (which is set immediately after it is created), we add the Appender to a static map.

	public class AppenderAdapter extends AppenderSkeleton
	{
	  // ... implementation continued from above ...

	  public static final Map<String, AppenderAdapter> appenders = new ...

	  public void setName( String name )
	  {
	    super.setName( name );
	    appenders.put( name, this );
	  }
	}
      

(The static map is a cheap and easy way to expose the Appender. It is provided as an example solution. Your implementation is free to use this or any other technique.)

The next step is to configure your Appender in the log4j.xml configuration file. The "name" attribute of the Appender must match the appender name you specified above (in our case "myAppender")

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j">
  <appender name="myAppender" class="logahawk.log4j.ListenerLog4jAppender" />
  <root>"
    <priority value ="debug" />
    <appender-ref ref="logahawkListener" />
  </root>
</log4j:configuration>      
      

The final step is to load the configuration file and setup the MyAppender created by that loading.

	// create your listener (might be modify the message, might be a filter, ...)
	Listener listener = ...

	// configure log4j, which will create an instance of MyAppender
	DOMConfigurator.configure( "log4j.xml" );

	// retrieve the instance of MyAppender
	MyAppender myAppender = AppenderAdatper.appenders.get( "myAppender" );

	// update the Appender to use your listener
	myAppender.setListener( listener );
      

Now you have control over the logging performed by any third-party library that uses your appender. The process for doing this with a Logger is very much the same, the differences are in the implementation of the append() method in MyAppender.

There are pre-built Appender implementations contained in Logahawk's supplemental package.

There are also working configuration and usage examples in the unit tests.