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.
 *
 * @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)
     * @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);
            }
        }
    }
}

This message and the information contained herein is proprietary and 
confidential and subject to the Amdocs policy statement,
you may review at http://www.amdocs.com/email_disclaimer.asp

Reply via email to