An appender is linked to a logger through either calling configuration API or defining a seperate property file. In addition, you can define the layout of an event; e.g. I have been using the XML Layout option for awhile now ( even though I really need to hack out the use of CDATA ) and I wondered how easy it would be to pipe all log4j events to be written into Xindice.

I wanted to be able to change all my existing log property files to use a new Appender called XindiceAppender, which meant that all logs would be placed within an Xindice db collection. I also required to have an xml file written everytime for backup purposes.

The steps to achieve this are as follows;

Create addDocument xindice object to write to Xindice: use addDocument.java included in Xindice documentation and amend it for our purposes.

The write method does all the heavy lifting, with the entry point for the logger to use writeEvent. There are set methods for defining the event, namespace to use for logger xml, and collection path.

We have had to use unchecked exceptions because of log4j architecture, this is simply through desire to illustrate things simply here. As you will see in the Appender description, we subclass from the log4j Appender class, which would have needed modification to handle our exception events properly.

The next file is the XindiceAppender, its just a hacked up version of WriterAppender.java that comes with log4j. WriterAppender wrote event data to a file, as previously stated I want to retain this capability, but also add writing to Xindice. Log4j can use multiple appenders so this is not neccesary in production, though when testing the code I needed to verify that events were actually being fired off.

Once again there is plenty of room for optimisation and improvement, though I thought breaking them up would assist in understanding the process. The additional flags and vars handle the extra requirements of writing to Xindice.

- writeXindice: if set to yes will write event to xindice

- writeFile: if set to yes will also write event to file

The Collection and log4jNamespace vars define respectively the db collection path and namespace to use in the generated event xml. Basically XindiceAppender should work in the same manner as WriterAppender with the added benefit of writing to xindice.

As with any log4j you will need to invoke the logging code with the appropriate configuration. OK you will still need to attatch this from within the code that is logging something...which is pure log4j stuff;

The com.example.xindice.XindiceAppender appender should write to whatever collection you have defined in xindice. In the case above, the logger is looking for a /db/log collection. Appropriate errors will be thrown for malformed xml.

With the addition of a server variable, we can direct output to a variety of remote Xindice repositories. Note that each event gets written as a single document within xindice, and since I have ommited explicitly naming the documents...I settled for xindice's method of automatically naming a file.

I have done little testing though everything seems to work fine, there will perhaps be conflicts with Xindice's own usage of Log4j, in addition it remains to be seen if xindice can handle such high volume, small transaction type data handling.