Hi,
I came across an issue with the
RollingFileAppender and I would like to contribute back my solution.
The problem is that we have a
RollingFileAppender to log customer usage. So you have, let’s say a file with
the user activity for each minute.
This logs are exported into other systems
that do monitoring and business intelligence based on that feedback.
The problem is that the rolling is tied to
log events, so if events stop happening (the customers end their working hours)
the log is not rolled until the next morning when the system is used again. So
the external systems don’t receive that log until the next day since the export
script cannot do the rolling by itself.
Therefore I developed and extension of the
appender, that schedules itself to rollover the file at the expected time if it
hasn’t been rolled by events.
I have tested it and I haven’t seen any
impact in performance. Only one thread is used, which is enough for a
reasonable number of appenders of this type.
See below the source code of the new
appender.
Let me know what you think.
Regards, Gonzalo
/*
* Copyright
1999-2005 The Apache Software Foundation.
*
* Licensed under the
Apache License, Version 2.0 (the "License");
* you may not use
this file except in compliance with the License.
* You may obtain a
copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by
applicable law or agreed to in writing, software
* distributed under
the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES
OR CONDITIONS OF ANY KIND, either express or implied.
* See the License
for the specific language governing permissions and
* limitations under
the License.
*/
package
org.apache.log4j;
import
java.util.concurrent.ScheduledThreadPoolExecutor;
import
java.util.concurrent.TimeUnit;
import
org.apache.log4j.helpers.LogLog;
/**
* Extends the
default time based rolling file appender to roll the files in a synchronous
manner.
* That means when
the time is due the file will be rolled, instead of rolling the file when
* a new event is
logged and the timeout is detected.
*
* <at> author Gonzalo
Herreros
*/
public class
SynchronousDailyRollingFileAppender extends DailyRollingFileAppender
{
//One thread
should be enough for a reasonable amount of rolling appenders
//Anyway there
should be no harm if there is a small delay
private static
ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
/* (non-Javadoc)
* <at> see
org.apache.log4j.DailyRollingFileAppender#activateOptions()
*/
public void
activateOptions() {
super.activateOptions();
scheduleNextRollover();
}
/**
* Schedule the
next call so we try to rollover
*/
protected void
scheduleNextRollover() {
long nextTime
= rc.getNextCheckMillis(now);
long lapse =
nextTime - now.getTime();
if (lapse
> 0){
synchronized(scheduler) {
scheduler.schedule(new Runnable() {
public void run() {
try {
//Prevent conflicts with other threads writing the log
synchronized(this){
now.setTime(System.currentTimeMillis());
rollOver();
}
} catch(Throwable t) {
LogLog.error("rollOver() failed.", t);
}
scheduleNextRollover();
}
},
lapse + 1, TimeUnit.MILLISECONDS);
}
}
}
}