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
.
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.
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.
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.
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.
="1.0"="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.
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