Log4j again – Asyn Log Appender to datasource

Hi, had some interesting use with the log4j. I think it should help some people, with similar situations with log4j. We need to do log4j with these needs:

(1) asynchronously (2) append to a database (3) use a datasource in a JNDI tree.

(1) is obviously advantageous, nobody wants to cost delay to processes that being logged.

(2) and (3) are common requirements – use dynamic connection pooling without having clear text password in log4j.xml or property files.

Here are the steps to do:

(a) Setup config in log4j.xml

<appender name=”DatabaseAppender”
class=”DatabaseAppender”>
<param name=”Threshold” value=”DEBUG” />
<layout>
<param name=”ConversionPattern” value=”%m” />
</layout>
</appender>

<appender name=”AsynAppenderToDatabaseAppender”
class=”org.apache.log4j.AsyncAppender”>
<appender-ref ref=”DatabaseAppender” />
</appender>

<root>
<appender-ref ref=”AsynAppenderToDatabaseAppender” />
</root>

DatabaseAppender is the custom appender which will eventually do the underhood logging.  The AsynAppenderToDatabaseAppender is simply a log4j AsyncAppender that will pipe the logger to the DatabaseAppender.  The root logger is my lazy mapping of all to the DatabaseAppender.  One can add many other loggers to it as desired.

(b) Implement the Custom DatabaseAppender.java

public class DatabaseAppender extends AppenderSkeleton {

public boolean requiresLayout(){
return true;
}

/**
* actual place to save to DB with LOG object for hibernate
*/
public synchronized void append( LoggingEvent event ) {

LogDatabaseDelegate del = new LogDatabaseDelegate();
LogTable log = new LogTable();
log.setLOGLEVEL_INT(event.getLevel().toInt());
log.setLOGLEVEL(event.getLevel().toString());
log.setLOGTIME(new Date(event.getTimeStamp()));
LocationInfo li = event.getLocationInformation();
log.setLOGGER(event.getLoggerName() + ” [” + li.getFileName() + “:” + li.getMethodName() + “:” + li.getLineNumber() + “]”);
log.setAPPID(SitePropertyConstants.getAPP_ID());
String msg = this.layout.format(event);
if (msg.length() > SitePropertyConstants.getMAX_CHAR_IN_LOG_MSG())
msg = msg.substring(0, SitePropertyConstants.getMAX_CHAR_IN_LOG_MSG());
log.setLOGMESSAGE(msg);
del.saveLog(log);

}

public synchronized void close(){

}
}

Here is pure java stuff with Hibernate.  The LogDatabaseDelegate will save LogTable object with information such as Log level, log time, logger name (class), log message, etc, etc. In the hibernate end, I simply mount the datasource to a JNDI tree using:

<property name=”connection.datasource”>myDataSource</property>

Definitely, hibernate is not relevant here, you can use any DAO layer to persist the log4j information to Database.

That’s all – Happy Logging4J to Database, asynchronously!

-T

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s