Log4j rolling file appenders in Windows

I’ve been using the DailyRollingFileAppender in log4j for years without any problems. It came as a surprise when my trusted appender failed to rollover in a new web service. A bit of googling made me realised it is a widespread problem. The only reason I haven’t encountered this problem before was because I have exclusively developed for Linux. And now my new work is a Windows shop.

Essentially, the log4j DailyRollingFileAppender renames the day’s log file at the end of the day. This runs into file contention problems in Windows, and the renaming regularly fails. A very simple solution to this is to create your log file with the date prefix already in place, and thus avoid renaming it entirely. This is the solution taken by Geoff Mottram on the DatedFileAppender he released to the public domain back in 2005. (This is the appender I found configured for some of the web services deployed on the company’s mule server).

The log4j crew also recognised this problem, and according to its bug tracker, the problem has been fixed for 1.3. But since the 1.3 series have been abandoned, the patch is now available as part of Log4j Extras.

Using the new log4j rolling file appender

To include log4j extras using maven

	<dependency>
		<groupId>log4j</groupId>
		<artifactId>apache-log4j-extras</artifactId>
		<version>1.2.17</version>
	</dependency>    

A sample log4j.xml

	<appender name="FILE" class="org.apache.log4j.rolling.RollingFileAppender">
		<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
	      		<param name="FileNamePattern" value="D:/logs/app-%d.log.gz"/>
	   	</rollingPolicy>
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n" />
		</layout>
	</appender>

How often the log file rolls is specified by the date format in the FileNamePattern. It uses the same formatter as Java’s SimpleDateFormat. By default, (%d in app-%d.log), a new log file is created daily. To create a new log file every minute, use something like app-%d{yyyy-MM-dd-HH-mm}.log. The gz suffix in app-%d.log.gz means old log files will be gzipped automatically.