www.rodneybeede.com "I would love to change the world, but they won't give me the source code" - unknown

Log4j XML - Last Modified 2015-10-01 20:48 UTC - Created 2010-11-24 15:43 UTC

Just notes on how I like to use log4j.


Place in classpath to have it automatically loaded. src/main/resources/log4j.xml is a good choice.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">

<!-- http://wiki.apache.org/logging-log4j/Log4jXmlFormat -->

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	<!-- The appender name "rolling" is referenced in Java code to display the absolute path of where logging is occurring -->
	<appender name="rolling" class="org.apache.log4j.rolling.RollingFileAppender">

		<!-- The active file to log to -->
		<param name="file" value="${catalina.home}/logs/WebApplication.log" />
		<param name="append" value="true" />
		<param name="encoding" value="UTF-8" />

		<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
			<!-- The file to roll to, this is a fairly intelligent parameter, if the 
				file ends in .gz, it gzips it, based on the date stamp it rolls at that time, 
				default is yyyy-MM-dd, (rolls at midnight) See: http://logging.apache.org/log4j/companions/extras/apidocs/org/apache/log4j/rolling/TimeBasedRollingPolicy.html -->
			<param name="FileNamePattern" value="${catalina.home}/logs/WebApplication.%d.log.gz" />

		<layout class="org.apache.log4j.PatternLayout">
			<!-- %d = date, %p = level, %t = thread, %c = category (usually class), 
				%m = message, %n = newline -->
			<param name="ConversionPattern"
				value="%d{yyyy-MM-dd HH:mm:ss,SSS Z}\t%-5p\tThread=%t\t%c\t%m%n" />

	<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
		<param name="BufferSize" value="500" />
		<appender-ref ref="rolling" />
		<!-- Don't log to console as that fills up the web container log (ex: catalina.log) which may not roll -->

		<level value="all" />
		<appender-ref ref="ASYNC" />


Maven pom.xml

You will want to add the version yourself based on the latest available.

Java use

private static final Logger log = Logger.getLogger(SOMECLASS.class);

The file cannot be validated as the XML definition "/some/path/log4j.dtd (The system cannot find the file specified)" that is specified as describing the syntax of the file cannot be located

This just means that the location for the DTD validation can't be found locally. One option is to use this DOCTYPE instead:

<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">

This however may cause your IDE to go out on the Internet to retrieve the DTD which could be slow if Apache's website is busy. You'll just get a hang with no useful error message when you rebuild.

Java LoggingUtil

package com.rodneybeede.cloudinabottle.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;

import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.AppenderAttachable;

public class LoggingUtils {
	 * @param logger Usually {@link Logger#getRootLogger()}
	 * @return File handle objects to all appenders that subclass {@link FileAppender} and have file settings != null.  Recursive.
	public static Collection<File> getAppenderFiles(final org.apache.log4j.Logger logger) {
		final Enumeration<?> childrenEnumeration = logger.getAllAppenders();
		return getAppenderFiles(childrenEnumeration);
	public static Collection<File> getAppenderFiles(final Enumeration<?> appenderEnumeration) {
		final Collection<File> files = new ArrayList<File>();
		while(appenderEnumeration.hasMoreElements()) {
			final Appender currAppender = (Appender) appenderEnumeration.nextElement();
			if(currAppender instanceof FileAppender) {
				final FileAppender fileAppender = (FileAppender) currAppender;
				if(null != fileAppender.getFile()) {
					files.add(new File(fileAppender.getFile()).getAbsoluteFile());
			if(currAppender instanceof AppenderAttachable) {
				// Recursive
				final Enumeration<?> childrenEnumeration = (((AppenderAttachable) currAppender).getAllAppenders());

		return files;