There is so much to tell about the Western country in that day that it is hard to know where to start. One thing sets off a hundred others. The problem is to decide which one to tell first.

—JOHN STEINBECK, East of Eden

Manual · Appenders · Appenders: Rolling File

Appenders: Rolling File

RollingFileAppender

RollingFileAppender extends FileAppender with the capability to rollover log files. For example, RollingFileAppender can log to a file named log.txt file and, once a certain condition is met, change its logging target to another file.

There are two important subcomponents that interact with RollingFileAppender. The first RollingFileAppender sub-component, namely RollingPolicy, (see below) is responsible for undertaking the actions required for a rollover. A second subcomponent of RollingFileAppender, namely TriggeringPolicy, (see below) will determine if and exactly when rollover occurs. Thus, RollingPolicy is responsible for the what and TriggeringPolicy is responsible for the when.

To be of any use, a RollingFileAppender must have both a RollingPolicy and a TriggeringPolicy set up. However, if its RollingPolicy also implements the TriggeringPolicy interface, then only the former needs to be specified explicitly.

Here are the available properties for RollingFileAppender:

Property Name Type Description
file String See FileAppender properties. Note that file can be null in which case the output is written only to the target specified by the RollingPolicy.
append boolean See FileAppender properties.
encoder Encoder See OutputStreamAppender properties.
rollingPolicy RollingPolicy This option is the component that will dictate RollingFileAppender's behavior when rollover occurs. See more information below.
triggeringPolicy TriggeringPolicy This option is the component that will tell RollingFileAppender when to activate the rollover procedure. See more information below.
prudent boolean FixedWindowRollingPolicy is not supported in prudent mode.

