log4j: Selecting appender based on logging level by using LevelRangeFilter

Ever wanted to filter out warning messages to stderr and info messages to stdout using log4j configuration settings without writing a single piece of code. Read more to find out how.

Log4j has various logging levels such as TRACE, DEBUG, INFO, WARN, ERROR and FATAL. Using standard configuration settings of log4j every message gets printed out to only one type of appender such as ConsoleAppender or FileAppender. Recently, I had a thought about how to go about if I wanted to filter out messages based on the logging level of the message. For instance, I may want to redirect the logs of TRACE, DEBUG, INFO to stdout and of WARN, ERROR and FATAL to stderr. For this log4j comes with a variety of filters. One of which is LevelRangeFilter which I am going to use.

LevelRangeFilter

This is a very simple filter based on level matching, which can be used to reject messages with priorities outside a certain range.
The filter admits three options LevelMin, LevelMax and AcceptOnMatch.

Working

If the level of the logging event is not between Min and Max (inclusive), then Filter.DENY is returned. This means that the logging event will not be logged for that particular appender. If the Logging event level is within the specified range, then if AcceptOnMatch is true, Filter.ACCEPT is returned, and if AcceptOnMatch is false, Filter.NEUTRAL is returned.

Enough talk, let’s get down to business.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
	<appender name="stdout">
		<param name="Target" value="System.out" />
		<layout>
			<param name="ConversionPattern" value="%d{HH:mm:ss} %p %c{2}: %m%n" />
		</layout>
		<filter>
			<param name="levelMax" value="info" />
		</filter>
	</appender>

	<appender name="stderr">
		<param name="Target" value="System.err" />
		<layout>
			<param name="ConversionPattern" value="%d{HH:mm:ss} %p %c{2}: %m%n" />
		</layout>
		<filter>
			<param name="levelMin" value="warn" />
		</filter>
	</appender>

	<logger name="com.wordpress.technoturd.twitter">
		<level value="debug" />
	</logger>

	<root>
		<priority value="info" />
		<appender-ref ref="stdout" />
		<appender-ref ref="stderr" />
	</root>
</log4j:configuration>

Let’s analyze the above code snippet.
There are 2 appenders- one on line 5 and the other on line 15 for stdout and stderr respectively. We also define these 2 appenders for the root tag on lines 31 and 32. Next, for each appender, we define a target-stdout/stderr and a layout for formatting of the output. After that, we define filters for both the appenders.
For stdout target, we set the value of the parameter levelMax to info and for stderr target, we set the value of levelMin to warn. This way all the logging events will be filtered according to their logging levels. For the logging events equal to or less than info will be filtered IN the stdout target and all those equal to or greater than warn will be filtered IN the stderr target.

Benefits

  1. For varying circumstances, we can define appenders other than ConsoleAppenders such as FileAppenders and have the different logging events filter out to different files.
  2. In Eclipse IDE (or others as well), this has a great advantage of making use of selective color coding for different error messages in the console window which can be really easy in order to identify which logging events are warnings or error messages.

    Eclipse Console with colored log4j messages

    Eclipse Console with colored log4j messages

6 thoughts on “log4j: Selecting appender based on logging level by using LevelRangeFilter

Leave a comment