uk.org.simonsite.log4j.appender
Class TimeAndSizeRollingAppender

java.lang.Object
  extended by org.apache.log4j.AppenderSkeleton
      extended by org.apache.log4j.WriterAppender
          extended by org.apache.log4j.FileAppender
              extended by uk.org.simonsite.log4j.appender.TimeAndSizeRollingAppender
All Implemented Interfaces:
Appender, OptionHandler, UnrecognizedElementHandler

public final class TimeAndSizeRollingAppender
extends FileAppender
implements UnrecognizedElementHandler

This appender is responsible for writing log events to file, and rolling files when they reach configurable limits of time and/or size. It is configured and behaves in much the same way as the DailyRollingFileAppender, with some useful differences.

Maximum file size

Maximum log file size can be configured (default 10MB) using the MaxFileSize property. This means that log files can be rolled within the configured time period if the maximum file size is exceeded. Backups are indicated by a count suffix at the end of log filenames, e.g. for the time suffix specified by the default pattern "'.'yyyy-MM-dd" (which would ordinarily result in a log file named e.g. "foo.log.2007-01-01") will result in backups named "foo.log.2007-01-01.1", "foo.log.2007-01-01.2", etc.

Maximum number of backup files

Configuring the maximum number of allowable backup log files (default 10) using the MaxRollFileCount property helps prevent this appender from consuming disk space without limit. Excess backup log files are scavenged by a background thread.

Configuring the scavenging interval (default 30 seconds) using the ScavengeInterval property specifies the duration for which the scavenger thread should sleep between operations. The log file scavenger only operates upon files that start with the path specified by the File configuration parameter. Older files will be deleted first.

Setting a scavenge interval of -1 prevents the scavenger from running.

Backup file compression

Backup log file compression may be configured using the allowed compression algorithms specified by the CompressionAlgorithm property:

Default behaviour is not to compress backup log files unless the CompressionAlgorithm property is configured. Backup files are compressed by a background thread. At roll time the name of the backup log File object is put into the compressor thread's FIFO queue. By default the compressor works on a best-effort basis: if the queue fills up, then older backup filenames are discarded and will therefore not be compressed.

The appender can be configured to force compression of all backup files by setting the CompressionUseBlockingQueue property to " true" (default is "false"). Forcing compression comes at the cost of blocking the compressor's queue and therefore the shared daemon thread used for compression and scavenging tasks; the application thread that invoked the Logger will not be blocked. The queue will cease to block once the current compression operation has completed and the compressor has removed the next file from its queue.

The appender's CompressionMinQueueSize property (default 0) controls the minimum number of backup files that must be in the queue awaiting compression before any compression will take actually take place. For example, if this property is set to 5, then at least 5 backup file rolls must take place before the oldest file currently in the compressor's queue will be compressed. Keeping the most recent files uncompressed can be helpful at support time.

You may choose to register a FileCompressionEventListener with the appender. To do so you must provide your own implementation of the FileCompressionEventListener interface on the classpath, and configure it via XML. For example:

<appender name="LOG-DAILYROLL" class="uk.org.simonsite.log4j .appender.TimeAndSizeRollingAppender">
  <param name="File" value="/logs/app.log"/>
  <param name="CompressionAlgorithm" value="ZIP"/>
  <fileCompressionEventListener class="com.acme.MyFileCompressionEventListener">
    <param name="MyParam" value="Sample Value"/>
  </fileCompressionEventListener>

  <layout class="org.apache.log4j.SimpleLayout"/>
</appender>

Time boundaries

If you have chosen a daily, weekly, or longer rolling strategy (via the DatePattern property), then you may wish to take advantage of the TimeZoneId property. In these cases setting the TimeZoneId property will ensure that the appender rolls at midnight in the configured time zone. For legal time zone IDs accepted by the appender, see core Java API doc for the TimeZone class.

