Click here to Skip to main content
15,867,835 members
Articles / Programming Languages / Java

DailyRollingFileAppender with maxBackupIndex

Rate me:
Please Sign up or sign in to vote.
4.00/5 (4 votes)
15 May 2010Apache3 min read 129.9K   1.5K   7   15
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


Written By
Software Developer (Senior) Société Générale
India India
Summary:

1. Extensive working experience in web and windows application development, database programming using Java and .Net technologies.

2. Good knowledge in SDLC and Processes like project planning, requirement gathering, development, test planning, release management and production support.

3. Good knowledge and working experience in following methodologies:
a. Agile Development Approach
b. Test Driven Development
c. Behavior Driven Development
d. Continuous Integration & Delivery Model.

4. Excellent communication & analytical skills, good team player, great mentoring capability.

5. Interaction with customer and team spread over different geographical area.

Technologies / Languages: J2SE 5/6, J2EE, .Net 2.0/3.5, C#, ASP.NET, AJAX, XHTML, CSS, JavaScript, jQuery, PL/SQL, Web Services (SOAP based), Winforms, Hibernate, Spring, GWT, XML, XSD, XPath, SAX, JAXB, JUnit, JBehave, Mockito, Selenium, StringTemplate, Log4J, Apache Commons API

Database: Oracle, SQL Server, MySQL, Sybase

Application Server: Tomcat, Sun Application Server, JBoss, GlassFish, Jetty, IIS

Development Environments: Eclipse, NetBeans, Visual Studio.

Designing Tools: Enterprise Architect, Microsoft Visio

Version Control: SVN, Perforce

Build Management: Hudson & JCruisemonitor, TeamCity

Bug Tracking Tools: HP Quality Center, Bugzilla, JIRA

Specialties:
1. Agile Test and Behavior Driven Development
2. Continuous Delivery Approach
2. Spring IOC and MVC
3. Web Services

Comments and Discussions

 
QuestionDailyRollingFileAppender with maxBackupIndex Pin
Member 1275955726-Sep-16 22:06
Member 1275955726-Sep-16 22:06 
Questionclass not found exception when deployed in jboss eap 5.1.0 Pin
Member 1100678612-Aug-14 2:23
Member 1100678612-Aug-14 2:23 
QuestionError using the class Pin
Sébastien Bervoets24-Jan-13 3:57
Sébastien Bervoets24-Jan-13 3:57 
AnswerRe: Error using the class Pin
Member 1100678611-Aug-14 20:51
Member 1100678611-Aug-14 20:51 
Questionsynchronization issues Pin
borta_galen6-Jun-12 23:24
borta_galen6-Jun-12 23:24 
QuestionI am getting ClassCastException error Pin
Member 857322616-Jan-12 21:44
Member 857322616-Jan-12 21:44 
Questionbug? Pin
rat197324-Aug-11 18:28
rat197324-Aug-11 18:28 
AnswerRe: bug? Pin
João Bruno Abou Hatem de Liz22-Apr-13 10:02
João Bruno Abou Hatem de Liz22-Apr-13 10:02 
AnswerRe: bug? Pin
Jabujavi2-Jul-15 23:59
Jabujavi2-Jul-15 23:59 
BugThanks, and a suggestion/bug?. Pin
fabrizio lana12-Jul-11 22:14
fabrizio lana12-Jul-11 22:14 
Hi, thanks for your work. I used it in my application. However it doesn't work for me because no file was cancelled.
The problem for me was that this instruction

String localFile = fileName.substring(directoryName.length());

returns the name with a "/" before the name, so the successive test fail always and no file was cancelled. I'm using it in win 7.
I modified it to make it works, adding this lines before test:

if (localFile.startsWith("\\") || localFile.startsWith("/"))
localFile = localFile.substring(1);

Here is the final snippet:
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());
if (localFile.startsWith("\\")
|| localFile.startsWith("/"))
localFile = localFile.substring(1);
return name.startsWith(localFile);
}
return name.startsWith(fileName);
}
GeneralRe: Thanks, and a suggestion/bug?. Pin
nalanjia2-Sep-13 20:55
nalanjia2-Sep-13 20:55 
Question.class please Pin
al.floress13-Jan-11 4:58
al.floress13-Jan-11 4:58 
AnswerRe: .class please Pin
Bikash Shaw15-Jan-11 7:14
Bikash Shaw15-Jan-11 7:14 
GeneralShorter Version Pin
javaTheHut2-Sep-10 6:04
javaTheHut2-Sep-10 6:04 
GeneralShorter Version Pin
javaTheHut2-Sep-10 6:02
javaTheHut2-Sep-10 6:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.