Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

DailyRollingFileAppender with maxBackupIndex

4.00/5 (4 votes)
15 May 2010Apache3 min read 132.2K   1.5K  
This is a modified version of Log4J DailyRollingFileAppender with maxBackupIndex to delete old log files if exceeds given maxBackupIndex size.

Introduction

If you are trying to use the Apache Log4J DailyRollingFileAppender for a daily log file, you may need to want to specify the maximum number of files which should be kept. Just like rolling RollingFileAppender supports maxBackupIndex. But the current version of Log4j (Apache log4j 1.2.16) does not provide any mechanism to delete old log files if you are using DailyRollingFileAppender. I tried to make small modifications in the original version of DailyRollingFileAppender to add maxBackupIndex property. So, it would be possible to clean up old log files which may not be required for future usage.

Changes Made in the DailyRollingFileAppender

Step 1: Renamed the Java file DailyRollingFileAppender to CustomDailyRollingFileAppender and put it into a different package, which is custom.log4j.appender.

Step 2: Added a new field variable protected int maxBackupIndex = 1; and set the default value as one. This is required because based on the value of maxBackupIndex our appender determines the number of files needed to keep backup.

Step 3: Created a mutator (setter method) and an accessor (getter method) for the filed maxBackupIndex.

C#
public int getMaxBackupIndex() {
	return maxBackupIndex;
}

public void setMaxBackupIndex(int maxBackups) {
	this.maxBackupIndex = maxBackups;
}

Step 4: Created a class within the same Java source file ModifiedTimeSortableFile. This class extends java.io.File class and implements java.lang.Comparable<T> to sort files list based upon their modified date. The main purpose behind creating this class is to override public int compareTo(File anotherPathName) method which is used later to call Collections.sort() method to sort the files in the oldest modified date order.

C#
class ModifiedTimeSortableFile extends File implements Serializable, Comparable<File>
{
	private static final long serialVersionUID = 1373373728209668895L;
	
	public ModifiedTimeSortableFile(String parent, String child) {
		super(parent, child);
	}

	public ModifiedTimeSortableFile(URI uri) {
		super(uri);
	}

	public ModifiedTimeSortableFile(File parent, String child) {
		super(parent, child);
	}	
	
	public ModifiedTimeSortableFile(String string) {
		super(string);
	}
	
	public int compareTo(File anotherPathName) {
		long thisVal = this.lastModified();
		long anotherVal = anotherPathName.lastModified();
		return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
	}
}

Step 5: Once the class ModifiedTimeSortableFile has been created, now we can move on to add new method private List<ModifiedTimeSortableFile> getAllFiles() to our modified class CustomDailyRollingFileAppender. The purpose of this method is to fetch a list of log files based on the pattern given in the log4j configuration file and return as a list.

C#
private List<ModifiedTimeSortableFile> getAllFiles()
   {
      List<ModifiedTimeSortableFile> files = new ArrayList<ModifiedTimeSortableFile>(); 
      FilenameFilter filter = new FilenameFilter() {
         public boolean accept(File dir, String name) {
            String directoryName = dir.getPath();
            LogLog.debug("directory name: " + directoryName);
            File file = new File(fileName);
            String perentDirectory = file.getParent();
            if(perentDirectory !=null)
            {
               String localFile = fileName.substring(directoryName.length());
               return name.startsWith(localFile);
            }
            return name.startsWith(fileName);
         }
      };
      File file = new File(fileName);
      String perentDirectory = file.getParent();
      if(file.exists())
      {
         if(file.getParent() == null){
            String absolutePath = file.getAbsolutePath();
            perentDirectory = absolutePath.substring(0,
				absolutePath.lastIndexOf(fileName));            
         }
      }
      File dir = new File(perentDirectory); 
      String[] names = dir.list(filter);
      
      for (int i = 0 ; i < names.length ; i++) {
         files.add(new ModifiedTimeSortableFile
		(dir + System.getProperty("file.separator") + names[i]));
         }
      return files;
   } 

Step 6: The void rollOver() throws IOException is responsible to rollover the current file to a new file. We just need to put additional logic before anything it does to rollover. Our logic simply gets the list of files, sorts those according to modified date, checks the maxBackupIndex and deletes additional old log files.

C#
List<ModifiedTimeSortableFile> files = getAllFiles();
Collections.sort(files)
if(files.size() >= maxBackupIndex)
{
   int index = 0;
   int diff = files.size() - (maxBackupIndex - 1);
   for(ModifiedTimeSortableFile file : files)
   {
     if(index >= diff)
       break;
            
     file.delete();
    index++;
   }
} 

How To Use

We have created our CustomDailyRollingFileAppender. Now, it's time to test our appender. There are only two steps involved to create a sample application as described below:

Step 1: Create a log4J configuration file to set the datePattern, maxBackupSize, etc.

XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
   <appender name="FILE" class="custom.log4j.appender.CustomDailyRollingFileAppender">
      <param name="file" value="test-agent.log" />
      <param name="datePattern" value="'_'dd-yyyy-MM'.log'" />
      <param name="maxBackupIndex" value="4" />
      <param name="append" value="true" />
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%d [%t] %p - %m%n" />
      </layout>
   </appender>
   <root>
      <priority value="info" />
      <appender-ref ref="FILE" />
   </root>
</log4j:configuration>

Here you can see the class name mentioned is the one which we have just created (i.e. CustomDailyRollingFileAppender). And we set the maxBackupIndex as 4. Hence, there should be only four log files that shall be kept on your system.

Step 2: Create a class with public static void main(String[] args) method and add latest log4J jar file at your classpath.

C#
public class Main {

  private static org.apache.log4j.Logger log = Logger.getLogger(Main.class);

  public static void main(String[] args) {
     String configFile;

     final File file = new File("log4j.xml");

      if (file.exists()) {
          final URL url = Main.class.getClassLoader().getResource("log4j.xml");
          configFile = url.getPath();
          PropertyConfigurator.configure("log4j.xml");
      }

     log.trace("Trace");
     log.debug("Debug");
     log.info("Info");
     log.warn("Warn");
     log.error("Error");
     log.fatal("Fatal");
  }

Now we are ready to test whether our appender is working fine or not. Just change your system date to observe files are backed up as per maxBackupIndex or not.

Conclusion

This is a modified version of DailyRollingFileAppender and all the comments and license in the source file have been kept untouched. I added my comment though. It is only tested on Windows Operating System. Please make your necessary adjustments in the code if required. The purpose of this article is to demonstrate how to create your own custom appenders.

History

  • 16th May, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0