Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
I wrote a customized appender using log4j which extends FileAppender since the existing appenders were not fulfiling my requirements.
This appender is a mixture of RollingFileAppender as well as DailyRollingFileAppender.
My requirement was to close the log file(known as Activity Log) on the basis of maximum no. of configured lines(not size) or maximum configured time(in sec,DailyRollingFileAppender supports a min granularity of only minutes)
Also the name of the log file had to be in a particular format-
AL_IP ADDRESS_DATE_TIME,where date_time is the time of the first hit.
I was able to control the creation of log files by overriding activateOptions().
Hence my logfile is created only on the first hit or when first written into and thereafter closed on the basis of maxRecords or maxSec.A new log file will be created if there is no existing open log file.
package com.comverse.mig.migprov.bl.activitylog;
import java.io.File;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.FileAppender;
import org.apache.log4j.spi.LoggingEvent;
public class OperationsAppender extends FileAppender {
private boolean initialized = false;
private String baseFileName = null;
private int numLines = 0;
private long startFile = 0;
private int maxRecords = 0;
private int maxSec = 0;
private String dateFormat;
private String file;
private static final Log log = LogFactory.getLog(OperationsAppender.class);
private static final Timer timer = new Timer(true);
/**
*
* write to ActivityLog
*
* @param event logging event invoked.
*
*/
@Override
protected void subAppend(LoggingEvent event) {
if(!initialized || checkStatus())
{
createNewFile();
}
synchronized (this) {
super.subAppend(event);
numLines++;
}
}
/**
*
* create a new ActivityLog File
*
*/
public void createNewFile()
{
try {
baseFileName = file + "_"+ InetAddress.getLocalHost().getHostAddress()+ "_"+ new SimpleDateFormat(dateFormat).format(Calendar.getInstance().getTime());
super.setFile(getTmpFileName());
super.activateOptions();
startFile = System.currentTimeMillis();
log.debug("Created Activity Log: " + getTmpFileName());
startTimer();
initialized = true;
} catch (Exception e) {
log.error("Error in configuration of log4j params,unable to create ActivityLog file");
}
}
/**
*
* Activity Log status check.
* It will be closed as per configured time or configured max. no. of records
*
* @return boolean true indicates current activity log file has been closed
*/
private boolean checkStatus()
{
boolean flag = false;
if ((maxSec==0 && numLines==maxRecords) || (maxRecords==0 && System.currentTimeMillis()>=maxSec*1000+startFile)||
(maxSec!=0 && maxRecords!=0 && (numLines == maxRecords || System.currentTimeMillis()>=maxSec*1000+startFile)))
{
rollOver();
flag=true;
}
return flag;
}
/**
*
* invokes File Appender's activateOptions() which controls the creation of log files.
*
*/
@Override
public void activateOptions()
{
if (maxSec == 0 && maxRecords == 0) {
log.info("ActivityLog: Time duration and Max records both are zeroed, not creating AL files");
} else {
super.setFile("dummy");
super.activateOptions();
}
}
/**
*
* Close and rename the current ActivityLog file and reset counter and timestamp.
*
*/
private void rollOver() {
log.debug("Closing and Renaming Activity Log File: " + getTmpFileName());
closeFile();
(new File(getTmpFileName())).renameTo(new File(getReportFileName()));
numLines = 0;
startFile=0;
initialized = false;
}
private String getReportFileName() {
return baseFileName+".report";
}
private String getTmpFileName() {
return baseFileName+".tmp";
}
public void setMaxRecords(int maxRecords) {
this.maxRecords = maxRecords;
}
public void setMaxSec(int maxSec) {
this.maxSec = maxSec;
}
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
@Override
public void setFile(String file) {
this.file=file;
}
/**
*
* start the timer to monitor the time duration
*
*/
private void startTimer() {
if (maxSec != 0) {
TimerTask timertask = new MonitorTime();
timer.schedule(timertask, maxSec * 1000);
}
}
/**
*
* Private inner class,will monitor time duration and close the
* Activity Log file if the configured time has elapsed
*
*/
private class MonitorTime extends TimerTask {
public void run() {
// time over
if (System.currentTimeMillis()>= maxSec * 1000 + startFile) {
rollOver();
}
}
}
}log4j.xml configuration:
<appender name="ACTIVITY_LOG_FILE" class="com.comverse.mig.migprov.bl.activitylog.OperationsAppender">
<param name="File" value="${log.dir}/cds/log/stat/AL"/>
<param name="Append" value="true"/>
<param name="maxRecords" value="10"/>
<param name="maxSec" value="600"/>
<param name="dateFormat" value="MM_dd_yyyy_HH_mm_ss"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{MM_dd_yyyy HH_mm_ss}%m%n"/>
</layout>
</appender>
<category name="activity" additivity="false">
<priority value="TRACE" />
<appender-ref ref="ACTIVITY_LOG_FILE" />
</category>