Setting the appender's DateRollEnforced property to true (default false) activates pro-active log rolling at time boundaries. Time boundaries are enforced by a background thread. The standard DailyRollingFileAppender only rolls log files reactively upon the dispatch of a logging event. This appender allows proactive control over log rolling by enforcing a schedule implied by the DatePattern property. For example, <param name="DatePattern" value=".yyyy-MM-dd"/> will see the log file roll at the end of the day, even if the application is otherwise inactive. Similarly <param name="DatePattern" value=".yyyy-MM-dd-HH"/> will result in log files being rolled every hour.

File roll events

A custom message of your choosing may be written into the first line of each new log file created after a file roll has completed. This is achieved by setting the FileRollEventMessage property to a message string. If this property is configured with a blank value (e.g. <param name="FileRollEventMessage"/>), the appender will ensure that a default message is written at the top of the new log file instead. If this property is not set, no message will be written to the top of new log files. Messages are appended at Level.ALL using the root logger.

As an alternative to a message being written on file roll you may choose the greater flexibility afforded by registering a FileRollEventListener with the appender. To do so you must provide your own implementation of the FileRollEventListener interface on the classpath, and configure it via XML. For example:

<appender name="LOG-DAILYROLL" class="uk.org.simonsite.log4j .appender.TimeAndSizeRollingAppender">
  <param name="File" value="/logs/app.log"/>
  <fileRollEventListener class="com.acme.MyFileRollEventListener" >
    <param name="MyParam" value="Sample Value"/>
  </fileRollEventListener>

  <layout class="org.apache.log4j.SimpleLayout"/>
</appender>

Roll on start-up

The appender can be configured to roll the most recent backup file, regardless of the file's last modification time or size, immediately after receiving the first logging event after the appender's options are activated.

For example, say the appender is configured to roll every hour, or for files exceeding 10MB in size, and that a 1 MB log file exists that was last written 10 minutes before the hour. The application is restarted 5 minutes before the hour and logs an event. When the RollOnStartup property is set to true, the log file described in this example scenario will be rolled into a backup, and a new log file will be created.

NB If you use a Layout that writes headers and footers and require a single header and footer per log file, then you should set the RollOnStartup property to true.

Flush to storage

