Reputation: 1091
My boss requires that I have a logging solution where
It seems with log4j I can only get one or the other criteria, but not both. With the log4j extras TimeBasedRollingPolicy I'm able to get log files to contain the date/time, which fulfills 1. However, there doesn't seem to be a way to make TimeBasedRollingPolicy delete old log files. According to this post it is not possible to make TimeBasedRollingPolicy delete old log files
With the log4j extras FixedWindowRollingPolicy and SizeBasedTriggeringPolicy I can get log4j to delete all but the last 10 log files so my hard drive doesn't run out of space, fulling 2. However I can't get this solution to put the date/time in the file name. With this configuration
def myAppAppender = new org.apache.log4j.rolling.RollingFileAppender(name: 'myApp', layout: pattern(conversionPattern: "%m%n"))
def rollingPolicy = new org.apache.log4j.rolling.FixedWindowRollingPolicy(fileNamePattern: '/tmp/myapp-%d{MM-dd-yyyy_HH:mm:ss}.log.%i',maxIndex:10,activeFileName: '/tmp/myapp.log')
rollingPolicy.activateOptions()
def triggeringPolicy = new org.apache.log4j.rolling.SizeBasedTriggeringPolicy(maxFileSize:10000000)
triggeringPolicy.activateOptions()
eventAppender.setRollingPolicy(rollingPolicy)
eventAppender.setTriggeringPolicy(triggeringPolicy)
the rolled log files do not contain the date/time. They look like this
myapp-.log.1
myapp-.log.2
...
Is is possible to fulfill both criteria 1) and 2) with log4j? Would I have to subclass TimeBasedRollingPolicy? If so, what methods should I override?
Upvotes: 4
Views: 1993
Reputation: 879
It is somewhat hard to do within Log4j generically but you can always extend the policy against your specific needs as follows.
You first need to copy paste TimeBasedRollingPolicy source code to a new class, for example MyAppDeletingTimeBasedRollingPolicy. Apache license permits this.
The critical part is to implement the delete logic against your needs. Below is my class, which deletes the files starting with "myapp-debug" and ending with "gz" and have not been modified in 3 days. You probably will need other checks, so be careful while blindly copying and pasting the code.
private static class DeleteOldMyAppLogFilesInDirAction extends ActionBase {
private static final long MAX_HISTORY = 3l * 24 * 60 * 60 * 1000; //3 days
private File dir;
public DeleteOldMyAppLogFilesInDirAction (File dir) {
this.dir = dir;
}
@Override
public boolean execute() throws IOException {
for (File f : dir.listFiles()) {
if (f.getName().startsWith("myapp-debug.") && f.getName().endsWith(".gz")
&& f.lastModified() < System.currentTimeMillis() - MAX_HISTORY) {
f.delete();
}
}
return true;
}
}
Then you need to change the return value from this:
return new RolloverDescriptionImpl(nextActiveFile, false, renameAction, compressAction);
To this:
Action deleteOldFilesAction = new DeleteOldMyAppLogFilesInDirAction (new File(currentActiveFile).getParentFile());
List<Action> asynchActions = new ArrayList<Action>();
if (compressAction != null) {
asynchActions.add(compressAction);
}
asynchActions.add(deleteOldFilesAction);
return new RolloverDescriptionImpl(nextActiveFile, false, renameAction, new CompositeAction(asynchActions, false));
There are some hardcoded assumptions in this class, like the file name and old files residing within the same directory as current file, be careful with those assumptions and be happy to hack your way for your own needs.
Upvotes: 1