All, A while back I created a TimeRollingFileAppender (Before the creation of the DailyRollingFileAppender). I was ready to rip mine out and use the Daily version but we needed to roll at specific times, like 5 past the hour etc... in addition, there is a problem when to VMs are writing/rolling the same file which causes all kinds of strange looking log files. So, I have updated, maintained, and continued to use the TimeRollingFileAppender. I thought I should send it out there and see if any of you thought it might be useful. It's key features are as follows: -Allows rolling to occure at any specific time defined to the second. -Allows rolling at any interval defined to the minute. -Allows custom time stamping defined by a java DateFormat -Takes care of multiple VMs writing to and rolling the log file. It probably lacks some features that the DailyRollingFileAppender has, but perhaps if it is worthy we could create a hybrid. Anyway, here it is for your review... |)ave
package org.apache.log4j; import java.util.GregorianCalendar; import java.util.Calendar; import java.util.Date; import java.text.SimpleDateFormat; import java.io.IOException; import java.io.Writer; import java.io.FileWriter; import java.io.File; import java.io.OutputStream; import java.io.OutputStreamWriter; import org.apache.log4j.helpers.OptionConverter; import org.apache.log4j.helpers.QuietWriter; import org.apache.log4j.helpers.CountingQuietWriter; import org.apache.log4j.spi.LoggingEvent; /** * Allows for logging to a file which is automatically rolled over * to a new file after the specified amount of time has elapsed. * The original file is moved and time/date stamped. The rolling * occures after the specified elapsed time from the initial roll * time starting today. * * So, if set to roll at 9:30am and then roll every 30 minutes, * and logging is started before 9:30am, the log file * will roll the first time a logging attempt is made and the time * is later than 9:30am today. It will then roll after the each * logging attempt made after 10:00am, 10:30am... * * If set to roll at a time earlier than the current time, the * current file is rolled and stamped with the current time when * the first logging attempt is made. Then the time to roll * is incremented by the roll interval until the next time to * roll is greater than the current time. For example if set * to roll the logs at 8:00am and every 30 minutes, and logging * started at 9:17, the current log is rolled and stamped using * a stamp based on 9:17, then the roll time set to 9:30am * (8:00 + 30 + 30 + 30 = 9:30 which is > 9:17). The next roll * will be at 9:30am and then 10:00 and so on. * Or if started at 9:17am and set to roll at 8:05 and then * every 7 minutes it would roll the current log and the next * roll would be at 9:22am. * * By default files will be rolled after 11:59:59pm on the * current day, and then every 24 hours after that. The file * will be moved from "file" to "file.yyyy.MM.dd". * * @author <a HREF="mailto:[EMAIL PROTECTED]">David Owens</a> * * @since version 0.8.? */ public class TimeRollingFileAppender extends FileAppender { /** * A string constant used in naming the option for setting the * hour at which to roll. * <b>RollHour</b>. */ static final public String ROLL_HOUR = "RollHour"; /** * A string constant used in naming the option for setting the * second at which to roll. * <b>RollSecond</b>. */ static final public String ROLL_SECOND = "RollSecond"; /** * A string constant used in naming the option for setting the * minute at which to roll. * <b>RollMinute</b>. */ static final public String ROLL_MINUTE = "RollMinute"; /** * A string constant used in naming the option for setting the * number of hours between rolls. * <b>RollIntervalHours</b>. */ static final public String ROLL_INTERVAL_HOURS = "RollIntervalHours"; /** * A string constant used in naming the option for setting the * number of minutes between rolls. * <b>RollIntervalMinutes</b>. */ static final public String ROLL_INTERVAL_MINUTES = "RollIntervalMinutes"; /** * A string constant used in naming the option for setting the * date/time format string used when stamping the backup files. * <b>StampFormat</b>. */ static final public String STAMP_FORMAT = "StampFormat"; private GregorianCalendar timeOfNextRoll = new GregorianCalendar(); private GregorianCalendar currentTime = new GregorianCalendar(); protected int rollHour = 00; // Roll when time > 00:XX:XX protected int rollMinute = 59; // Roll when time > XX:59:XX protected int rollSecond = 59; // Roll when time > XX:XX:59 protected int rollIntervalHours = 24; // Roll after 24 hours and XX minutes. protected int rollIntervalMinutes = 00; // Roll after XX hours and 00 minutes. protected SimpleDateFormat stampFormat = new SimpleDateFormat(".yyyy.MM.dd"); // Timestamp in this format /** * Sets the time when the first roll should occure. */ private void initRollDate() { timeOfNextRoll.setTime(new Date()); timeOfNextRoll.set(Calendar.HOUR_OF_DAY, rollHour); timeOfNextRoll.set(Calendar.MINUTE, rollMinute); timeOfNextRoll.set(Calendar.SECOND, rollSecond); //System.out.println("Time of next roll = " + timeOfNextRoll.get(Calendar.HOUR_OF_DAY) + ":" + timeOfNextRoll.get(Calendar.MINUTE)); } /** The default constructor simply calls its {@link FileAppender#FileAppender parents constructor}. */ public TimeRollingFileAppender() { super(); initRollDate(); } /** Instantiate a TimeRollingFileAppender and set the output destination to a new {@link OutputStreamWriter} initialized with <code>os</code> as its {@link OutputStream}. */ public TimeRollingFileAppender(Layout layout, OutputStream os) { super(layout, os); initRollDate(); } /** Instantiate a TimeRollingFileAppender and set the output destination to <code>writer</code>. <p>The <code>writer</code> must have been opened by the user. */ public TimeRollingFileAppender(Layout layout, Writer writer) { super(layout, writer); initRollDate(); } /** Instantiate a TimeRollingFileAppender and open the file designated by <code>filename</code>. The opened filename will become the ouput destination for this appender. <p>If the <code>append</code> parameter is true, the file will be appended to. Otherwise, the file desginated by <code>filename</code> will be truncated before being opened. */ public TimeRollingFileAppender(Layout layout, String filename, boolean append) throws IOException { super(layout, filename, append); initRollDate(); } /** Instantiate a FileAppender and open the file designated by <code>filename</code>. The opened filename will become the output destination for this appender. <p>The file will be appended to. */ public TimeRollingFileAppender(Layout layout, String filename) throws IOException { super(layout, filename); initRollDate(); } /** Same as {@link FileAppender#doAppend FileAppender.doAppend} except that the output file will be rolled over when the file reaches <code>MaxFileSize</code>. */ public synchronized void doAppend(LoggingEvent event) { if(!isAsSevereAsThreshold(event.priority)) return; // It may be the case that there is no output target for this // appender. if(this.qw == null) return; currentTime.setTime(new Date()); //System.out.print("Test if " + currentTime.get(Calendar.HOUR_OF_DAY) + ":" + currentTime.get(Calendar.MINUTE) + " > "); //System.out.println(timeOfNextRoll.get(Calendar.HOUR_OF_DAY) + ":" + timeOfNextRoll.get(Calendar.MINUTE)); if(this.timeOfNextRoll.before(currentTime) && fileName != null) { while(this.timeOfNextRoll.before(currentTime)) { this.timeOfNextRoll.add(Calendar.HOUR_OF_DAY,rollIntervalHours); this.timeOfNextRoll.add(Calendar.MINUTE,rollIntervalMinutes); } this.rollOver(); } super.doAppend(event); } public synchronized void setFile(String fileName, boolean append) throws IOException { super.setFile(fileName, append); if(append) { File f = new File(fileName); ((CountingQuietWriter) qw).setCount(f.length()); } } /** * Copies file and stamps it with the specified stamp format. */ public synchronized void rollOver() { File target; File file; // Rename fileName to fileName<stamp> target = new File(fileName + stampFormat.format(currentTime.getTime())); //System.out.println("Rolling " + fileName + " to " + target); file = new File(fileName); file.renameTo(target); try { // This will also close the file. This is OK since multiple // close operations are safe. this.setFile(fileName, false); } catch(IOException e) { System.err.println("setFile("+fileName+", false) call failed."); e.printStackTrace(); } } public String[] getOptionStrings() { return OptionConverter.concatanateArrays(super.getOptionStrings(), new String[] {ROLL_HOUR, ROLL_MINUTE, ROLL_SECOND, ROLL_INTERVAL_HOURS, ROLL_INTERVAL_MINUTES, STAMP_FORMAT}); } /** * Sets the hour at which the log should be rolled. * * @param int The hour to roll to the next log. */ public void setRollHour(int hour) { rollHour = hour; timeOfNextRoll.set(Calendar.HOUR_OF_DAY, rollHour); } /** * Sets the minute at which the log should be rolled. * * @param int The minute to roll to the next log. */ public void setRollMinute(int minute) { rollMinute = minute; timeOfNextRoll.set(Calendar.MINUTE, rollMinute); } /** * Sets the second at which the log should be rolled. * * @param int The second to roll to the next log. */ public void setRollSecond(int second) { rollSecond = second; timeOfNextRoll.set(Calendar.SECOND, rollSecond); } /** * Sets the number of hours between rolls. * * @param int The number of hours between rolls. */ public void setRollIntervalHours(int hours) { rollIntervalHours = hours; } /** * Sets the number of minutes between rolls. * * @param int The number of minutes between rolls. */ public void setRollIntervalMinutes(int minutes) { rollIntervalMinutes = minutes; } /** * Sets the format of the time used to stamp the * old log file. This string must be in the * format used by SimpleDateFormat. * * @param String A format string used to format * the time when rolling the log file. */ public void setStampFormat(String format) { stampFormat.applyLocalizedPattern(format); } /** * Sets the format of the time used to stamp the * old log file. * * @param SimpleDateFormat The format used to format * the time apended to the fileanme when rolling * the log file. */ public void setStampFormat(SimpleDateFormat format) { stampFormat = format; } public void setOption(String option, String value) { super.setOption(option, value); //System.out.println("setOption called with " + option + " & " + value); if(option.equalsIgnoreCase(ROLL_HOUR)) { setRollHour(OptionConverter.toInt(value, rollHour)); } else if(option.equalsIgnoreCase(ROLL_MINUTE)) { setRollMinute(OptionConverter.toInt(value, rollMinute)); } else if(option.equalsIgnoreCase(ROLL_SECOND)) { setRollSecond(OptionConverter.toInt(value, rollSecond)); } else if(option.equalsIgnoreCase(ROLL_INTERVAL_HOURS)) { rollIntervalHours = OptionConverter.toInt(value, rollIntervalHours); } else if(option.equalsIgnoreCase(ROLL_INTERVAL_MINUTES)) { rollIntervalMinutes = OptionConverter.toInt(value, rollIntervalMinutes); } else if(option.equalsIgnoreCase(STAMP_FORMAT)) { stampFormat.applyLocalizedPattern(value); } } protected void setQWForFiles(Writer writer) { this.qw = new CountingQuietWriter(writer, errorHandler); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]