Out-of-the-box Log4J file appenders can be configured to flush after each append (via WriterAppender#setImmediateFlush()), though this offers no guarantees that what is appended will actually be written to disk. What is appended may be stored, for a short time, in memory buffers by the underlying OS. Therefore, in the event of machine failure, some logging events may be lost. Setting the FlushToStorageOnAppend property to true causes this appender to invoke FileDescriptor.sync() after each append. FlushToStorageOnAppend is false by default. NB This option comes with a performance overhead and may have a material impact upon application throughput: applications should be profiled.

Sample configurations

Sample 1

An example configuration snippet taken from an actual Log4J XML configuration file is given here (generate the Javadoc to see the correct formatting). This configuration provides an appender that rolls each day and creates log files no larger than 10MB. The number of backup files is checked every 30 seconds, whereupon if the number of backup files exceeds 100 the extra backups will be deleted. The appender will make best efforts to compress backup files using the GZ algorithm.

<appender name="LOG-DAILYROLL" class="uk.org.simonsite.log4j .appender.TimeAndSizeRollingAppender">
  <param name="File" value="/logs/app.log"/>
  <param name="Threshold" value="DEBUG"/>
  <param name="DatePattern" value=".yyyy-MM-dd"/>
  <param name="MaxFileSize" value="10MB"/>
  <param name="MaxRollFileCount" value="100"/>
  <param name="ScavengeInterval" value="30000"/>
  <param name="BufferedIO" value="false"/>
  <param name="CompressionAlgorithm" value="GZ"/>
  <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%-5p %-23d{ISO8601} [%t] %x: %c{1} - %m%n"/>
  </layout>
</appender>

Sample 2

This next configuration provides an appender that rolls each day, creates log files no larger than 100MB, and limits the number of backup files to no more than 10. The number of backup files is checked every 30 seconds, whereupon if the number of backup files exceeds 10 the extra backups will be deleted. The appender will make best efforts to compress backup files using the ZIP algorithm, but it will only compress backup files after more than 5 rolls have taken place during the lifetime of the application instance. Finally, this configuration causes the appender to honour time boundaries by rolling logs pro-actively at the end of each day, rather that reactively in response to a logging event. After file roll is complete, the new log file will have the message "First line of each file following a roll" printed on the first line.

<appender name="LOG-DAILYROLL" class="uk.org.simonsite.log4j .appender.TimeAndSizeRollingAppender">
  <param name="File" value="/logs/app.log"/>
  <param name="Threshold" value="DEBUG"/>
  <param name="DatePattern" value=".yyyy-MM-dd"/>
  <param name="MaxFileSize" value="100MB"/>
  <param name="DateRollEnforced" value="true"/>
  <param name="FileRollEventMessage" value="First line of each file following a roll"/>
  <param name="BufferedIO" value="false"/>
  <param name="CompressionAlgorithm" value="ZIP"/>
  <param name="CompressionMinQueueSize" value="5"/>
  <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%-5p %-23d{ISO8601} [%t] %x: %c{1} - %m%n"/>
  </layout>
</appender>

Sample 3

A final example of the simplest configuration provides an appender that rolls each day and creates log files no larger than 10MB. The number of backup files is checked every 30 seconds, whereupon if the number of backup files exceeds 10 the extra backups will be deleted. Backup files are not compressed, log files are rolled reactively, and no roll event messages are written at the top of each new log file.

<appender name="LOG-DAILYROLL" class="uk.org.simonsite.log4j .appender.TimeAndSizeRollingAppender">
  <param name="File" value="/logs/app.log"/>
  <param name="Threshold" value="DEBUG"/>
  <param name="BufferedIO" value="false"/>
  <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%-5p %-23d{ISO8601} [%t] %x: %c{1} - %m%n"/>
  </layout>
</appender>

Version:
4.7
Author:
Simon Park
See Also:
DailyRollingFileAppender

Field Summary
 
Fields inherited from class org.apache.log4j.FileAppender
bufferedIO, bufferSize, fileAppend, fileName
 
Fields inherited from class org.apache.log4j.WriterAppender
encoding, immediateFlush, qw
 
Fields inherited from class org.apache.log4j.AppenderSkeleton
closed, errorHandler, headFilter, layout, name, tailFilter, threshold
 
Constructor Summary
TimeAndSizeRollingAppender()
           
TimeAndSizeRollingAppender(Layout layout, String filename)
           
TimeAndSizeRollingAppender(Layout layout, String filename, boolean append)
           
TimeAndSizeRollingAppender(Layout layout, String filename, boolean append, boolean bufferedIO, int bufferSize)
           
 
Method Summary
 void activateOptions()
           
 void close()
           
protected  void closeFile()
          Makes file closing behaviour visible to classes in this package.
protected  OutputStreamWriter createWriter(OutputStream os)
           
 boolean equals(Object other)
           
 String getCompressionAlgorithm()
           
 int getCompressionLevel()
           
 long getCompressionMaxBlockingInterval()
           
 int getCompressionMinQueueSize()
           
 boolean getCompressionUseBlockingQueue()
           
 String getDatePattern()
           
 String getDatePatternLocale()
           
 boolean getDateRollEnforced()
           
(package private)  LoggingTaskExecutorService getExecutorService()
           
(package private)  FileRoller getFileRoller()
           
 String getFileRollEventListener()
          Deprecated.  
 boolean getFlushToStorageOnAppend()
           
(package private)  FileCompressionEventListener getGuestFileCompressionEventListener()
           
(package private)  FileRollEventListener getGuestFileRollEventListener()
           
(package private)  File getIoFile()
           
(package private)  LogFileCompressorTask getLogFileCompressor()
           
(package private)  LogFileScavenger getLogFileScavenger()
           
 String getMaxFileSize()
           
 int getMaxRollFileCount()
           
 String getMinFreeDiskSpace()
           
(package private)  AppenderRollingProperties getProperties()
           
 boolean getRollOnStartup()
           
 long getScavengeInterval()
           
 String getTimeZoneId()
           
 int hashCode()
           
(package private)  void openFile()
          Opens the log file and prepares this appender to write to it.
 boolean parseUnrecognizedElement(Element element, Properties props)
          Parses the following elements and configures instances of the classes attributed to each element discovered: <fileRollEventListener class="..." /> for implementors of FileRollEventListener <fileCompressionEventListener class="..." /> for implementors of FileCompressionEventListener <logFileScavenger class="..." /> for implementors of LogFileScavenger <logTaskExecutorService class="..." /> for implementors of LoggingTaskExecutorService For each of these elements, child <param/> elements are treated as expected by the DOMConfigurator.
 void setCompressionAlgorithm(String compressionAlgorithm)
           
 void setCompressionLevel(int compressionLevel)
           
 void setCompressionMaxBlockingInterval(long compressionInterval)
           
 void setCompressionMinQueueSize(int compressionMinQueueSize)
          The minimum number of backup files that must be in the queue awaiting compression before any compression will take place.
 void setCompressionUseBlockingQueue(boolean compressionBlockingQueue)
           
 void setDatePattern(String datePattern)
           
 void setDatePatternLocale(String datePatternLocale)
          Sets the Locale to be used when processing date patterns.
 void setDateRollEnforced(boolean dateRollEnforced)
           
 void setFileRollEventListener(String className)
          Deprecated. Configure FileRollEventListeners via XML, using the "fileRollEventListener" element.
 void setFileRollEventMessage(String message)
           
 void setFlushToStorageOnAppend(boolean flushToStorageOnAppend)
          When this property is true, configured values for the properties FileAppender.setBufferedIO(boolean)and WriterAppender.setImmediateFlush(boolean) are overridden to false and true, respectively, upon activation of an instance of this object.
 void setLogFileScavenger(String className)
          Deprecated. Configure LogFileScavengers via XML, using the "logFileScavenger" element.
(package private)  void setLogTaskExecutorService(LoggingTaskExecutorService loggingTaskExecutorService)
          Test use only.
 void setMaxFileSize(String value)
           
 void setMaxRollFileCount(int maxRollFileCount)
           
 void setMinFreeDiskSpace(long minFreeDiskSpace)
           
 void setMinFreeDiskSpace(String value)
          Warning Use of this property requires Java 6.
protected  void setQWForFiles(Writer writer)
           
 void setRollOnStartup(boolean rollOnStartup)
           
 void setScavengeInterval(long intervalMillis)
           
 void setTimeZoneId(String timeZoneId)
           
protected  void subAppend(LoggingEvent event)
          Responsible for executing file rolls as and when required, in addition to delegating to the super class to perform the actual append operation.
protected  void writeFooter()
           
protected  void writeHeader()
           
 
Methods inherited from class org.apache.log4j.FileAppender
getAppend, getBufferedIO, getBufferSize, getFile, reset, setAppend, setBufferedIO, setBufferSize, setFile, setFile
 
Methods inherited from class org.apache.log4j.WriterAppender
append, checkEntryConditions, closeWriter, getEncoding, getImmediateFlush, requiresLayout, setEncoding, setErrorHandler, setImmediateFlush, setWriter, shouldFlush
 
Methods inherited from class org.apache.log4j.AppenderSkeleton
addFilter, clearFilters, doAppend, finalize, getErrorHandler, getFilter, getFirstFilter, getLayout, getName, getThreshold, isAsSevereAsThreshold, setLayout, setName, setThreshold
 
Methods inherited from class java.lang.Object
clone, getClass, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

TimeAndSizeRollingAppender

public TimeAndSizeRollingAppender()

TimeAndSizeRollingAppender

public TimeAndSizeRollingAppender(Layout layout,
                                  String filename)
                           throws IOException
Parameters:
layout -
filename -
Throws:
IOException

TimeAndSizeRollingAppender

public TimeAndSizeRollingAppender(Layout layout,
                                  String filename,
                                  boolean append)
                           throws IOException
Parameters:
layout -
filename -
append -
Throws:
IOException

TimeAndSizeRollingAppender

public TimeAndSizeRollingAppender(Layout layout,
                                  String filename,
                                  boolean append,
                                  boolean bufferedIO,
                                  int bufferSize)
                           throws IOException
Parameters:
layout -
filename -
append -
bufferedIO -
bufferSize -
Throws:
IOException
Method Detail

equals

public boolean equals(Object other)
Overrides:
equals in class Object

hashCode

public int hashCode()
Overrides:
hashCode in class Object

activateOptions

public final void activateOptions()
Specified by:
activateOptions in interface OptionHandler
Overrides:
activateOptions in class FileAppender

close

public final void close()
Specified by:
close in interface Appender
Overrides:
close in class WriterAppender

parseUnrecognizedElement

public final boolean parseUnrecognizedElement(Element element,
                                              Properties props)
                                       throws Exception
Parses the following elements and configures instances of the classes attributed to each element discovered: For each of these elements, child <param/> elements are treated as expected by the DOMConfigurator.

NB Only one of each element is permitted.

Specified by:
parseUnrecognizedElement in interface UnrecognizedElementHandler
Throws:
Exception
See Also:
(org.w3c.dom.Element, java.util.Properties)

getCompressionAlgorithm

public String getCompressionAlgorithm()

getCompressionUseBlockingQueue

public boolean getCompressionUseBlockingQueue()

getCompressionMaxBlockingInterval

public long getCompressionMaxBlockingInterval()

getCompressionMinQueueSize

public int getCompressionMinQueueSize()

getCompressionLevel

public int getCompressionLevel()

getDatePattern

public String getDatePattern()

getDatePatternLocale

public String getDatePatternLocale()

getDateRollEnforced

public boolean getDateRollEnforced()

getFileRollEventListener

public String getFileRollEventListener()
Deprecated. 

Returns:
The fully qualified class name of the guest listener.

getFlushToStorageOnAppend

public boolean getFlushToStorageOnAppend()

getMaxFileSize

public String getMaxFileSize()

getMinFreeDiskSpace

public String getMinFreeDiskSpace()

getMaxRollFileCount

public int getMaxRollFileCount()

getRollOnStartup

public boolean getRollOnStartup()

getScavengeInterval

public long getScavengeInterval()

getTimeZoneId

public String getTimeZoneId()

setCompressionAlgorithm

public void setCompressionAlgorithm(String compressionAlgorithm)
Parameters:
compressionAlgorithm - "ZIP" or "GZ"

setCompressionUseBlockingQueue

public void setCompressionUseBlockingQueue(boolean compressionBlockingQueue)

setCompressionMaxBlockingInterval

public void setCompressionMaxBlockingInterval(long compressionInterval)

setCompressionLevel

public void setCompressionLevel(int compressionLevel)
Parameters:
compressionLevel - Deflater.DEFAULT_COMPRESSION, Deflater.NO_COMPRESSION, or in the range Deflater.BEST_SPEED to Deflater.BEST_COMPRESSION.
See Also:
Deflater

setCompressionMinQueueSize

public void setCompressionMinQueueSize(int compressionMinQueueSize)
The minimum number of backup files that must be in the queue awaiting compression before any compression will take place.

Parameters:
compressionMinQueueSize - >= 0.

setDatePattern

public void setDatePattern(String datePattern)
Parameters:
datePattern - in compliance with localized patterns similar to those specified by SimpleDateFormat. Note that the pattern characters in the main Javadoc of SimpleDateFormat are defaults for Locale.ENGLISH, if I understand correctly.
See Also:
SimpleDateFormat

setDatePatternLocale

public void setDatePatternLocale(String datePatternLocale)
Sets the Locale to be used when processing date patterns. Variants are not supported; only language and (optionally) country may be used, e.g. "en",  "en_GB" or "fr_CA" are all valid. If no locale is supplied, Locale.ENGLISH will be used.

Parameters:
datePatternLocale -
See Also:
Locale, setDatePattern(String)

setDateRollEnforced

public void setDateRollEnforced(boolean dateRollEnforced)
Parameters:
dateRollEnforced - When true file rolls will occur pro-actively when the time boundary is reached, rather than reactively in response to a logging event.

setFileRollEventListener

public void setFileRollEventListener(String className)
Deprecated. Configure FileRollEventListeners via XML, using the "fileRollEventListener" element.

Parameters:
className - The fully qualified name of the class that implements the FileRollEventListener interface; implementors must be declared public and have a default constructor.

setFlushToStorageOnAppend

public void setFlushToStorageOnAppend(boolean flushToStorageOnAppend)
When this property is true, configured values for the properties FileAppender.setBufferedIO(boolean)and WriterAppender.setImmediateFlush(boolean) are overridden to false and true, respectively, upon activation of an instance of this object.

Parameters:
flushToStorageOnAppend - false by default.

setLogFileScavenger

public void setLogFileScavenger(String className)
Deprecated. Configure LogFileScavengers via XML, using the "logFileScavenger" element.

Parameters:
className - The fully qualified name of the class that implements the LogFileScavenger interface; implementors must be declared public and have a default constructor.

setFileRollEventMessage

public void setFileRollEventMessage(String message)
Parameters:
message - The message to be appended at the top of each new file created following a file roll. If the message is empty, a default message will be appended instead.

setMaxFileSize

public void setMaxFileSize(String value)

setMinFreeDiskSpace

public void setMinFreeDiskSpace(String value)
Warning Use of this property requires Java 6.

Parameters:
value -

setMaxRollFileCount

public void setMaxRollFileCount(int maxRollFileCount)

setRollOnStartup

public void setRollOnStartup(boolean rollOnStartup)
Parameters:
rollOnStartup - true if the appender should roll, and create a new log file, immediately upon receiving the first logging event after activation.

setScavengeInterval

public void setScavengeInterval(long intervalMillis)

setMinFreeDiskSpace

public void setMinFreeDiskSpace(long minFreeDiskSpace)

setTimeZoneId

public void setTimeZoneId(String timeZoneId)

getFileRoller

final FileRoller getFileRoller()

getGuestFileRollEventListener

final FileRollEventListener getGuestFileRollEventListener()

getGuestFileCompressionEventListener

final FileCompressionEventListener getGuestFileCompressionEventListener()

getLogFileCompressor

final LogFileCompressorTask getLogFileCompressor()

getLogFileScavenger

final LogFileScavenger getLogFileScavenger()

getExecutorService

final LoggingTaskExecutorService getExecutorService()

getProperties

final AppenderRollingProperties getProperties()

getIoFile

final File getIoFile()

openFile

final void openFile()
Opens the log file and prepares this appender to write to it.


setLogTaskExecutorService

final void setLogTaskExecutorService(LoggingTaskExecutorService loggingTaskExecutorService)
Test use only.

Parameters:
loggingTaskExecutorService -

closeFile

protected final void closeFile()
Makes file closing behaviour visible to classes in this package.

Overrides:
closeFile in class FileAppender
See Also:
FileAppender.closeFile()

createWriter

protected final OutputStreamWriter createWriter(OutputStream os)
Overrides:
createWriter in class WriterAppender

setQWForFiles

protected final void setQWForFiles(Writer writer)
Overrides:
setQWForFiles in class FileAppender

subAppend

protected final void subAppend(LoggingEvent event)
Responsible for executing file rolls as and when required, in addition to delegating to the super class to perform the actual append operation. Synchronized for safety during enforced file roll.

Overrides:
subAppend in class WriterAppender
See Also:
WriterAppender.subAppend(org.apache.log4j.spi.LoggingEvent)

writeFooter

protected final void writeFooter()
Overrides:
writeFooter in class WriterAppender

writeHeader

protected final void writeHeader()
Overrides:
writeHeader in class WriterAppender