RollingFileAppender supports the prudent mode in conjunction with TimeBasedRollingPolicy albeit with two restrictions.

  1. In prudent mode, file compression is not supported nor allowed. (We can't have one JVM writing to a file while another JVM is compressing it.)
  2. The file property of FileAppender cannot be set and must be left blank. Indeed, most operating systems do not allow renaming of a file while another process has it opened.
See also properties for FileAppender.

Overview of rolling policies

RollingPolicy is responsible for the rollover procedure which involves file moving and renaming.

The RollingPolicy interface is presented below:

package ch.qos.logback.core.rolling;

import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.spi.LifeCycle;

public interface RollingPolicy extends LifeCycle {

  public void rollover() throws RolloverFailure;
  public String getActiveFileName();
  public CompressionMode getCompressionMode();
  public void setParent(FileAppender appender);
}

The rollover method accomplishes the work involved in archiving the current log file. The getActiveFileName() method is called to compute the file name of the current log file (where live logs are written to). As indicated by getCompressionMode method a RollingPolicy is also responsible for determining the compression mode. Lastly, a RollingPolicy is given a reference to its parent via the setParent method.

TimeBasedRollingPolicy

TimeBasedRollingPolicy is possibly the most popular rolling policy. It defines a rollover policy based on time, for example by day or by month. TimeBasedRollingPolicy assumes the responsibility for rollover as well as for the triggering of said rollover. Indeed, TimeBasedTriggeringPolicy implements both RollingPolicy and TriggeringPolicy interfaces.

TimeBasedRollingPolicy's configuration takes one mandatory fileNamePattern property and several optional properties.

Property Name Type Description
fileNamePattern String The mandatory fileNamePattern property defines the name of the rolled-over (archived) log files. Its value should consist of the name of the file, plus a suitably placed %d conversion specifier. The %d conversion specifier may contain a date-and-time pattern as specified by the java.text.SimpleDateFormat class. If the date-and-time pattern is omitted, then the default pattern yyyy-MM-dd is assumed. The rollover period is inferred from the value of fileNamePattern.

Note that the file property in RollingFileAppender (the parent of TimeBasedRollingPolicy) can be either set to a value or omitted (=null). By setting the file property of the containing FileAppender, you can decouple the location of the active log file and the location of the archived log files. The current logs will always be targeted at the file specified by the file property. It follows that the name of the currently active log file will not change over time.

However, if you choose to omit the file property, then the active file will be computed anew for each period based on the value of fileNamePattern. In this configuration no roll over occurs, unless file compression is specified. The examples below should clarify this point.

The date-and-time pattern, as found within the accolades of %d{} follow java.text.SimpleDateFormat conventions. The forward slash '/' or backward slash '\' characters anywhere within the fileNamePattern property or within the date-and-time pattern will be interpreted as directory separators.

Multiple %d specifiers

It is possible to specify multiple %d specifiers but only one of which can be primary, i.e. used to infer the rollover period. All other tokens must be marked as auxiliary by passing the 'aux' parameter (see examples below).

Multiple %d specifiers allow you to organize archive files in a folder structure different than that of the roll-over period. For example, the file name pattern shown below organizes log folders by year and month but roll-over log files every day at midnight.

/var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log
TimeZone

Under certain circumstances, you might wish to roll-over log files according to a clock in a timezone different than that of the host. It is possible to pass a timezone argument following the date-and-time pattern within the %d conversion specifier. For example:

aFolder/test.%d{yyyy-MM-dd-HH, UTC}.log

If the specified timezone identifier is unknown or misspelled, the GMT timezone is assumed as dictated by the TimeZone.getTimeZone(String) method specification.

maxHistory int

The optional maxHistory property controls the maximum number of archive files to keep, asynchronously deleting older files. For example, if you specify monthly rollover, and set maxHistory to 6, then 6 months worth of archives files will be kept with files older than 6 months deleted. Note as old archived log files are removed, any folders which were created for the purpose of log file archiving will be removed as appropriate.

Setting maxHistory to zero disables archive removal. By default, maxHistory is set to zero, i.e. by default there is no archive removal.

totalSizeCap FileSize

The optional totalSizeCap property controls the total size of all archive files. Oldest archives are deleted asynchronously when the total size cap is exceeded. The totalSizeCap property requires maxHistory property to be set as well. Moreover, the "max history" restriction is always applied first and the "total size cap" restriction applied second. In other words, if enabled, both restrictions are applied, albeit sequentially.

The totalSizeCap property can be specified in units of bytes, kilobytes, megabytes or gigabytes by suffixing a numeric value with KB, MB and respectively GB. For example, 5242880, 5120KB, 5120 KB, 5MB, 5 MB, 2 GB and 2GB are all valid values, with the first five being equivalent. A numerical value with no suffix is taken to be in units of bytes.

By default, totalSizeCap is set to zero, meaning that there is no total size cap.

cleanHistoryOnStart boolean

If set to true, archive removal will be executed on appender start up. By default, this property is set to false.

Archive removal is normally performed during roll over. However, some applications may not live long enough for roll over to be triggered. It follows that for such short-lived applications archive removal may never get a chance to execute. By setting cleanHistoryOnStart to true, archive removal is performed at appender start up.

Here are a few fileNamePattern values with an explanation of their effects.

fileNamePattern Rollover schedule Example
/wombat/foo.%d Daily rollover (at midnight). Due to the omission of the optional time and date pattern for the %d token specifier, the default pattern of yyyy-MM-dd is assumed, which corresponds to daily rollover.

file property not set: During November 23rd, 2006, logging output will go to the file /wombat/foo.2006-11-23. At midnight and for the rest of the 24th, logging output will be directed to /wombat/foo.2006-11-24.

file property set to /wombat/foo.txt: During November 23rd, 2006, logging output will go to the file /wombat/foo.txt. At midnight, foo.txt will be renamed as /wombat/foo.2006-11-23. A new /wombat/foo.txt file will be created and for the rest of November 24th logging output will be directed to foo.txt.

/wombat/%d{yyyy/MM}/foo.txt Rollover at the beginning of each month.

file property not set: During the month of October 2006, logging output will go to /wombat/2006/10/foo.txt. After midnight of October 31st and for the rest of November, logging output will be directed to /wombat/2006/11/foo.txt.

file property set to /wombat/foo.txt: The active log file will always be /wombat/foo.txt. During the month of October 2006, logging output will go to /wombat/foo.txt. At midnight of October 31st, /wombat/foo.txt will be renamed as /wombat/2006/10/foo.txt. A new /wombat/foo.txt file will be created where logging output will go for the rest of November. At midnight of November 30th, /wombat/foo.txt will be renamed as /wombat/2006/11/foo.txt and so on.

/wombat/foo.%d{yyyy-ww}.log Rollover at the first day of each week. Note that the first day of the week depends on the locale. Similar to previous cases, except that rollover will occur at the beginning of every new week.
/wombat/foo%d{yyyy-MM-dd_HH}.log Rollover at the top of each hour. Similar to previous cases, except that rollover will occur at the top of every hour.
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log Rollover at the beginning of every minute. Similar to previous cases, except that rollover will occur at the beginning of every minute.
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log Rollover at the beginning of every minute. Similar to previous cases, except that file names will be expressed in UTC.
/foo/%d{yyyy-MM,aux}/%d.log Rollover daily. Archives located under a folder containing year and month. In this example, the first %d token is marked as auxiliary. The second %d token, with time and date pattern omitted, is then assumed to be primary. Thus, rollover will occur daily (default for %d) and the folder name will depend on the year and month. For example, during the month of November 2006, archived files will all placed under the /foo/2006-11/ folder, e.g /foo/2006-11/2006-11-14.log.

Any forward or backward slash characters are interpreted as folder (directory) separators. Any required folder will be created as necessary. You can thus easily place your log files in separate folders.

Automatic file compression

TimeBasedRollingPolicy supports automatic file compression. This feature is enabled if the value of the fileNamePattern option ends with .gz .zip or .xz. Note that xz compression requires Tukaani project's XZ library for Java. In case XZ compression is requested but the XZ library is missing, then logback will substitute GZ compression as a fallback.

fileNamePattern Rollover schedule Example
/wombat/foo.%d.gz Daily rollover (at midnight) with automatic GZIP compression of the archived files.

file property not set: During November 23rd, 2009, logging output will go to the file /wombat/foo.2009-11-23. However, at midnight that file will be compressed to become /wombat/foo.2009-11-23.gz. For the 24th of November, logging output will be directed to /wombat/folder/foo.​2009-11-24 until it's rolled over at the beginning of the next day.

file property set to /wombat/foo.txt: During November 23rd, 2009, logging output will go to the file /wombat/foo.txt. At midnight that file will be compressed and renamed as /wombat/foo.2009-11-23.gz. A new /wombat/foo.txt file will be created where logging output will go for the rest of November 24th. At midnight November 24th, /wombat/foo.txt will be compressed and renamed as /wombat/foo.2009-11-24.gz and so on.

The fileNamePattern serves a dual purpose. First, by studying the pattern, logback computes the requested rollover periodicity. Second, it computes each archived file's name. Note that it is possible for two different patterns to specify the same periodicity. The patterns yyyy-MM and yyyy@MM both specify monthly rollover, although the resulting archive files will carry different names.

By setting the file property you can decouple the location of the active log file and the location of the archived log files. The logging output will be targeted into the file specified by the file property. It follows that the name of the active log file will not change over time. However, if you choose to omit the file property, then the active file will be computed anew for each period based on the value of fileNamePattern. By leaving the file option unset you can avoid file renaming errors which occur while there exist external file handles referencing log files during roll over.

The maxHistory property controls the maximum number of archive files to keep, deleting older files. For example, if you specify monthly rollover, and set maxHistory to 6, then 6 months worth of archives files will be kept with files older than 6 months deleted. Note as old archived log files are removed, any folders which were created for the purpose of log file archiving will be removed as appropriate.

For various technical reasons, rollovers are not clock-driven but depend on the arrival of logging events. For example, on 8th of March 2002, assuming the fileNamePattern is set to yyyy-MM-dd (daily rollover), the arrival of the first event after midnight will trigger a rollover. If there are no logging events during, say 23 minutes and 47 seconds after midnight, then rollover will actually occur at 00:23'47 AM on March 9th and not at 0:00 AM. Thus, depending on the arrival rate of events, rollovers might be triggered with some latency. However, regardless of the delay, the rollover algorithm is known to be correct, in the sense that all logging events generated during a certain period will be output in the correct file delimiting that period.

Here is a sample configuration for RollingFileAppender in conjunction with a TimeBasedRollingPolicy.

Example: Sample configuration of a RollingFileAppender using a TimeBasedRollingPolicy (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-RollingTimeBased.​xml)

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- daily rollover -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

      <!-- keep 30 days' worth of history capped at 3GB total size -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>

    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Requires a server call.

Requires a server call.

The next configuration sample illustrates the use of RollingFileAppender associated with TimeBasedRollingPolicy in prudent mode.

Example: Sample configuration of a RollingFileAppender using a TimeBasedRollingPolicy (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-PrudentTimeBasedRolling.​xml)

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- Support multiple-JVM writing to the same log file -->
    <prudent>true</prudent>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>30</maxHistory> 
      <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp -%msg%n</pattern>
    </encoder>
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Requires a server call.

Requires a server call.

Size and time based rolling policy

Sometimes you may wish to archive files essentially by date but at the same time limit the size of each log file, in particular if post-processing tools impose size limits on the log files. In order to address this requirement, logback ships with SizeAndTimeBasedRollingPolicy.

Note that TimeBasedRollingPolicy already allows limiting the combined size of archived log files. If you only wish to limit the combined size of log archives, then TimeBasedRollingPolicy described above and setting the totalSizeCap property should be amply sufficient. Moreover, given that file renaming is a relatively slow process and is frought with problems, we discourage the use of SizeAndTimeBasedRollingPolicy unless you have a real-world use case.

The roll over based on size relies on the "%i" conversion token in addition to "%d". Both the %i and %d tokens are mandatory. Each time the current log file reaches maxFileSize before the current time period ends, it will be archived with an increasing index, starting at 0.

The table below lists the properties applicable for SizeAndTimeBasedRollingPolicy. Note these properties complement those applicable for TimeBasedRollingPolicy.

Property Name Type Description
maxFileSize FileSize

Each time the current log file reaches maxFileSize before the current time period ends, it will be archived with an increasing index, starting at 0.

Options in defined in units of "FileSize" can be specified in bytes, kilobytes, megabytes or gigabytes by suffixing a numeric value with KB, MB and respectively GB. For example, 5000000, 5000KB, 5MB and 2GB are all valid values, with the first three being equivalent.

checkIncrement Duration

since 1.5.8 The checkIncrement property is no longer needed as logback now counts the number of bytes written to file.

Here is a sample configuration file demonstrating time and size based log file archiving.

Example: Sample configuration for SizeAndTimeBasedRollingPolicy (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-sizeAndTime.​xml)

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>


  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>

</configuration>

Requires a server call.

Requires a server call.

Note the "%i" conversion token in addition to "%d". Both the %i and %d tokens are mandatory. Each time the current log file reaches maxFileSize before the current time period ends, it will be archived with an increasing index, starting at 0.

Size and time based archiving supports deletion of old archive files. You need to specify the number of periods to preserve with the maxHistory property. When your application is stopped and restarted, logging will continue at the correct location, i.e. at the largest index number for the current period.

In versions prior to 1.1.7, this document mentioned a component called SizeAndTimeBasedFNATP. However, given that SizeAndTimeBasedRollingPolicy offers a simpler configuration structure, we no longer document SizeAndTimeBasedFNATP. Moreover, in logback version 1.5.8, SizeAndTimeBasedFNATP was renamed as SizeAndTimeBasedFileNamingAndTriggeringPolicy. Thus, earlier configuration files using SizeAndTimeBasedFNATP will no longer work.

FixedWindowRollingPolicy

Given that file renaming is a relatively slow process and is frought with problems, we consider FixedWindowRollingPolicy as a deprecated policy and do not recommend its use.

When rolling over, FixedWindowRollingPolicy renames files according to a fixed window algorithm as described below.

The fileNamePattern option represents the file name pattern for the archived (rolled over) log files. This option is required and must include an integer token %i somewhere within the pattern.

Here are the available properties for FixedWindowRollingPolicy

Property Name Type Description
minIndex int

This option represents the lower bound for the window's index.

maxIndex int

This option represents the upper bound for the window's index.

fileNamePattern String

This option represents the pattern that will be followed by the FixedWindowRollingPolicy when renaming the log files. It must contain the string %i, which will indicate the position where the value of the current window index will be inserted.

For example, using MyLogFile%i.log associated with minimum and maximum values of 1 and 3 will produce archive files named MyLogFile1.log, MyLogFile2.log and MyLogFile3.log.

Note that file compression is also specified via this property. For example, fileNamePattern set to MyLogFile%i.log.zip means that archived files must be compressed using the zip format; gz format is also supported.

Given that the fixed window rolling policy requires as many file renaming operations as the window size, large window sizes are strongly discouraged. When large values are specified by the user, the current implementation will automatically reduce the window size to 20.

Let us go over a more concrete example of the fixed window rollover policy. Suppose that minIndex is set to 1, maxIndex set to 3, fileNamePattern property set to foo%i.log, and that file property is set to foo.log.

Number of rollovers Active output target Archived log files Description
0 foo.log - No rollover has happened yet, logback logs into the initial file.
1 foo.log foo1.log First rollover. foo.log is renamed as foo1.log. A new foo.log file is created and becomes the active output target.
2 foo.log foo1.log, foo2.log Second rollover. foo1.log is renamed as foo2.log. foo.log is renamed as foo1.log. A new foo.log file is created and becomes the active output target.
3 foo.log foo1.log, foo2.log, foo3.log Third rollover. foo2.log is renamed as foo3.log. foo1.log is renamed as foo2.log. foo.log is renamed as foo1.log. A new foo.log file is created and becomes the active output target.
4 foo.log foo1.log, foo2.log, foo3.log In this and subsequent rounds, the rollover begins by deleting foo3.log. Other files are renamed by incrementing their index as shown in previous steps. In this and subsequent rollovers, there will be three archive logs and one active log file.

The configuration file below gives an example of configuring RollingFileAppender and FixedWindowRollingPolicy. Note that the File option is mandatory even if it contains some of the same information as conveyed with the fileNamePattern option.

Example: Sample configuration of a RollingFileAppender using a FixedWindowRollingPolicy (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-RollingFixedWindow.​xml)

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>

    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>tests.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp -%msg%n</pattern>
    </encoder>
  </appender>
	
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Requires a server call.

Requires a server call.

Overview of triggering policies

TriggeringPolicy implementations are responsible for instructing the RollingFileAppender when to rollover.

The TriggeringPolicy interface contains only one method.

package ch.qos.logback.core.rolling;

import java.io.File;
import ch.qos.logback.core.spi.LifeCycle;

public interface TriggeringPolicy<E> extends LifeCycle {

  public boolean isTriggeringEvent(final File activeFile, final <E> event);
}

The isTriggeringEvent() method takes as parameters the active file and the logging event currently being processed. The concrete implementation determines whether the rollover should occur or not, based on these parameters.

The most widely-used triggering policy, namely TimeBasedRollingPolicy which also doubles as a rolling policy, was already discussed earlier along with other rolling policies.

SizeBasedTriggeringPolicy

SizeBasedTriggeringPolicy looks at the size of the currently active file. If it grows larger than the specified size, it will signal the owning RollingFileAppender to trigger the rollover of the existing active file.

SizeBasedTriggeringPolicy accepts only one parameter, namely maxFileSize, with a default value of 10 MB.

The maxFileSize option can be specified in bytes, kilobytes, megabytes or gigabytes by suffixing a numeric value with KB, MB and respectively GB. For example, 5000000, 5000KB, 5MB and 2GB are all valid values, with the first three being equivalent.

Here is a sample configuration with a RollingFileAppender in conjunction with SizeBasedTriggeringPolicy triggering rollover when the log file reaches 5MB in size.

Example: Sample configuration of a RollingFileAppender using a SizeBasedTriggeringPolicy (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-RollingSizeBased.​xml)

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>test.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp -%msg%n</pattern>
    </encoder>
  </appender>
	
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Requires a server call.

Requires a server call.