<?xml version="1.0"?>
<!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You 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.
-->

<document xmlns="http://maven.apache.org/XDOC/2.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
    <properties>
        <title>Log4j 2 Appenders</title>
        <author email="rgoers@apache.org">Ralph Goers</author>
        <author email="ggrgeory@apache.org">Gary Gregory</author>
        <author email="nickwilliams@apache.org">Nick Williams</author>
        <author email="mattsicker@apache.org">Matt SIcker</author>
    </properties>

    <body>
      <section name="Appenders">
        <p>
          Appenders are responsible for delivering LogEvents to their destination. Every Appender must
          implement the <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/Appender.html">Appender</a>
          interface. Most Appenders will extend
          <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/appender/AbstractAppender.html">AbstractAppender</a>
          which adds <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/LifeCycle.html">Lifecycle</a>
          and <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/filter/Filterable.html">Filterable</a>
          support. Lifecycle allows components to finish initialization after configuration has completed and to
          perform cleanup during shutdown. Filterable allows the component to have Filters attached to it which are
          evaluated during event processing.
        </p>
        <p>
          Appenders usually are only responsible for writing the event data to the target destination. In most cases
          they delegate responsibility for formatting the event to a <a href="layouts.html">layout</a>. Some
          appenders wrap other appenders so that they can modify the LogEvent, handle a failure in an Appender,
          route the event to a subordinate Appender based on advanced Filter criteria or provide similar functionality
          that does not directly format the event for viewing.
        </p>
        <p>
          Appenders always have a name so that they can be referenced from Loggers.
        </p>
        <p>
          In the tables below, the "Type" column corresponds to the Java type expected. For non-JDK classes, these
          should usually be in <a href="../log4j-core/apidocs/index.html">Log4j Core</a> unless otherwise noted.
        </p>
        <a name="AsyncAppender"/>
        <subsection name="AsyncAppender">
          <p>The AsyncAppender accepts references to other Appenders and causes LogEvents to be written to them
            on a separate Thread. Note that exceptions while writing to those Appenders will be hidden from
            the application. The AsyncAppender should be configured after the appenders it references to allow it
            to shut down properly.</p>
          <p>
            By default, AsyncAppender uses
            <a class="javadoc" href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ArrayBlockingQueue.html">java.util.concurrent.ArrayBlockingQueue</a>
            which does not require any external libraries. Note that multi-threaded applications should exercise care
            when using this appender as such: the blocking queue is susceptible to lock contention and our
            <a href="../performance.html#asyncLogging">tests showed</a>
            performance may become worse when more threads are logging concurrently.
            Consider using <a href="async.html">lock-free Async Loggers</a> for optimal performance.
          </p>
          <table>
            <caption align="top">AsyncAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>AppenderRef</td>
              <td>String</td>
              <td>The name of the Appenders to invoke asynchronously. Multiple AppenderRef
                elements can be configured.</td>
            </tr>
            <tr>
              <td>blocking</td>
              <td>boolean</td>
              <td>If true, the appender will wait until there are free slots in the queue. If false, the event
                will be written to the error appender if the queue is full. The default is true.</td>
            </tr>
            <tr>
              <td>shutdownTimeout</td>
              <td>integer</td>
              <td>How many milliseconds the Appender should wait to flush outstanding log events in the queue
                on shutdown. The default is zero which means to wait forever.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>integer</td>
              <td>Specifies the maximum number of events that can be queued. The default is 128. Note that when using a
                disruptor-style <tt>BlockingQueue</tt>, this buffer size must be a power of 2.
                <p>
                  When the application is logging faster than the underlying appender can keep up with
                  for a long enough time to fill up the queue, the behavious is determined by the
                  <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/async/AsyncQueueFullPolicy.html">AsyncQueueFullPolicy</a>.
                </p>
              </td>
            </tr>
            <tr>
              <td>errorRef</td>
              <td>String</td>
              <td>The name of the Appender to invoke if none of the appenders can be called, either due to errors
                in the appenders or because the queue is full. If not specified then errors will be ignored.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
                may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>includeLocation</td>
              <td>boolean</td>
              <td>Extracting location is an expensive operation (it can make
              logging 5 - 20 times slower). To improve performance, location is
              not included by default when adding a log event to the queue.
              You can change this by setting includeLocation="true".</td>
            </tr>
            <tr>
              <td>BlockingQueueFactory</td>
              <td>BlockingQueueFactory</td>
              <td>This element overrides what type of <tt>BlockingQueue</tt> to use. See
                <a href="#BlockingQueueFactory">below documentation</a> for more details.</td>
            </tr>
          </table>
          <p>
            There are also a few system properties that can be used to maintain application throughput even when
            the underlying appender cannot keep up with the logging rate and the queue is filling up.
            See the details for system properties
            <a href="configuration.html#log4j2.AsyncQueueFullPolicy"><tt>log4j2.AsyncQueueFullPolicy</tt> and
              <tt>log4j2.DiscardThreshold</tt></a>.
          </p>
          <p>
            A typical AsyncAppender configuration might look like:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <File name="MyFile" fileName="logs/app.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </File>
    <Async name="Async">
      <AppenderRef ref="MyFile"/>
    </Async>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Async"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            <a name="BlockingQueueFactory"/>
            Starting in Log4j 2.7, a custom implementation of <tt>BlockingQueue</tt> or <tt>TransferQueue</tt> can be
            specified using a
            <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/async/BlockingQueueFactory.html">BlockingQueueFactory</a>
            plugin. To override the default <tt>BlockingQueueFactory</tt>, specify the plugin inside an
            <code><![CDATA[<Async/>]]></code> element like so:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<Configuration name="LinkedTransferQueueExample">
  <Appenders>
    <List name="List"/>
    <Async name="Async" bufferSize="262144">
      <AppenderRef ref="List"/>
      <LinkedTransferQueue/>
    </Async>
  </Appenders>
  <Loggers>
    <Root>
      <AppenderRef ref="Async"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            Log4j ships with the following implementations:
          </p>
          <table>
            <caption align="top">BlockingQueueFactory Implementations</caption>
            <tr>
              <th>Plugin Name</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>ArrayBlockingQueue</td>
              <td>
                This is the default implementation that uses
                <a class="javadoc" href="https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ArrayBlockingQueue.html">ArrayBlockingQueue</a>.
              </td>
            </tr>
            <tr>
              <td>DisruptorBlockingQueue</td>
              <td>
                This uses the <a href="https://github.com/conversant/disruptor">Conversant Disruptor</a> implementation
                of <tt>BlockingQueue</tt>. This plugin takes a single optional attribute, <tt>spinPolicy</tt>, which
                corresponds to
                <!-- TODO: this needs performance charts and links added -->
              </td>
            </tr>
            <tr>
              <td>JCToolsBlockingQueue</td>
              <td>
                This uses <a href="https://jctools.github.io/JCTools/">JCTools</a>, specifically the
                <abbr title="multiple producer single consumer">MPSC</abbr> bounded lock-free queue.
                <!-- TODO: this need performance charts and links added -->
              </td>
            </tr>
            <tr>
              <td>LinkedTransferQueue</td>
              <td>
                This uses the new in Java 7 implementation
                <a class="javadoc" href="https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedTransferQueue.html">LinkedTransferQueue</a>.
                Note that this queue does not use the <tt>bufferSize</tt> configuration attribute from AsyncAppender as
                <tt>LinkedTransferQueue</tt> does not support a maximum capacity.
                <!-- TODO: this needs performance charts and links added -->
              </td>
            </tr>
          </table>
        </subsection>
        <a name="CassandraAppender"/>
        <subsection name="CassandraAppender">
          <p>
            The CassandraAppender writes its output to an <a href="https://cassandra.apache.org/">Apache Cassandra</a>
            database. A keyspace and table must be configured ahead of time, and the columns of that table are mapped
            in a configuration file. Each column can specify either a <a href="layouts.html">StringLayout</a> (e.g., a
            <a href="layouts.html#PatternLayout">PatternLayout</a>) along with an optional conversion type, or only
            a conversion type for <code>org.apache.logging.log4j.spi.ThreadContextMap</code> or
            <code>org.apache.logging.log4j.spi.ThreadContextStack</code> to store the <a href="thread-context.html">MDC or NDC</a>
            in a map or list column respectively. A conversion type compatible with <code>java.util.Date</code> will
            use the log event timestamp converted to that type (e.g., use <code>java.util.Date</code> to fill a
            <code>timestamp</code> column type in Cassandra).
          </p>
          <table>
            <caption align="top">CassandraAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>batched</td>
              <td>boolean</td>
              <td>Whether or not to use batch statements to write log messages to Cassandra. By default, this is <code>false</code>.</td>
            </tr>
            <tr>
              <td>batchType</td>
              <td><a href="http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/BatchStatement.Type.html">BatchStatement.Type</a></td>
              <td>The batch type to use when using batched writes. By default, this is <code>LOGGED</code>.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>int</td>
              <td>The number of log messages to buffer or batch before writing. By default, no buffering is done.</td>
            </tr>
            <tr>
              <td>clusterName</td>
              <td>String</td>
              <td>The name of the Cassandra cluster to connect to.</td>
            </tr>
            <tr>
              <td>columns</td>
              <td>ColumnMapping[]</td>
              <td>A list of column mapping configurations. Each column must specify a column name. Each column can
                have a conversion type specified by its fully qualified class name. By default, the conversion type is
                <code>String</code>. If the configured type is assignment-compatible with
                <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/util/ReadOnlyStringMap.html">ReadOnlyStringMap</a>
                /
                <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/spi/ThreadContextMap.html">ThreadContextMap</a>
                or
                <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/spi/ThreadContextStack.html">ThreadContextStack</a>,
                then that column will be populated with the MDC or NDC respectively. If the configured type is
                assignment-compatible with <code>java.util.Date</code>, then the log timestamp will be converted to
                that configured date type. If a <code>literal</code> attribute is given, then its value will be used as
                is in the <code>INSERT</code> query without any escaping. Otherwise, the layout or pattern specified
                will be converted into the configured type and stored in that column.
              </td>
            </tr>
            <tr>
              <td>contactPoints</td>
              <td>SocketAddress[]</td>
              <td>A list of hosts and ports of Cassandra nodes to connect to. These must be valid hostnames or IP
                addresses. By default, if a port is not specified for a host or it is set to 0, then the default
                Cassandra port of 9042 will be used. By default, <code>localhost:9042</code> will be used.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter may be used
                by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>keyspace</td>
              <td>String</td>
              <td>The name of the keyspace containing the table that log messages will be written to.</td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>password</td>
              <td>String</td>
              <td>The password to use (along with the username) to connect to Cassandra.</td>
            </tr>
            <tr>
              <td>table</td>
              <td>String</td>
              <td>The name of the table to write log messages to.</td>
            </tr>
            <tr>
              <td>useClockForTimestampGenerator</td>
              <td>boolean</td>
              <td>Whether or not to use the configured <code>org.apache.logging.log4j.core.util.Clock</code> as a
                <a class="javadoc" href="http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/TimestampGenerator.html">TimestampGenerator</a>.
                By default, this is <code>false</code>.</td>
            </tr>
            <tr>
              <td>username</td>
              <td>String</td>
              <td>The username to use to connect to Cassandra. By default, no username or password is used.</td>
            </tr>
            <tr>
              <td>useTls</td>
              <td>boolean</td>
              <td>Whether or not to use TLS/SSL to connect to Cassandra. This is <code>false</code> by default.</td>
            </tr>
          </table>
          <p>
            Here is an example CassandraAppender configuration:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<Configuration name="CassandraAppenderTest">
  <Appenders>
    <Cassandra name="Cassandra" clusterName="Test Cluster" keyspace="test" table="logs" bufferSize="10" batched="true">
      <SocketAddress host="localhost" port="9042"/>
      <ColumnMapping name="id" pattern="%uuid{TIME}" type="java.util.UUID"/>
      <ColumnMapping name="timeid" literal="now()"/>
      <ColumnMapping name="message" pattern="%message"/>
      <ColumnMapping name="level" pattern="%level"/>
      <ColumnMapping name="marker" pattern="%marker"/>
      <ColumnMapping name="logger" pattern="%logger"/>
      <ColumnMapping name="timestamp" type="java.util.Date"/>
      <ColumnMapping name="mdc" type="org.apache.logging.log4j.spi.ThreadContextMap"/>
      <ColumnMapping name="ndc" type="org.apache.logging.log4j.spi.ThreadContextStack"/>
    </Cassandra>
  </Appenders>
  <Loggers>
    <Logger name="org.apache.logging.log4j.nosql.appender.cassandra" level="DEBUG">
      <AppenderRef ref="Cassandra"/>
    </Logger>
    <Root level="ERROR"/>
  </Loggers>
</Configuration>
]]></pre>
          <p>
            This example configuration uses the following table schema:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
CREATE TABLE logs (
    id timeuuid PRIMARY KEY,
    timeid timeuuid,
    message text,
    level text,
    marker text,
    logger text,
    timestamp timestamp,
    mdc map<text,text>,
    ndc list<text>
);
]]></pre>
        </subsection>
        <a name="ConsoleAppender"/>
        <subsection name="ConsoleAppender">
          <p>
            As one might expect, the ConsoleAppender writes its output to either System.out or System.err with System.out
            being the default target. A Layout must be provided to format the LogEvent.
          </p>
          <table>
            <caption align="top">ConsoleAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>The Layout to use to format the LogEvent. If no layout is supplied the default pattern layout
              of "%m%n" will be used.</td>
            </tr>
            <tr>
              <td>follow</td>
              <td>boolean</td>
              <td>Identifies whether the appender honors reassignments of System.out or System.err
                via System.setOut or System.setErr made after configuration. Note that the follow
                attribute cannot be used with Jansi on Windows. Cannot be used with <code>direct</code>.</td>
            </tr>
            <tr>
              <td>direct</td>
              <td>boolean</td>
              <td>Write directly to <code>java.io.FileDescriptor</code> and bypass <code>java.lang.System.out/.err</code>.
                Can give up to 10x performance boost when the output is redirected to file or other process.
                Cannot be used with Jansi on Windows. Cannot be used with <code>follow</code>. Output will not respect
                <code>java.lang.System.setOut()/.setErr()</code> and may get intertwined with other output to
                <code>java.lang.System.out/.err</code> in a multi-threaded application.
                <i>New since 2.6.2. Be aware that this is a new addition, and it has only been tested with Oracle JVM
                  on Linux and Windows so far.</i></td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>target</td>
              <td>String</td>
              <td>Either "SYSTEM_OUT" or "SYSTEM_ERR". The default is "SYSTEM_OUT".</td>
            </tr>
          </table>
          <p>
            A typical Console configuration might look like:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT">
      <PatternLayout pattern="%m%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="FailoverAppender"/>
        <subsection name="FailoverAppender">
          <p>The FailoverAppender wraps a set of appenders. If the primary Appender fails the secondary appenders will be
          tried in order until one succeeds or there are no more secondaries to try.</p>
          <table>
            <caption align="top">FailoverAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>primary</td>
              <td>String</td>
              <td>The name of the primary Appender to use.</td>
            </tr>
            <tr>
              <td>failovers</td>
              <td>String[]</td>
              <td>The names of the secondary Appenders to use.</td>
            </tr>

            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>retryIntervalSeconds</td>
              <td>integer</td>
              <td>The number of seconds that should pass before retrying the primary Appender. The default is 60.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead.</td>
            </tr>
            <tr>
              <td>target</td>
              <td>String</td>
              <td>Either "SYSTEM_OUT" or "SYSTEM_ERR". The default is "SYSTEM_ERR".</td>
            </tr>
          </table>
          <p>
            A Failover configuration might look like:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/app-%d{MM-dd-yyyy}.log.gz"
                 ignoreExceptions="false">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
    <Console name="STDOUT" target="SYSTEM_OUT" ignoreExceptions="false">
      <PatternLayout pattern="%m%n"/>
    </Console>
    <Failover name="Failover" primary="RollingFile">
      <Failovers>
        <AppenderRef ref="Console"/>
      </Failovers>
    </Failover>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Failover"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="FileAppender"/>
        <subsection name="FileAppender">
          <p>The FileAppender is an OutputStreamAppender that writes to the File named in the fileName parameter. The
            FileAppender uses a FileManager (which extends OutputStreamManager) to actually perform the file I/O. While
            FileAppenders from different Configurations cannot be shared, the FileManagers can be if the Manager is
            accessible. For example, two web applications in a servlet container can have their own configuration and
            safely write to the same file if Log4j is in a ClassLoader that is common to both of them.</p>
          <table>
            <caption align="top">FileAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>append</td>
              <td>boolean</td>
              <td>When true - the default, records will be appended to the end of the file. When set to false,
                the file will be cleared before new records are written.</td>
            </tr>
            <tr>
              <td>bufferedIO</td>
              <td>boolean</td>
              <td>When true - the default, records will be written to a buffer and the data will be written to
                disk when the buffer is full or, if immediateFlush is set, when the record is written.
                File locking cannot be used with bufferedIO. Performance tests have shown that using buffered I/O
                significantly improves performance, even if immediateFlush is enabled.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>int</td>
              <td>When bufferedIO is true, this is the buffer size, the default is 8192 bytes.</td>
            </tr>
            <tr>
              <td>createOnDemand</td>
              <td>boolean</td>
              <td>The appender creates the file on-demand. The appender only creates the file when a log event
                passes all filters and is routed to this appender. Defaults to false.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>fileName</td>
              <td>String</td>
              <td>The name of the file to write to. If the file, or any of its parent directories, do not exist,
                they will be created.</td>
            </tr>
            <tr>
              <td>immediateFlush</td>
              <td>boolean</td>
              <td><p>When set to true - the default, each write will be followed by a flush.
                This will guarantee the data is written
                to disk but could impact performance.</p>
                <p>Flushing after every write is only useful when using this
				appender with synchronous loggers. Asynchronous loggers and
				appenders will automatically flush at the end of a batch of events,
				even if immediateFlush is set to false. This also guarantees
				the data is written to disk but is more efficient.</p>
              </td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>The Layout to use to format the LogEvent. If no layout is supplied the default pattern layout
                of "%m%n" will be used.</td>
            </tr>
            <tr>
              <td>locking</td>
              <td>boolean</td>
              <td>When set to true, I/O operations will occur only while the file lock is held allowing FileAppenders
                in multiple JVMs and potentially multiple hosts to write to the same file simultaneously. This
                will significantly impact performance so should be used carefully. Furthermore, on many systems
                the file lock is "advisory" meaning that other applications can perform operations on the file
                without acquiring a lock. The default value is false.</td>
            </tr>

            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
          </table>
          <p>
            Here is a sample File configuration:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <File name="MyFile" fileName="logs/app.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </File>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="MyFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="FlumeAppender"/>
        <subsection name="FlumeAppender">
          <p><i>This is an optional component supplied in a separate jar.</i></p>
          <p><a href="http://flume.apache.org/index.html">Apache Flume</a> is a distributed, reliable,
            and available system for efficiently collecting, aggregating, and moving large amounts of log data
            from many different sources to a centralized data store. The FlumeAppender takes LogEvents and sends
            them to a Flume agent as serialized Avro events for consumption.</p>
          <p>
            The Flume Appender supports three modes of operation.
          </p>
            <ol>
              <li>It can act as a remote Flume client which sends Flume events via Avro to a Flume Agent configured
              with an Avro Source.</li>
              <li>It can act as an embedded Flume Agent where Flume events pass directly into Flume for processing.</li>
              <li>It can persist events to a local BerkeleyDB data store and then asynchronously send the events to
              Flume, similar to the embedded Flume Agent but without most of the Flume dependencies.</li>
            </ol>
          <p>
            Usage as an embedded agent will cause the messages to be directly passed to the Flume Channel and then
            control will be immediately returned to the application. All interaction with remote agents will occur
            asynchronously. Setting the "type" attribute to "Embedded" will force the use of the embedded agent. In
            addition, configuring agent properties in the appender configuration will also cause the embedded agent
            to be used.
          </p>
          <table>
            <caption align="top">FlumeAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>agents</td>
              <td>Agent[]</td>
              <td>An array of Agents to which the logging events should be sent. If more than one agent is specified
                the first Agent will be the primary and subsequent Agents will be used in the order specified as
                secondaries should the primary Agent fail. Each Agent definition supplies the Agents host and port.
                The specification of agents and properties are mutually exclusive. If both are configured an
                error will result.</td>
            </tr>
            <tr>
              <td>agentRetries</td>
              <td>integer</td>
              <td>The number of times the agent should be retried before failing to a secondary. This parameter is
                ignored when type="persistent" is specified (agents are tried once before failing to the next).</td>
            </tr>
            <tr>
              <td>batchSize</td>
              <td>integer</td>
              <td>Specifies the number of events that should be sent as a batch. The default is 1. <i>This
                parameter only applies to the Flume Appender.</i></td>
            </tr>
            <tr>
              <td>compress</td>
              <td>boolean</td>
              <td>When set to true the message body will be compressed using gzip</td>
            </tr>
            <tr>
              <td>connectTimeoutMillis</td>
              <td>integer</td>
              <td>The number of milliseconds Flume will wait before timing out the connection.</td>
            </tr>
            <tr>
              <td>dataDir</td>
              <td>String</td>
              <td>Directory where the Flume write ahead log should be written. Valid only when embedded is set
                to true and Agent elements are used instead of Property elements.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>eventPrefix</td>
              <td>String</td>
              <td>The character string to prepend to each event attribute in order to distinguish it from MDC attributes.
                The default is an empty string.</td>
            </tr>
            <tr>
              <td>flumeEventFactory</td>
              <td>FlumeEventFactory</td>
              <td>Factory that generates the Flume events from Log4j events. The default factory is the
                FlumeAvroAppender itself.</td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>The Layout to use to format the LogEvent. If no layout is specified RFC5424Layout will be used.</td>
            </tr>
            <tr>
              <td>lockTimeoutRetries</td>
              <td>integer</td>
              <td>The number of times to retry if a LockConflictException occurs while writing to Berkeley DB. The
                default is 5.</td>
            </tr>
            <tr>
              <td>maxDelayMillis</td>
              <td>integer</td>
              <td>The maximum number of milliseconds to wait for batchSize events before publishing the batch.</td>
            </tr>
            <tr>
              <td>mdcExcludes</td>
              <td>String</td>
              <td>A comma separated list of mdc keys that should be excluded from the FlumeEvent. This is mutually
                exclusive with the mdcIncludes attribute.</td>
            </tr>
            <tr>
              <td>mdcIncludes</td>
              <td>String</td>
              <td>A comma separated list of mdc keys that should be included in the FlumeEvent. Any keys in the MDC
                not found in the list will be excluded. This option is mutually exclusive with the mdcExcludes
                attribute.</td>
            </tr>
            <tr>
              <td>mdcRequired</td>
              <td>String</td>
              <td>A comma separated list of mdc keys that must be present in the MDC. If a key is not present a
                LoggingException will be thrown.</td>
            </tr>
            <tr>
              <td>mdcPrefix</td>
              <td>String</td>
              <td>A string that should be prepended to each MDC key in order to distinguish it from event attributes.
                The default string is "mdc:".</td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>properties</td>
              <td>Property[]</td>
              <td><p>One or more Property elements that are used to configure the Flume Agent. The properties must be
                configured without the agent name (the appender name is used for this) and no sources can be
                configured. Interceptors can be specified for the source using "sources.log4j-source.interceptors".
                All other Flume configuration properties are allowed. Specifying both Agent and Property
                elements will result in an error.</p>
                <p>When used to configure in Persistent mode the valid properties are:</p>
                <ol>
                  <li>"keyProvider" to specify the name of the plugin to provide the secret key for encryption.</li>
                </ol>
              </td>
            </tr>
            <tr>
              <td>requestTimeoutMillis</td>
              <td>integer</td>
              <td>The number of milliseconds Flume will wait before timing out the request.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>type</td>
              <td>enumeration</td>
              <td>One of "Avro", "Embedded", or "Persistent" to indicate which variation of the Appender is desired.</td>
            </tr>
          </table>
            <p>
              A sample FlumeAppender configuration that is configured with a primary and a secondary agent,
              compresses the body, and formats the body using the RFC5424Layout:
            </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Flume name="eventLogger" compress="true">
      <Agent host="192.168.10.101" port="8800"/>
      <Agent host="192.168.10.102" port="8800"/>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
    </Flume>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="eventLogger"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            A sample FlumeAppender configuration that is configured with a primary and a secondary agent,
            compresses the body, formats the body using the RFC5424Layout, and persists encrypted events to disk:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Flume name="eventLogger" compress="true" type="persistent" dataDir="./logData">
      <Agent host="192.168.10.101" port="8800"/>
      <Agent host="192.168.10.102" port="8800"/>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
      <Property name="keyProvider">MySecretProvider</Property>
    </Flume>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="eventLogger"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            A sample FlumeAppender configuration that is configured with a primary and a secondary agent,
            compresses the body, formats the body using RFC5424Layout and passes the events to an embedded Flume
            Agent.
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Flume name="eventLogger" compress="true" type="Embedded">
      <Agent host="192.168.10.101" port="8800"/>
      <Agent host="192.168.10.102" port="8800"/>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
    </Flume>
    <Console name="STDOUT">
      <PatternLayout pattern="%d [%p] %c %m%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="EventLogger" level="info">
      <AppenderRef ref="eventLogger"/>
    </Logger>
    <Root level="warn">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            A sample FlumeAppender configuration that is configured with a primary and a secondary agent using
            Flume configuration properties, compresses the body, formats the body using RFC5424Layout and passes the
            events to an embedded Flume Agent.
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" name="MyApp" packages="">
  <Appenders>
    <Flume name="eventLogger" compress="true" type="Embedded">
      <Property name="channels">file</Property>
      <Property name="channels.file.type">file</Property>
      <Property name="channels.file.checkpointDir">target/file-channel/checkpoint</Property>
      <Property name="channels.file.dataDirs">target/file-channel/data</Property>
      <Property name="sinks">agent1 agent2</Property>
      <Property name="sinks.agent1.channel">file</Property>
      <Property name="sinks.agent1.type">avro</Property>
      <Property name="sinks.agent1.hostname">192.168.10.101</Property>
      <Property name="sinks.agent1.port">8800</Property>
      <Property name="sinks.agent1.batch-size">100</Property>
      <Property name="sinks.agent2.channel">file</Property>
      <Property name="sinks.agent2.type">avro</Property>
      <Property name="sinks.agent2.hostname">192.168.10.102</Property>
      <Property name="sinks.agent2.port">8800</Property>
      <Property name="sinks.agent2.batch-size">100</Property>
      <Property name="sinkgroups">group1</Property>
      <Property name="sinkgroups.group1.sinks">agent1 agent2</Property>
      <Property name="sinkgroups.group1.processor.type">failover</Property>
      <Property name="sinkgroups.group1.processor.priority.agent1">10</Property>
      <Property name="sinkgroups.group1.processor.priority.agent2">5</Property>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
    </Flume>
    <Console name="STDOUT">
      <PatternLayout pattern="%d [%p] %c %m%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="EventLogger" level="info">
      <AppenderRef ref="eventLogger"/>
    </Logger>
    <Root level="warn">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="JDBCAppender"/>
        <subsection name="JDBCAppender">
          <p>The JDBCAppender writes log events to a relational database table using standard JDBC. It can be configured
            to obtain JDBC connections using a JNDI <code>DataSource</code> or a custom factory method. Whichever
            approach you take, it <strong><em>must</em></strong> be backed by a connection pool. Otherwise, logging
            performance will suffer greatly. If batch statements are supported by the configured JDBC driver and a
            <code>bufferSize</code> is configured to be a positive number, then log events will be batched. Note that as
            of Log4j 2.8, there are two ways to configure log event to column mappings: the original <code>ColumnConfig</code>
            style that only allows strings and timestamps, and the new <code>ColumnMapping</code> plugin that uses Log4j's
            built-in type conversion to allow for more data types (this is the same plugin as in the
            <a href="#CassandraAppender">Cassandra Appender</a>).</p>
          <table>
            <caption align="top">JDBCAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td><em>Required.</em> The name of the Appender.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter may be
                used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>int</td>
              <td>If an integer greater than 0, this causes the appender to buffer log events and flush whenever the
                buffer reaches this size.</td>
            </tr>
            <tr>
              <td>connectionSource</td>
              <td>ConnectionSource</td>
              <td><em>Required.</em> The connections source from which database connections should be retrieved.</td>
            </tr>
            <tr>
              <td>tableName</td>
              <td>String</td>
              <td><em>Required.</em> The name of the database table to insert log events into.</td>
            </tr>
            <tr>
              <td>columnConfigs</td>
              <td>ColumnConfig[]</td>
              <td><em>Required (and/or columnMappings).</em> Information about the columns that log event data should be inserted into and how
                to insert that data. This is represented with multiple <code>&lt;Column&gt;</code> elements.</td>
            </tr>
            <tr>
              <td>columnMappings</td>
              <td>ColumnMapping[]</td>
              <td><em>Required (and/or columnConfigs).</em> A list of column mapping configurations. Each column must
                specify a column name. Each column can have a conversion type specified by its fully qualified class
                name. By default, the conversion type is <code>String</code>. If the configured type is
                assignment-compatible with
                <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/util/ReadOnlyStringMap.html">ReadOnlyStringMap</a>
                /
                <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/spi/ThreadContextMap.html">ThreadContextMap</a>
                or
                <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/spi/ThreadContextStack.html">ThreadContextStack</a>,
                then that column will be populated with the MDC or NDC respectively (this is database-specific how they
                handle inserting a <code>Map</code> or <code>List</code> value). If the configured type is
                assignment-compatible with <code>java.util.Date</code>, then the log timestamp will be converted to
                that configured date type. If the configured type is assignment-compatible with <code>java.sql.Clob</code>
                or <code>java.sql.NClob</code>, then the formatted event will be set as a Clob or NClob respectively
                (similar to the traditional ColumnConfig plugin). If a <code>literal</code> attribute is given, then its
                value will be used as is in the <code>INSERT</code> query without any escaping. Otherwise, the layout or
                pattern specified will be converted into the configured type and stored in that column.
              </td>
            </tr>
          </table>
          <p>When configuring the JDBCAppender, you must specify a <code>ConnectionSource</code> implementation from
            which the Appender gets JDBC connections. You must use exactly one of the <code>&lt;DataSource&gt;</code>
            or <code>&lt;ConnectionFactory&gt;</code> nested elements.</p>
          <table>
            <caption align="top">DataSource Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>jndiName</td>
              <td>String</td>
              <td><em>Required.</em> The full, prefixed JNDI name that the <code>javax.sql.DataSource</code> is bound
                to, such as <code>java:/comp/env/jdbc/LoggingDatabase</code>. The <code>DataSource</code> must be backed
                by a connection pool; otherwise, logging will be very slow.</td>
            </tr>
          </table>
          <table>
            <caption align="top">ConnectionFactory Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>class</td>
              <td>Class</td>
              <td><em>Required.</em> The fully qualified name of a class containing a static factory method for
                obtaining JDBC connections.</td>
            </tr>
            <tr>
              <td>method</td>
              <td>Method</td>
              <td><em>Required.</em> The name of a static factory method for obtaining JDBC connections. This method
                must have no parameters and its return type must be either <code>java.sql.Connection</code> or
                <code>DataSource</code>. If the method returns <code>Connection</code>s, it must obtain them from a
                connection pool (and they will be returned to the pool when Log4j is done with them); otherwise, logging
                will be very slow. If the method returns a <code>DataSource</code>, the <code>DataSource</code> will
                only be retrieved once, and it must be backed by a connection pool for the same reasons.</td>
            </tr>
          </table>
          <p>When configuring the JDBCAppender, use the nested <code>&lt;Column&gt;</code> elements to specify which
            columns in the table should be written to and how to write to them. The JDBCAppender uses this information
            to formulate a <code>PreparedStatement</code> to insert records without SQL injection vulnerability.</p>
          <table>
            <caption align="top">Column Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td><em>Required.</em> The name of the database column.</td>
            </tr>
            <tr>
              <td>pattern</td>
              <td>String</td>
              <td>Use this attribute to insert a value or values from the log event in this column using a
                <code>PatternLayout</code> pattern. Simply specify any legal pattern in this attribute. Either this
                attribute, <code>literal</code>, or <code>isEventTimestamp="true"</code> must be specified, but not more
                than one of these.</td>
            </tr>
            <tr>
              <td>literal</td>
              <td>String</td>
              <td>Use this attribute to insert a literal value in this column. The value will be included directly in
                the insert SQL, without any quoting (which means that if you want this to be a string, your value should
                contain single quotes around it like this: <code>literal="'Literal String'"</code>). This is especially
                useful for databases that don't support identity columns. For example, if you are using Oracle you could
                specify <code>literal="NAME_OF_YOUR_SEQUENCE.NEXTVAL"</code> to insert a unique ID in an ID column.
                Either this attribute, <code>pattern</code>, or <code>isEventTimestamp="true"</code> must be specified,
                but not more than one of these.</td>
            </tr>
            <tr>
              <td>isEventTimestamp</td>
              <td>boolean</td>
              <td>Use this attribute to insert the event timestamp in this column, which should be a SQL datetime. The
                value will be inserted as a <code>java.sql.Types.TIMESTAMP</code>. Either this attribute (equal to
                <code>true</code>), <code>pattern</code>, or <code>isEventTimestamp</code> must be specified, but not
                more than one of these.</td>
            </tr>
            <tr>
              <td>isUnicode</td>
              <td>boolean</td>
              <td>This attribute is ignored unless <code>pattern</code> is specified. If <code>true</code> or omitted
                (default), the value will be inserted as unicode (<code>setNString</code> or <code>setNClob</code>).
                Otherwise, the value will be inserted non-unicode (<code>setString</code> or <code>setClob</code>).</td>
            </tr>
            <tr>
              <td>isClob</td>
              <td>boolean</td>
              <td>This attribute is ignored unless <code>pattern</code> is specified. Use this attribute to indicate
                that the column stores Character Large Objects (CLOBs). If <code>true</code>, the value will be inserted
                as a CLOB (<code>setClob</code> or <code>setNClob</code>). If <code>false</code> or omitted (default),
                the value will be inserted as a VARCHAR or NVARCHAR (<code>setString</code> or <code>setNString</code>).
              </td>
            </tr>
          </table>
          <p>
            Here are a couple sample configurations for the JDBCAppender, as well as a sample factory implementation
            that uses Commons Pooling and Commons DBCP to pool database connections:
          </p>

            <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <JDBC name="databaseAppender" tableName="dbo.application_log">
      <DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" />
      <Column name="eventDate" isEventTimestamp="true" />
      <Column name="level" pattern="%level" />
      <Column name="logger" pattern="%logger" />
      <Column name="message" pattern="%message" />
      <Column name="exception" pattern="%ex{full}" />
    </JDBC>
  </Appenders>
  <Loggers>
    <Root level="warn">
      <AppenderRef ref="databaseAppender"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>

            <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <JDBC name="databaseAppender" tableName="LOGGING.APPLICATION_LOG">
      <ConnectionFactory class="net.example.db.ConnectionFactory" method="getDatabaseConnection" />
      <Column name="EVENT_ID" literal="LOGGING.APPLICATION_LOG_SEQUENCE.NEXTVAL" />
      <Column name="EVENT_DATE" isEventTimestamp="true" />
      <Column name="LEVEL" pattern="%level" />
      <Column name="LOGGER" pattern="%logger" />
      <Column name="MESSAGE" pattern="%message" />
      <Column name="THROWABLE" pattern="%ex{full}" />
    </JDBC>
  </Appenders>
  <Loggers>
    <Root level="warn">
      <AppenderRef ref="databaseAppender"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
            <pre class="prettyprint linenums lang-java"><![CDATA[package net.example.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;

public class ConnectionFactory {
    private static interface Singleton {
        final ConnectionFactory INSTANCE = new ConnectionFactory();
    }

    private final DataSource dataSource;

    private ConnectionFactory() {
        Properties properties = new Properties();
        properties.setProperty("user", "logging");
        properties.setProperty("password", "abc123"); // or get properties from some configuration file

        GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<PoolableConnection>();
        DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
                "jdbc:mysql://example.org:3306/exampleDb", properties
        );
        new PoolableConnectionFactory(
                connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED
        );

        this.dataSource = new PoolingDataSource(pool);
    }

    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }
}]]></pre>
        </subsection>
        <a name="JMSAppender"/>
        <!-- cool URLs don't change, so here are some old anchors -->
        <a name="JMSQueueAppender"/>
        <a name="JMSTopicAppender"/>
        <subsection name="JMSAppender">
          <p>The JMSAppender sends the formatted log event to a JMS Destination.</p>
          <p>
            Note that in Log4j 2.0, this appender was split into a JMSQueueAppender and a JMSTopicAppender. Starting
            in Log4j 2.1, these appenders were combined into the JMSAppender which makes no distinction between queues
            and topics. However, configurations written for 2.0 which use the <code>&lt;JMSQueue/&gt;</code> or
            <code>&lt;JMSTopic/&gt;</code> elements will continue to work with the new <code>&lt;JMS/&gt;</code>
            configuration element.
          </p>
          <table>
            <caption align="top">JMSAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>factoryBindingName</td>
              <td>String</td>
              <td>The name to locate in the Context that provides the
                <a class="javadoc" href="http://download.oracle.com/javaee/5/api/javax/jms/ConnectionFactory.html">ConnectionFactory</a>.
                This can be any subinterface of <code>ConnectionFactory</code> as well. This attribute is required.
              </td>
            </tr>
            <tr>
              <td>factoryName</td>
              <td>String</td>
              <td>The fully qualified class name that should be used to define the Initial Context Factory as defined in
                <a class="javadoc" href="http://download.oracle.com/javase/6/docs/api/javax/naming/Context.html#INITIAL_CONTEXT_FACTORY">INITIAL_CONTEXT_FACTORY</a>.
                If no value is provided the
                default InitialContextFactory will be used. If a factoryName is specified without a providerURL
                a warning message will be logged as this is likely to cause problems.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>
                The Layout to use to format the LogEvent. If you do not specify a layout,
                this appender will use a <a href="layouts.html#SerializedLayout">SerializedLayout</a>.
              </td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender. Required.</td>
            </tr>
            <tr>
              <td>password</td>
              <td>String</td>
              <td>The password to use to create the JMS connection.</td>
            </tr>
            <tr>
              <td>providerURL</td>
              <td>String</td>
              <td>The URL of the provider to use as defined by
                <a class="javadoc" href="http://download.oracle.com/javase/6/docs/api/javax/naming/Context.html#PROVIDER_URL">PROVIDER_URL</a>.
                If this value is null the default system provider will be used.</td>
            </tr>
            <tr>
              <td>destinationBindingName</td>
              <td>String</td>
              <td>
                The name to use to locate the
                <a class="javadoc" href="http://download.oracle.com/javaee/5/api/javax/jms/Destination.html">Destination</a>.
                This can be a <code>Queue</code> or <code>Topic</code>, and as such, the attribute names
                <code>queueBindingName</code> and <code>topicBindingName</code> are aliases to maintain compatibility
                with the Log4j 2.0 JMS appenders.
              </td>
            </tr>
            <tr>
              <td>securityPrincipalName</td>
              <td>String</td>
              <td>The name of the identity of the Principal as specified by
                <a class="javadoc" href="http://download.oracle.com/javase/6/docs/api/javax/naming/Context.html#SECURITY_PRINCIPAL">SECURITY_PRINCIPAL</a>.
                If a securityPrincipalName is specified without securityCredentials a warning message will be
                logged as this is likely to cause problems.</td>
            </tr>
            <tr>
              <td>securityCredentials</td>
              <td>String</td>
              <td>The security credentials for the principal as specified by
                <a class="javadoc" href="http://download.oracle.com/javase/6/docs/api/javax/naming/Context.html#SECURITY_CREDENTIALS">SECURITY_CREDENTIALS</a>.
              </td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>urlPkgPrefixes</td>
              <td>String</td>
              <td>A colon-separated list of package prefixes for the class name of the factory class that will create
                a URL context factory as defined by
                <a class="javadoc" href="http://download.oracle.com/javase/6/docs/api/javax/naming/Context.html#URL_PKG_PREFIXES">URL_PKG_PREFIXES</a>.
              </td>
            </tr>
            <tr>
              <td>userName</td>
              <td>String</td>
              <td>The user id used to create the JMS connection.</td>
            </tr>
          </table>
          <p>
            Here is a sample JMSAppender configuration:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp">
  <Appenders>
    <JMS name="jmsQueue" destinationBindingName="MyQueue"
         factoryBindingName="MyQueueConnectionFactory"/>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="jmsQueue"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="JPAAppender"/>
        <subsection name="JPAAppender">
          <p>The JPAAppender writes log events to a relational database table using the Java Persistence API 2.1.
            It requires the API and a provider implementation be on the classpath. It also requires a decorated entity
            configured to persist to the table desired. The entity should either extend
            <code>org.apache.logging.log4j.core.appender.db.jpa.BasicLogEventEntity</code> (if you mostly want to
            use the default mappings) and provide at least an <code>@Id</code> property, or
            <code>org.apache.logging.log4j.core.appender.db.jpa.AbstractLogEventWrapperEntity</code> (if you want
            to significantly customize the mappings). See the Javadoc for these two classes for more information. You
            can also consult the source code of these two classes as an example of how to implement the entity.</p>
          <table>
            <caption align="top">JPAAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td><em>Required.</em> The name of the Appender.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter may be
                used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>int</td>
              <td>If an integer greater than 0, this causes the appender to buffer log events and flush whenever the
                buffer reaches this size.</td>
            </tr>
            <tr>
              <td>entityClassName</td>
              <td>String</td>
              <td><em>Required.</em> The fully qualified name of the concrete LogEventWrapperEntity implementation that
                has JPA annotations mapping it to a database table.</td>
            </tr>
            <tr>
              <td>persistenceUnitName</td>
              <td>String</td>
              <td><em>Required.</em> The name of the JPA persistence unit that should be used for persisting log
                events.</td>
            </tr>
          </table>
          <p>
            Here is a sample configuration for the JPAAppender. The first XML sample is the Log4j configuration file,
            the second is the <code>persistence.xml</code> file. EclipseLink is assumed here, but any JPA 2.1 or higher
            provider will do. You should <em>always</em> create a <em>separate</em> persistence unit for logging, for
            two reasons. First, <code>&lt;shared-cache-mode&gt;</code> <em>must</em> be set to "NONE," which is usually
            not desired in normal JPA usage. Also, for performance reasons the logging entity should be isolated in its
            own persistence unit away from all other entities and you should use a non-JTA data source. Note that your
            persistence unit <em>must</em> also contain <code>&lt;class&gt;</code> elements for all of the
            <code>org.apache.logging.log4j.core.appender.db.jpa.converter</code> converter classes.
          </p>

            <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <JPA name="databaseAppender" persistenceUnitName="loggingPersistenceUnit"
         entityClassName="com.example.logging.JpaLogEntity" />
  </Appenders>
  <Loggers>
    <Root level="warn">
      <AppenderRef ref="databaseAppender"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>

            <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
                                 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">

  <persistence-unit name="loggingPersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapAttributeConverter</class>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter</class>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackAttributeConverter</class>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter</class>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.MarkerAttributeConverter</class>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.MessageAttributeConverter</class>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.StackTraceElementAttributeConverter</class>
    <class>org.apache.logging.log4j.core.appender.db.jpa.converter.ThrowableAttributeConverter</class>
    <class>com.example.logging.JpaLogEntity</class>
    <non-jta-data-source>jdbc/LoggingDataSource</non-jta-data-source>
    <shared-cache-mode>NONE</shared-cache-mode>
  </persistence-unit>

</persistence>]]></pre>

            <pre class="prettyprint linenums lang-java"><![CDATA[package com.example.logging;
...
@Entity
@Table(name="application_log", schema="dbo")
public class JpaLogEntity extends BasicLogEventEntity {
    private static final long serialVersionUID = 1L;
    private long id = 0L;

    public TestEntity() {
        super(null);
    }
    public TestEntity(LogEvent wrappedEvent) {
        super(wrappedEvent);
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    // If you want to override the mapping of any properties mapped in BasicLogEventEntity,
    // just override the getters and re-specify the annotations.
}]]></pre>

            <pre class="prettyprint linenums lang-java"><![CDATA[package com.example.logging;
...
@Entity
@Table(name="application_log", schema="dbo")
public class JpaLogEntity extends AbstractLogEventWrapperEntity {
    private static final long serialVersionUID = 1L;
    private long id = 0L;

    public TestEntity() {
        super(null);
    }
    public TestEntity(LogEvent wrappedEvent) {
        super(wrappedEvent);
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "logEventId")
    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Override
    @Enumerated(EnumType.STRING)
    @Column(name = "level")
    public Level getLevel() {
        return this.getWrappedEvent().getLevel();
    }

    @Override
    @Column(name = "logger")
    public String getLoggerName() {
        return this.getWrappedEvent().getLoggerName();
    }

    @Override
    @Column(name = "message")
    @Convert(converter = MyMessageConverter.class)
    public Message getMessage() {
        return this.getWrappedEvent().getMessage();
    }
    ...
}]]></pre>
        </subsection>
        <a name="KafkaAppender"/>
        <subsection name="KafkaAppender">
          <p>
            The KafkaAppender logs events to an <a href="https://kafka.apache.org/">Apache Kafka</a> topic.
            Each log event is sent as a Kafka record with no key.
          </p>
          <table>
            <caption align="top">KafkaAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>topic</td>
              <td>String</td>
              <td>The Kafka topic to use. Required.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
                may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>
                The Layout to use to format the LogEvent. If you do not specify a layout, the appender will send the
                <a class="javadoc" href="http://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/message/Message.html#getFormattedMessage())">formatted message</a>
                to Kafka as a UTF-8 encoded string.
              </td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender. Required.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>syncSend</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing sends to block until the record has been acknowledged by the
                Kafka server. When set to <code>false</code> sends return immediately, allowing for lower latency and significantly
                higher throughput. <i>New since 2.8. Be aware that this is a new addition, and it has not been extensively tested.
                Any failure sending to Kafka will be reported as error to StatusLogger and the log event will be dropped
                (the ignoreExceptions parameter will not be effective). Log events may arrive out of order to the Kafka server.</i>
              </td>
            </tr>
            <tr>
              <td>properties</td>
              <td>Property[]</td>
              <td>
                You can set properties in <a href="http://kafka.apache.org/documentation.html#producerconfigs">Kafka producer properties</a>.
                You need to set the <code>bootstrap.servers</code> property, there are sensible default values for the others.
                Do not set the <code>value.serializer</code> property.
              </td>
            </tr>
          </table>
          <p>
            Here is a sample KafkaAppender configuration snippet:
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
  ...
  <Appenders>
    <Kafka name="Kafka" topic="log-test">
      <PatternLayout pattern="%date %message"/>
        <Property name="bootstrap.servers">localhost:9092</Property>
    </Kafka>
  </Appenders>]]></pre>
          <p>
            This appender is synchronous by default and will block until the record has been acknowledged by the Kafka server, timeout
            for this can be set with the <code>timeout.ms</code> property (defaults to 30 seconds). Wrap with
            <a href="http://logging.apache.org/log4j/2.x/manual/appenders.html#AsyncAppender">Async appender</a> and/or set syncSend to
            <code>false</code> to log asynchronously.
          </p>
          <p>
            This appender requires the <a href="http://kafka.apache.org/">Kafka client library</a>. Note that you need to use a version of
            the Kafka client library matching the Kafka server used.
          </p>
          <p>
            <em>Note:</em>Make sure to not let <code>org.apache.kafka</code> log to a Kafka appender on DEBUG level,
            since that will cause recursive logging:
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
  ...
  <Loggers>
    <Root level="DEBUG">
      <AppenderRef ref="Kafka"/>
    </Root>
    <Logger name="org.apache.kafka" level="INFO" /> <!-- avoid recursive logging -->
  </Loggers>]]></pre>
        </subsection>
      <a name="MemoryMappedFileAppender" />
      <subsection name="MemoryMappedFileAppender">
        <p><i>New since 2.1. Be aware that this is a new addition, and although it has been
          tested on several platforms, it does not have as much track record as the other file appenders.</i></p>
        <p>
          The MemoryMappedFileAppender maps a part of the specified file into memory
          and writes log events to this memory, relying on the operating system's
          virtual memory manager to synchronize the changes to the storage device.
          The main benefit of using memory mapped files is I/O performance. Instead of making system
          calls to write to disk, this appender can simply change the program's local memory,
          which is orders of magnitude faster. Also, in most operating systems the memory
          region mapped actually is the kernel's <a href="http://en.wikipedia.org/wiki/Page_cache">page
          cache</a> (file cache), meaning that no copies need to be created in user space.
          (TODO: performance tests that compare performance of this appender to
          RandomAccessFileAppender and FileAppender.)
        </p>
        <p>
          There is some overhead with mapping a file region into memory,
          especially very large regions (half a gigabyte or more).
          The default region size is 32 MB, which should strike a reasonable balance
          between the frequency and the duration of remap operations.
          (TODO: performance test remapping various sizes.)
        </p>
        <p>
          Similar to the FileAppender and the RandomAccessFileAppender,
          MemoryMappedFileAppender uses a MemoryMappedFileManager to actually perform the
          file I/O. While MemoryMappedFileAppender from different Configurations
          cannot be shared, the MemoryMappedFileManagers can be if the Manager is
          accessible. For example, two web applications in a servlet container can have
          their own configuration and safely write to the same file if Log4j
          is in a ClassLoader that is common to both of them.
        </p>
        <table>
          <caption align="top">MemoryMappedFileAppender Parameters</caption>
          <tr>
            <th>Parameter Name</th>
            <th>Type</th>
            <th>Description</th>
          </tr>
          <tr>
            <td>append</td>
            <td>boolean</td>
            <td>When true - the default, records will be appended to the end
              of the file. When set to false, the file will be cleared before
              new records are written.
            </td>
          </tr>
          <tr>
            <td>fileName</td>
            <td>String</td>
            <td>The name of the file to write to. If the file, or any of its
              parent directories, do not exist, they will be created.
            </td>
          </tr>
          <tr>
            <td>filters</td>
            <td>Filter</td>
            <td>A Filter to determine if the event should be handled by this
              Appender. More than one Filter may be used by using a CompositeFilter.
            </td>
          </tr>
          <tr>
            <td>immediateFlush</td>
            <td>boolean</td>
            <td>
              <p>When set to true, each write will be followed by a
                call to <a href="http://docs.oracle.com/javase/7/docs/api/java/nio/MappedByteBuffer.html#force()">MappedByteBuffer.force()</a>.
            This will guarantee the data is written to the storage device.
              </p>
              <p>The default for this parameter is <code>false</code>.
                This means that the data is written to the storage device even
                if the Java process crashes, but there may be data loss if the
                operating system crashes.</p>
              <p>Note that manually forcing a sync on every log event loses most
                of the performance benefits of using a memory mapped file.</p>
              <p>Flushing after every write is only useful when using this
              appender with synchronous loggers. Asynchronous loggers and
              appenders will automatically flush at the end of a batch of events,
              even if immediateFlush is set to false. This also guarantees
              the data is written to disk but is more efficient.
              </p>
            </td>
          </tr>
          <tr>
            <td>regionLength</td>
            <td>int</td>
            <td>The length of the mapped region, defaults to 32 MB
              (32 * 1024 * 1024 bytes). This parameter must be a value
              between 256 and 1,073,741,824 (1 GB or 2^30);
              values outside this range will be adjusted to the closest valid
              value.
              Log4j will round the specified value up to the nearest power of two.</td>
          </tr>
          <tr>
            <td>layout</td>
            <td>Layout</td>
            <td>The Layout to use to format the LogEvent. If no layout is supplied the default pattern layout
              of "%m%n" will be used.</td>
          </tr>
          <tr>
            <td>name</td>
            <td>String</td>
            <td>The name of the Appender.</td>
          </tr>
          <tr>
            <td>ignoreExceptions</td>
            <td>boolean</td>
            <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
              internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
              caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
              <a href="#FailoverAppender">FailoverAppender</a>.</td>
          </tr>
        </table>
        <p>
          Here is a sample MemoryMappedFile configuration:
        </p>

          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <MemoryMappedFile name="MyFile" fileName="logs/app.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </MemoryMappedFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="MyFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
      </subsection>
        <a name="NoSQLAppender"/>
        <subsection name="NoSQLAppender">
          <p>The NoSQLAppender writes log events to a NoSQL database using an internal lightweight provider interface.
            Provider implementations currently exist for MongoDB and Apache CouchDB, and writing a custom provider is
            quite simple.</p>
          <table>
            <caption align="top">NoSQLAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td><em>Required.</em> The name of the Appender.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter may be
                used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>int</td>
              <td>If an integer greater than 0, this causes the appender to buffer log events and flush whenever the
                buffer reaches this size.</td>
            </tr>
            <tr>
              <td>NoSqlProvider</td>
              <td>NoSQLProvider&lt;C extends NoSQLConnection&lt;W, T extends NoSQLObject&lt;W&gt;&gt;&gt;</td>
              <td><em>Required.</em> The NoSQL provider that provides connections to the chosen NoSQL database.</td>
            </tr>
          </table>
          <p>You specify which NoSQL provider to use by specifying the appropriate configuration element within the
            <code>&lt;NoSql&gt;</code> element. The types currently supported are <code>&lt;MongoDb&gt;</code> and
            <code>&lt;CouchDb&gt;</code>. To create your own custom provider, read the JavaDoc for the
            <code>NoSQLProvider</code>, <code>NoSQLConnection</code>, and <code>NoSQLObject</code> classes and the
            documentation about creating Log4j plugins. We recommend you review the source code for the MongoDB and
            CouchDB providers as a guide for creating your own provider.</p>
          <table>
            <caption align="top">MongoDB Provider Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>collectionName</td>
              <td>String</td>
              <td><em>Required.</em> The name of the MongoDB collection to insert the events into.</td>
            </tr>
            <tr>
              <td>writeConcernConstant</td>
              <td>Field</td>
              <td>By default, the MongoDB provider inserts records with the instructions
                <code>com.mongodb.WriteConcern.ACKNOWLEDGED</code>. Use this optional attribute to specify the name of
                a constant other than <code>ACKNOWLEDGED</code>.</td>
            </tr>
            <tr>
              <td>writeConcernConstantClass</td>
              <td>Class</td>
              <td>If you specify <code>writeConcernConstant</code>, you can use this attribute to specify a class other
                than <code>com.mongodb.WriteConcern</code> to find the constant on (to create your own custom
                instructions).</td>
            </tr>
            <tr>
              <td>factoryClassName</td>
              <td>Class</td>
              <td>To provide a connection to the MongoDB database, you can use this attribute and
                <code>factoryMethodName</code> to specify a class and static method to get the connection from. The
                method must return a <code>com.mongodb.DB</code> or a <code>com.mongodb.MongoClient</code>. If the
                <code>DB</code> is not authenticated, you must also specify a <code>username</code> and
                <code>password</code>. If you use the factory method for providing a connection, you must not specify
                the <code>databaseName</code>, <code>server</code>, or <code>port</code> attributes.</td>
            </tr>
            <tr>
              <td>factoryMethodName</td>
              <td>Method</td>
              <td>See the documentation for attribute <code>factoryClassName</code>.</td>
            </tr>
            <tr>
              <td>databaseName</td>
              <td>String</td>
              <td>If you do not specify a <code>factoryClassName</code> and <code>factoryMethodName</code> for providing
                a MongoDB connection, you must specify a MongoDB database name using this attribute. You must also
                specify a <code>username</code> and <code>password</code>. You can optionally also specify a
                <code>server</code> (defaults to localhost), and a <code>port</code> (defaults to the default MongoDB
                port).</td>
            </tr>
            <tr>
              <td>server</td>
              <td>String</td>
              <td>See the documentation for attribute <code>databaseName</code>.</td>
            </tr>
            <tr>
              <td>port</td>
              <td>int</td>
              <td>See the documentation for attribute <code>databaseName</code>.</td>
            </tr>
            <tr>
              <td>username</td>
              <td>String</td>
              <td>See the documentation for attributes <code>databaseName</code> and <code>factoryClassName</code>.</td>
            </tr>
            <tr>
              <td>password</td>
              <td>String</td>
              <td>See the documentation for attributes <code>databaseName</code> and <code>factoryClassName</code>.</td>
            </tr>
          </table>
          <table>
            <caption align="top">CouchDB Provider Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>factoryClassName</td>
              <td>Class</td>
              <td>To provide a connection to the CouchDB database, you can use this attribute and
                <code>factoryMethodName</code> to specify a class and static method to get the connection from. The
                method must return a <code>org.lightcouch.CouchDbClient</code> or a
                <code>org.lightcouch.CouchDbProperties</code>. If you use the factory method for providing a connection,
                you must not specify the <code>databaseName</code>, <code>protocol</code>, <code>server</code>,
                <code>port</code>, <code>username</code>, or <code>password</code> attributes.</td>
            </tr>
            <tr>
              <td>factoryMethodName</td>
              <td>Method</td>
              <td>See the documentation for attribute <code>factoryClassName</code>.</td>
            </tr>
            <tr>
              <td>databaseName</td>
              <td>String</td>
              <td>If you do not specify a <code>factoryClassName</code> and <code>factoryMethodName</code> for providing
                a CouchDB connection, you must specify a CouchDB database name using this attribute. You must also
                specify a <code>username</code> and <code>password</code>. You can optionally also specify a
                <code>protocol</code> (defaults to http), <code>server</code> (defaults to localhost), and a
                <code>port</code> (defaults to 80 for http and 443 for https).</td>
            </tr>
            <tr>
              <td>protocol</td>
              <td>String</td>
              <td>Must either be "http" or "https." See the documentation for attribute <code>databaseName</code>.</td>
            </tr>
            <tr>
              <td>server</td>
              <td>String</td>
              <td>See the documentation for attribute <code>databaseName</code>.</td>
            </tr>
            <tr>
              <td>port</td>
              <td>int</td>
              <td>See the documentation for attribute <code>databaseName</code>.</td>
            </tr>
            <tr>
              <td>username</td>
              <td>String</td>
              <td>See the documentation for attributes <code>databaseName</code>.</td>
            </tr>
            <tr>
              <td>password</td>
              <td>String</td>
              <td>See the documentation for attributes <code>databaseName</code>.</td>
            </tr>
          </table>
          <p>
            Here are a few sample configurations for the NoSQLAppender:
          </p>

            <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <NoSql name="databaseAppender">
      <MongoDb databaseName="applicationDb" collectionName="applicationLog" server="mongo.example.org"
               username="loggingUser" password="abc123" />
    </NoSql>
  </Appenders>
  <Loggers>
    <Root level="warn">
      <AppenderRef ref="databaseAppender"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>

            <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <NoSql name="databaseAppender">
      <MongoDb collectionName="applicationLog" factoryClassName="org.example.db.ConnectionFactory"
               factoryMethodName="getNewMongoClient" />
    </NoSql>
  </Appenders>
  <Loggers>
    <Root level="warn">
      <AppenderRef ref="databaseAppender"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>

            <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <NoSql name="databaseAppender">
      <CouchDb databaseName="applicationDb" protocol="https" server="couch.example.org"
               username="loggingUser" password="abc123" />
    </NoSql>
  </Appenders>
  <Loggers>
    <Root level="warn">
      <AppenderRef ref="databaseAppender"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            The following example demonstrates how log events are persisted in NoSQL databases if represented in a JSON
            format:
          </p>
            <pre class="prettyprint lang-javascript"><![CDATA[{
    "level": "WARN",
    "loggerName": "com.example.application.MyClass",
    "message": "Something happened that you might want to know about.",
    "source": {
        "className": "com.example.application.MyClass",
        "methodName": "exampleMethod",
        "fileName": "MyClass.java",
        "lineNumber": 81
    },
    "marker": {
        "name": "SomeMarker",
        "parent" {
            "name": "SomeParentMarker"
        }
    },
    "threadName": "Thread-1",
    "millis": 1368844166761,
    "date": "2013-05-18T02:29:26.761Z",
    "thrown": {
        "type": "java.sql.SQLException",
        "message": "Could not insert record. Connection lost.",
        "stackTrace": [
                { "className": "org.example.sql.driver.PreparedStatement$1", "methodName": "responder", "fileName": "PreparedStatement.java", "lineNumber": 1049 },
                { "className": "org.example.sql.driver.PreparedStatement", "methodName": "executeUpdate", "fileName": "PreparedStatement.java", "lineNumber": 738 },
                { "className": "com.example.application.MyClass", "methodName": "exampleMethod", "fileName": "MyClass.java", "lineNumber": 81 },
                { "className": "com.example.application.MainClass", "methodName": "main", "fileName": "MainClass.java", "lineNumber": 52 }
        ],
        "cause": {
            "type": "java.io.IOException",
            "message": "Connection lost.",
            "stackTrace": [
                { "className": "java.nio.channels.SocketChannel", "methodName": "write", "fileName": null, "lineNumber": -1 },
                { "className": "org.example.sql.driver.PreparedStatement$1", "methodName": "responder", "fileName": "PreparedStatement.java", "lineNumber": 1032 },
                { "className": "org.example.sql.driver.PreparedStatement", "methodName": "executeUpdate", "fileName": "PreparedStatement.java", "lineNumber": 738 },
                { "className": "com.example.application.MyClass", "methodName": "exampleMethod", "fileName": "MyClass.java", "lineNumber": 81 },
                { "className": "com.example.application.MainClass", "methodName": "main", "fileName": "MainClass.java", "lineNumber": 52 }
            ]
        }
    },
    "contextMap": {
        "ID": "86c3a497-4e67-4eed-9d6a-2e5797324d7b",
        "username": "JohnDoe"
    },
    "contextStack": [
        "topItem",
        "anotherItem",
        "bottomItem"
    ]
}]]></pre>
        </subsection>
        <a name="OutputStreamAppender"/>
        <subsection name="OutputStreamAppender">
          <p>
          The OutputStreamAppender provides the base for many of the other Appenders such as the File and Socket
          appenders that write the event to an Output Stream. It cannot be directly configured. Support for
          immediateFlush and buffering is provided by the OutputStreamAppender. The OutputStreamAppender uses an
          OutputStreamManager to handle the actual I/O, allowing the stream to be shared by Appenders in multiple
          configurations.
          </p>
        </subsection>
			<a name="RandomAccessFileAppender" />
			<subsection name="RandomAccessFileAppender">
				<p>
					The RandomAccessFileAppender is similar to the standard
					<a href="#FileAppender">FileAppender</a>
					except it is always buffered (this cannot be switched off)
					and internally it uses a
					<tt>ByteBuffer + RandomAccessFile</tt>
					instead of a
					<tt>BufferedOutputStream</tt>.
					We saw a 20-200% performance improvement compared to
					FileAppender with "bufferedIO=true" in our
					<a href="../performance.html#whichAppender">measurements</a>.
					Similar to the FileAppender,
					RandomAccessFileAppender uses a RandomAccessFileManager to actually perform the
					file I/O. While RandomAccessFileAppender
					from different Configurations
					cannot be shared, the RandomAccessFileManagers can be if the Manager is
					accessible. For example, two web applications in a
					servlet container can have
					their own configuration and safely
					write to the same file if Log4j
					is in a ClassLoader that is common to
					both of them.
				</p>
				<table>
          <caption align="top">RandomAccessFileAppender Parameters</caption>
          <tr>
						<th>Parameter Name</th>
						<th>Type</th>
						<th>Description</th>
					</tr>
          <tr>
						<td>append</td>
						<td>boolean</td>
						<td>When true - the default, records will be appended to the end
							of the file. When set to false,
							the file will be cleared before
							new records are written.
						</td>
					</tr>
          <tr>
						<td>fileName</td>
						<td>String</td>
						<td>The name of the file to write to. If the file, or any of its
							parent directories, do not exist,
							they will be created.
						</td>
					</tr>
          <tr>
						<td>filters</td>
						<td>Filter</td>
						<td>A Filter to determine if the event should be handled by this
							Appender. More than one Filter
							may be used by using a CompositeFilter.
						</td>
					</tr>
          <tr>
						<td>immediateFlush</td>
						<td>boolean</td>
		                <td>
                          <p>
                            When set to true - the default, each write will be followed by a flush.
		                    This will guarantee the data is written
		                    to disk but could impact performance.
                          </p>
		                  <p>
                            Flushing after every write is only useful when using this
						    appender with synchronous loggers. Asynchronous loggers and
						    appenders will automatically flush at the end of a batch of events,
						    even if immediateFlush is set to false. This also guarantees
						    the data is written to disk but is more efficient.
                          </p>
		                </td>
					</tr>
          <tr>
                      <td>bufferSize</td>
                      <td>int</td>
                      <td>The buffer size, defaults to 262,144 bytes (256 * 1024).</td>
                    </tr>
          <tr>
						<td>layout</td>
						<td>Layout</td>
						<td>The Layout to use to format the LogEvent. If no layout is supplied the default pattern layout
              of "%m%n" will be used.</td>
					</tr>
          <tr>
						<td>name</td>
						<td>String</td>
						<td>The name of the Appender.</td>
					</tr>
          <tr>
                      <td>ignoreExceptions</td>
                      <td>boolean</td>
                      <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                        internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                        caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                        <a href="#FailoverAppender">FailoverAppender</a>.</td>
                    </tr>
				</table>
				<p>
					Here is a sample RandomAccessFile configuration:
        </p>

					<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RandomAccessFile name="MyFile" fileName="logs/app.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </RandomAccessFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="MyFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
			</subsection>
        <a name="RewriteAppender"/>
        <subsection name="RewriteAppender">
          <p>
            The RewriteAppender allows the LogEvent to manipulated before it is processed by another Appender. This
            can be used to mask sensitive information such as passwords or to inject information into each event.
            The RewriteAppender must be configured with a <a href="RewritePolicy">RewritePolicy</a>. The
            RewriteAppender should be configured after any Appenders it references to allow it to shut down properly.
          </p>
          <table>
            <caption align="top">RewriteAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>AppenderRef</td>
              <td>String</td>
              <td>The name of the Appenders to call after the LogEvent has been manipulated. Multiple AppenderRef
                elements can be configured.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>rewritePolicy</td>
              <td>RewritePolicy</td>
              <td>The RewritePolicy that will manipulate the LogEvent.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
          </table>
          <h4>RewritePolicy</h4>
            <p>
              RewritePolicy is an interface that allows implementations to inspect and possibly modify LogEvents
              before they are passed to Appender. RewritePolicy declares a single method named rewrite that must
              be implemented. The method is passed the LogEvent and can return the same event or create a new one.
            </p>
            <h5>MapRewritePolicy</h5>
              <p>
                MapRewritePolicy will evaluate LogEvents that contain a MapMessage and will add or update
                elements of the Map.
              </p>
              <table>
                <tr>
                  <th>Parameter Name</th>
                  <th>Type</th>
                  <th>Description</th>
                </tr>
                <tr>
                  <td>mode</td>
                  <td>String</td>
                  <td>"Add" or "Update"</td>
                </tr>
                <tr>
                  <td>keyValuePair</td>
                  <td>KeyValuePair[]</td>
                  <td>An array of keys and their values.</td>
                </tr>
              </table>
            <p>
             The following configuration shows a RewriteAppender configured to add a product key and its value
             to the MapMessage.:
            </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT">
      <PatternLayout pattern="%m%n"/>
    </Console>
    <Rewrite name="rewrite">
      <AppenderRef ref="STDOUT"/>
      <MapRewritePolicy mode="Add">
        <KeyValuePair key="product" value="TestProduct"/>
      </MapRewritePolicy>
    </Rewrite>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Rewrite"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <h5>PropertiesRewritePolicy</h5>
          <p>
            PropertiesRewritePolicy will add properties configured on the policy to the ThreadContext Map
            being logged. The properties will not be added to the actual ThreadContext Map. The property
            values may contain variables that will be evaluated when the configuration is processed as
            well as when the event is logged.
          </p>
          <table>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>properties</td>
              <td>Property[]</td>
              <td>One of more Property elements to define the keys and values to be added to the ThreadContext Map.</td>
            </tr>
          </table>
          <p>
            The following configuration shows a RewriteAppender configured to add a product key and its value
            to the MapMessage:
          </p>
            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT">
      <PatternLayout pattern="%m%n"/>
    </Console>
    <Rewrite name="rewrite">
      <AppenderRef ref="STDOUT"/>
      <PropertiesRewritePolicy>
        <Property name="user">${sys:user.name}</Property>
        <Property name="env">${sys:environment}</Property>
      </PropertiesRewritePolicy>
    </Rewrite>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Rewrite"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        <h5>LoggerNameLevelRewritePolicy</h5>
        <p>
          You can use this policy to make loggers in third party code less chatty by changing event levels.
          The LoggerNameLevelRewritePolicy will rewrite log event levels for a given logger name prefix.
          You configure a LoggerNameLevelRewritePolicy with a logger name prefix and a pairs of levels,
          where a pair defines a source level and a target level.
        </p>
          <table>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>loggerName</td>
              <td>String</td>
              <td>A logger name used as a prefix to test each event's logger name.</td>
            </tr>
            <tr>
              <td>LevelPair</td>
              <td>KeyValuePair[]</td>
              <td>An array of keys and their values, each key is a source level, each value a target level.</td>
            </tr>
          </table>
          <p>
            The following configuration shows a RewriteAppender configured to map level INFO to DEBUG and level
            WARN to INFO for all loggers that start with <code>com.foo.bar</code>.
          </p>
            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp">
  <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT">
      <PatternLayout pattern="%m%n"/>
    </Console>
    <Rewrite name="rewrite">
      <AppenderRef ref="STDOUT"/>
      <LoggerNameLevelRewritePolicy loggerName="com.foo.bar">
        <KeyValuePair key="INFO" value="DEBUG"/>
        <KeyValuePair key="WARN" value="INFO"/>
      </LoggerNameLevelRewritePolicy>
    </Rewrite>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Rewrite"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="RollingFileAppender"/>
        <subsection name="RollingFileAppender">
          <p>The RollingFileAppender is an OutputStreamAppender that writes to the File named in the fileName parameter
            and rolls the file over according the TriggeringPolicy and the RolloverPolicy. The
            RollingFileAppender uses a RollingFileManager (which extends OutputStreamManager) to actually perform the
            file I/O and perform the rollover. While RolloverFileAppenders from different Configurations cannot be
            shared, the RollingFileManagers can be if the Manager is accessible. For example, two web applications in a
            servlet container can have their own configuration and safely
            write to the same file if Log4j is in a ClassLoader that is common to both of them.</p>
          <p>
            A RollingFileAppender requires a <a href="#TriggeringPolicies">TriggeringPolicy</a> and a
            <a href="#RolloverStrategies">RolloverStrategy</a>. The triggering policy determines if a rollover should
            be performed while the RolloverStrategy defines how the rollover should be done. If no RolloverStrategy
            is configured, RollingFileAppender will use the <a href="#DefaultRolloverStrategy">DefaultRolloverStrategy</a>.
            Since log4j-2.5, a <a href="#CustomDeleteOnRollover">custom delete action</a> can be configured in the
            DefaultRolloverStrategy to run at rollover. Since 2.8 if no file name is configured then
            <a href="DirectWriteRolloverStrategy">DirectWriteRolloverStrategy</a> will be used instead of
            DefaultRolloverStrategy.
          </p>
          <p>
            File locking is not supported by the RollingFileAppender.
          </p>
          <table>
            <caption align="top">RollingFileAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>append</td>
              <td>boolean</td>
              <td>When true - the default, records will be appended to the end of the file. When set to false,
                the file will be cleared before new records are written.</td>
            </tr>
            <tr>
              <td>bufferedIO</td>
              <td>boolean</td>
              <td>When true - the default, records will be written to a buffer and the data will be written to
                disk when the buffer is full or, if immediateFlush is set, when the record is written.
                File locking cannot be used with bufferedIO. Performance tests have shown that using buffered I/O
                significantly improves performance, even if immediateFlush is enabled.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>int</td>
              <td>When bufferedIO is true, this is the buffer size, the default is 8192 bytes.</td>
            </tr>
            <tr>
              <td>createOnDemand</td>
              <td>boolean</td>
              <td>The appender creates the file on-demand. The appender only creates the file when a log event
                passes all filters and is routed to this appender. Defaults to false.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>fileName</td>
              <td>String</td>
              <td>The name of the file to write to. If the file, or any of its parent directories, do not exist,
                they will be created.</td>
            </tr>
            <tr>
              <td>filePattern</td>
              <td>String</td>
              <td>The pattern of the file name of the archived log file. The format of the pattern is
                dependent on the RolloverPolicy that is used. The DefaultRolloverPolicy will accept both
                a date/time pattern compatible with
                <a href="http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html">SimpleDateFormat</a>
                and/or a %i which represents an integer counter. The pattern also supports interpolation at
                runtime so any of the Lookups (such as the <a href="./lookups.html#DateLookup">DateLookup</a>) can
                be included in the pattern.</td>
            </tr>
            <tr>
              <td>immediateFlush</td>
              <td>boolean</td>
              <td><p>When set to true - the default, each write will be followed by a flush.
                This will guarantee the data is written
                to disk but could impact performance.</p>
                <p>Flushing after every write is only useful when using this
				appender with synchronous loggers. Asynchronous loggers and
				appenders will automatically flush at the end of a batch of events,
				even if immediateFlush is set to false. This also guarantees
				the data is written to disk but is more efficient.</p>
              </td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>The Layout to use to format the LogEvent. If no layout is supplied the default pattern layout
                of "%m%n" will be used.</td>
            </tr>

            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>policy</td>
              <td>TriggeringPolicy</td>
              <td>The policy to use to determine if a rollover should occur.</td>
            </tr>
            <tr>
              <td>strategy</td>
              <td>RolloverStrategy</td>
              <td>The strategy to use to determine the name and location of the archive file.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
          </table>
          <a name="TriggeringPolicies"/>
          <h4>Triggering Policies</h4>
            <h5>Composite Triggering Policy</h5>
              <p>
                The <code>CompositeTriggeringPolicy</code> combines multiple triggering policies and returns true if
                any of the configured policies return true. The <code>CompositeTriggeringPolicy</code> is configured
                simply by wrapping other policies in a <code>Policies</code> element.
              </p>
              <p>
                For example, the following XML fragment defines policies that rollover the log when the JVM starts,
                when the log size reaches twenty megabytes, and when the current date no longer matches the log’s
                start date.
              </p>
            <pre class="prettyprint linenums"><![CDATA[<Policies>
  <OnStartupTriggeringPolicy />
  <SizeBasedTriggeringPolicy size="20 MB" />
  <TimeBasedTriggeringPolicy />
</Policies>]]></pre>
            <h5>Cron Triggering Policy</h5>
              <p>The <code>CronTriggeringPolicy</code> triggers rollover based on a cron expression.</p>
              <table>
                <caption align="top">CronTriggeringPolicy Parameters</caption>
                <tr>
                  <th>Parameter Name</th>
                  <th>Type</th>
                  <th>Description</th>
                </tr>
                <tr>
                  <td>schedule</td>
                  <td>String</td>
                  <td>The cron expression. The expression is the same as what is allowed in the Quartz scheduler. See
                    <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/util/CronExpression.html">CronExpression</a>
                    for a full description of the expression.
                  </td>
                </tr>
                <tr>
                  <td>evaluateOnStartup</td>
                  <td>boolean</td>
                  <td>On startup the cron expression will be evaluated against the file's last modification timestamp.
                    If the cron expression indicates a rollover should have occurred between that time and the current
                    time the file will be immediately rolled over.</td>
                </tr>
              </table>
            <h5>OnStartup Triggering Policy</h5>
              <p>
                The <code>OnStartupTriggeringPolicy</code> policy causes a rollover if the log file is older than the
                current JVM's start time and the minimum file size is met or exceeded.
              </p>
                <table>
                  <caption align="top">OnStartupTriggeringPolicy Parameters</caption>
                  <tr>
                    <th>Parameter Name</th>
                    <th>Type</th>
                    <th>Description</th>
                  </tr>
                  <tr>
                    <td>minSize</td>
                    <td>long</td>
                    <td>
                      The minimum size the file must have to roll over. A size of zero will cause a roll over no matter
                      what the file size is. The default value is 1, which will prevent rolling over an empty file.
                    </td>
                  </tr>
                </table>
              <p>
                <em>Google App Engine note:</em><br />
                When running in Google App Engine, the OnStartup policy causes a rollover if the log file is older
                than <em>the time when Log4J initialized</em>.
                (Google App Engine restricts access to certain classes so Log4J cannot determine JVM start time with
                <code>java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime()</code>
                and falls back to Log4J initialization time instead.)
              </p>
            <h5>SizeBased Triggering Policy</h5>
              <p>
                The <code>SizeBasedTriggeringPolicy</code> causes a rollover once the file has reached the specified
                size. The size can be specified in bytes, with the suffix KB, MB or GB, for example <code>20MB</code>.
              </p>
            <h5>TimeBased Triggering Policy</h5>
              <p>
                The <code>TimeBasedTriggeringPolicy</code> causes a rollover once the date/time pattern no longer
                applies to the active file. This policy accepts an <code>interval</code> attribute which indicates how
                frequently the rollover should occur based on the time pattern and a <code>modulate</code> boolean
                attribute.
              </p>
                <table>
                  <caption align="top">TimeBasedTriggeringPolicy Parameters</caption>
                  <tr>
                    <th>Parameter Name</th>
                    <th>Type</th>
                    <th>Description</th>
                  </tr>
                  <tr>
                    <td>interval</td>
                    <td>integer</td>
                    <td>How often a rollover should occur based on the most specific time unit in the date pattern.
                      For example, with a date pattern with hours as the most specific item and and increment of 4 rollovers
                      would occur every 4 hours.
                      The default value is 1.</td>
                  </tr>
                  <tr>
                    <td>modulate</td>
                    <td>boolean</td>
                    <td>Indicates whether the interval should be adjusted to cause the next rollover to occur on
                      the interval boundary. For example, if the item is hours, the current hour is 3 am and the
                      interval is 4 then the first rollover will occur at 4 am and then next ones will occur at
                      8 am, noon, 4pm, etc.</td>
                  </tr>
                </table>
          <a name="RolloverStrategies"/>
          <h4>Rollover Strategies</h4>
            <a name="DefaultRolloverStrategy"/>
            <h5>Default Rollover Strategy</h5>
              <p>
                The default rollover strategy accepts both a date/time pattern and an integer from the filePattern
                attribute specified on the RollingFileAppender itself. If the date/time pattern
                is present it will be replaced with the current date and time values. If the pattern contains an integer
                it will be incremented on each rollover. If the pattern contains both a date/time and integer
                in the pattern the integer will be incremented until the result of the date/time pattern changes. If
                the file pattern ends with ".gz", ".zip", ".bz2", ".deflate", ".pack200", or ".xz" the resulting archive
                will be compressed using the compression scheme that matches the suffix. The formats bzip2, Deflate,
                Pack200 and XZ require <a href="http://commons.apache.org/proper/commons-compress/">Apache Commons Compress</a>.
                In addition, XZ requires <a href="http://tukaani.org/xz/java.html">XZ for Java</a>.
                The pattern may also contain lookup references that can be resolved at runtime such as is shown in the example
                below.
              </p>
              <p>The default rollover strategy supports three variations for incrementing the counter. The first is
                the "fixed window" strategy. To illustrate how it works, suppose that the min attribute is set to 1,
                the max attribute is set to 3, the file name is "foo.log", and the file name pattern is "foo-%i.log".
              </p>

              <table>
                <tr>
                  <th>Number of rollovers</th>
                  <th>Active output target</th>
                  <th>Archived log files</th>
                  <th>Description</th>
                </tr>
                <tr>
                  <td>0</td>
                  <td>foo.log</td>
                  <td>-</td>
                  <td>All logging is going to the initial file.</td>
                </tr>
                <tr>
                  <td>1</td>
                  <td>foo.log</td>
                  <td>foo-1.log</td>
                  <td>During the first rollover foo.log is renamed to foo-1.log. A new foo.log file is created and
                  starts being written to.</td>
                </tr>
                <tr>
                  <td>2</td>
                  <td>foo.log</td>
                  <td>foo-1.log, foo-2.log</td>
                  <td>During the second rollover foo-1.log is renamed to foo-2.log and foo.log is renamed to
                    foo-1.log. A new foo.log file is created and starts being written to.</td>
                </tr>
                <tr>
                  <td>3</td>
                  <td>foo.log</td>
                  <td>foo-1.log, foo-2.log, foo-3.log</td>
                  <td>During the third rollover foo-2.log is renamed to foo-3.log, foo-1.log is renamed to foo-2.log and
                    foo.log is renamed to foo-1.log. A new foo.log file is created and starts being written to.</td>
                </tr>
                <tr>
                  <td>4</td>
                  <td>foo.log</td>
                  <td>foo-1.log, foo-2.log, foo-3.log</td>
                  <td>In the fourth and subsequent rollovers, foo-3.log is deleted, foo-2.log is renamed to foo-3.log,
                    foo-1.log is renamed to foo-2.log and foo.log is renamed to foo-1.log. A new foo.log file is
                    created and starts being written to.</td>
                </tr>
              </table>
              <p>By way of contrast, when the fileIndex attribute is set to "max" but all the other settings
                are the same the following actions will be performed.
              </p>
              <table>
                <tr>
                  <th>Number of rollovers</th>
                  <th>Active output target</th>
                  <th>Archived log files</th>
                  <th>Description</th>
                </tr>
                <tr>
                  <td>0</td>
                  <td>foo.log</td>
                  <td>-</td>
                  <td>All logging is going to the initial file.</td>
                </tr>
                <tr>
                  <td>1</td>
                  <td>foo.log</td>
                  <td>foo-1.log</td>
                  <td>During the first rollover foo.log is renamed to foo-1.log. A new foo.log file is created and
                    starts being written to.</td>
                </tr>
                <tr>
                  <td>2</td>
                  <td>foo.log</td>
                  <td>foo-1.log, foo-2.log</td>
                  <td>During the second rollover foo.log is renamed to foo-2.log. A new foo.log file is created
                    and starts being written to.</td>
                </tr>
                <tr>
                  <td>3</td>
                  <td>foo.log</td>
                  <td>foo-1.log, foo-2.log, foo-3.log</td>
                  <td>During the third rollover foo.log is renamed to foo-3.log. A new foo.log file is created and
                    starts being written to.</td>
                </tr>
                <tr>
                  <td>4</td>
                  <td>foo.log</td>
                  <td>foo-1.log, foo-2.log, foo-3.log</td>
                  <td>In the fourth and subsequent rollovers, foo-1.log is deleted, foo-2.log is renamed to foo-1.log,
                    foo-3.log is renamed to foo-2.log and foo.log is renamed to foo-3.log. A new foo.log file is
                    created and starts being written to.</td>
                </tr>
              </table>
              <p>
                Finally, as of release 2.8, if the fileIndex attribute is set to "nomax" then the min and max values
                will be ignored and file numbering will increment by 1 and each rollover will have an incrementally
                higher value with no maximum number of files.
              </p>
              <table>
                <caption align="top">DefaultRolloverStrategy Parameters</caption>
                <tr>
                  <th>Parameter Name</th>
                  <th>Type</th>
                  <th>Description</th>
                </tr>
                <tr>
                  <td>fileIndex</td>
                  <td>String</td>
                  <td>If set to "max" (the default), files with a higher index will be newer than files with a
                    smaller index. If set to "min", file renaming and the counter will follow the Fixed Window strategy
                    described above.</td>
                </tr>
                <tr>
                  <td>min</td>
                  <td>integer</td>
                  <td>The minimum value of the counter. The default value is 1.</td>
                </tr>
                <tr>
                  <td>max</td>
                  <td>integer</td>
                  <td>The maximum value of the counter. Once this values is reached older archives will be
                    deleted on subsequent rollovers.</td>
                </tr>
                <tr>
                  <td>compressionLevel</td>
                  <td>integer</td>
                  <td>
                    Sets the compression level, 0-9, where 0 = none, 1 = best speed, through 9 = best compression.
                    Only implemented for ZIP files.
                  </td>
                </tr>
              </table>
          <a name="DirectWriteRolloverStrategy"/>
          <h5>DirectWrite Rollover Strategy</h5>
            <p>
              The DirectWriteRolloverStrategy causes log events to be written directly to files represented by the
              file pattern. With this strategy file renames are not performed. If the size-based triggering policy
              causes multiple files to be written durring the specified time period they will be numbered starting
              at one and continually incremented until a time-based rollover occurs.
            </p>
            <p>
              Warning: If the file pattern has a
              suffix indicating compression should take place the current file will not be compressed when the
              application is shut down. Furthermore, if the time changes such that the file pattern no longer
              matches the current file it will not be compressed at startup either.
            </p>
            <table>
              <caption align="top">DirectWriteRolloverStrategy Parameters</caption>
              <tr>
                <th>Parameter Name</th>
                <th>Type</th>
                <th>Description</th>
              </tr>
              <tr>
                <td>maxFiles</td>
                <td>String</td>
                <td>The maximum number of files to allow in the time period matching the file pattern. If the
                  number of files is exceeded the oldest file will be deleted. If specified, the value must
                  be greater than 1. If the value is less than zero or omitted then the number of files will
                  not be limited.</td>
              </tr>
              <tr>
                <td>compressionLevel</td>
                <td>integer</td>
                <td>
                  Sets the compression level, 0-9, where 0 = none, 1 = best speed, through 9 = best compression.
                  Only implemented for ZIP files.
                </td>
              </tr>
            </table>
          <p>
            Below is a sample configuration that uses a RollingFileAppender with both the time and size based
            triggering policies, will create up to 7 archives on the same day (1-7) that are stored in a directory
            based on the current year and month, and will compress each
            archive using gzip:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            This second example shows a rollover strategy that will keep up to 20 files before removing them.
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="20"/>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            Below is a sample configuration that uses a RollingFileAppender with both the time and size based
            triggering policies, will create up to 7 archives on the same day (1-7) that are stored in a directory
            based on the current year and month, and will compress each
            archive using gzip and will roll every 6 hours when the hour is divisible by 6:
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            This sample configuration uses a RollingFileAppender with both the cron and size based
            triggering policies, and writes directly to an unlimited number of archive files. The cron
            trigger causes a rollover every hour while the file size is limited to 250MB:
          </p>

          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" filePattern="logs/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <CronTriggeringPolicy schedule="0 0 * * * ?"/>
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            This sample configuration is the same as the previous but limits the number of files saved each hour to 10:
          </p>

          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingFile name="RollingFile" filePattern="logs/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <CronTriggeringPolicy schedule="0 0 * * * ?"/>
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
      <DirectWriteRolloverStrategy maxFiles="10"/>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <a name="CustomDeleteOnRollover"/>
          <h5>Log Archive Retention Policy: Delete on Rollover</h5>
          <p>
            Log4j-2.5 introduces a <tt>Delete</tt> action that gives users more control
            over what files are deleted at rollover time than what was possible with the DefaultRolloverStrategy
            <tt>max</tt> attribute.
            The Delete action lets users configure one or more conditions that select the files to delete
            relative to a base directory.
          </p>
          <p>
            Note that it is possible to delete any file, not just rolled over log files, so use this action with care!
            With the <tt>testMode</tt> parameter you can test your configuration without accidentally deleting the wrong files.
          </p>
          <table>
            <caption align="top">Delete Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>basePath</td>
              <td>String</td>
              <td><em>Required.</em> Base path from where to start scanning for files to delete.</td>
            </tr>
            <tr>
              <td>maxDepth</td>
              <td>int</td>
              <td>The maximum number of levels of directories to visit. A value of 0
                  means that only the starting file (the base path itself) is visited,
                  unless denied by the security manager. A value of
                  Integer.MAX_VALUE indicates that all levels should be visited. The default is 1,
                  meaning only the files in the specified base directory.</td>
            </tr>
            <tr>
              <td>followLinks</td>
              <td>boolean</td>
              <td>Whether to follow symbolic links. Default is false.</td>
            </tr>
            <tr>
              <td>testMode</td>
              <td>boolean</td>
              <td>If true, files are not deleted but instead a message is printed to the <a
                 href="configuration.html#StatusMessages">status logger</a> at INFO level.
                 Use this to do a dry run to test if the configuration works as expected. Default is false.</td>
            </tr>
            <tr>
              <td>pathSorter</td>
              <td>PathSorter</td>
              <td>A plugin implementing the
                <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/appender/rolling/action/PathSorter.html">PathSorter</a>
                interface to sort the files before selecting the files to delete. The default is to sort most recently
                modified files first.</td>
            </tr>
            <tr>
              <td>pathConditions <a name="DeletePathCondition"/></td>
              <td>PathCondition[]</td>
              <td><p><em>Required if no ScriptCondition is specified.</em> One or more PathCondition elements.</p>
                <p>
                  If more than one condition is specified,
                  they all need to accept a path before it is deleted. Conditions can be nested, in which case the
                  inner condition(s) are evaluated only if the outer condition accepts the path.
                  If conditions are not nested they may be evaluated in any order.
                </p>
                <p>
                  Conditions can also be combined with the logical operators AND, OR and NOT by using the
                  <tt>IfAll</tt>, <tt>IfAny</tt> and <tt>IfNot</tt> composite conditions.
                </p>
                <p>Users can create custom conditions or use the built-in conditions:</p>
                <ul>
                  <li><a href="#DeleteIfFileName">IfFileName</a> - accepts files whose path (relative to the base path) matches a
                    <a href="https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">regular expression</a> or a
                    <a href="https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)">glob</a>.</li>
                  <li><a href="#DeleteIfLastModified">IfLastModified</a> - accepts files that are as old as or older than the specified
                    <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/appender/rolling/action/Duration.html#parse(CharSequence)">duration</a>.
                  </li>
                  <li><a href="#DeleteIfAccumulatedFileCount">IfAccumulatedFileCount</a> - accepts paths after some count threshold is exceeded during the file tree walk.</li>
                  <li><a href="#DeleteIfAccumulatedFileSize">IfAccumulatedFileSize</a> - accepts paths after the accumulated file size threshold is exceeded during the file tree walk.</li>
                  <li>IfAll - accepts a path if all nested conditions accept it (logical AND).
                    Nested conditions may be evaluated in any order.</li>
                  <li>IfAny - accepts a path if one of the nested conditions accept it (logical OR).
                    Nested conditions may be evaluated in any order.</li>
                  <li>IfNot - accepts a path if the nested condition does not accept it (logical NOT).</li>
                </ul>
              </td>
            </tr>
            <tr>
              <td>scriptCondition <a name="DeleteScriptCondition"/></td>
              <td>ScriptCondition</td>
              <td><p><em>Required if no PathConditions are specified.</em> A ScriptCondition element specifying a script.</p>
                <p>
                  The ScriptCondition should contain a <a href="#ScriptCondition">Script,
                  ScriptRef or ScriptFile</a> element that specifies the logic to be executed.
                  (See also the <a href="filters.html#Script">ScriptFilter</a> documentation for more examples of
                  configuring ScriptFiles and ScriptRefs.)
                </p>
                <p>The script is passed a number of <a href="#ScriptParameters">parameters</a>,
                  including a list of paths found under the base path (up to <tt>maxDepth</tt>)
                  and must return a list with the paths to delete.</p>
              </td>
            </tr>
          </table>
          <a name="DeleteIfFileName"/>
          <table>
            <caption align="top">IfFileName Condition Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>glob</td>
              <td>String</td>
              <td><em>Required if regex not specified.</em>
                Matches the relative path (relative to the base path) using a limited pattern language that resembles regular expressions but with a
                <a href="https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)">simpler syntax</a>.
              </td>
            </tr>
            <tr>
              <td>regex</td>
              <td>String</td>
              <td><em>Required if glob not specified.</em>
                Matches the relative path (relative to the base path) using a regular expression as defined by the
                <a href="https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">Pattern</a> class.
              </td>
            </tr>
            <tr>
              <td>nestedConditions</td>
              <td>PathCondition[]</td>
              <td>An optional set of nested <a href="#DeletePathCondition">PathConditions</a>. If any nested conditions
                exist they all need to accept the file before it is deleted. Nested conditions are only evaluated if the
                outer condition accepts a file (if the path name matches).
              </td>
            </tr>
          </table>
          <a name="DeleteIfLastModified"/>
          <table>
            <caption align="top">IfLastModified Condition Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>age</td>
              <td>String</td>
              <td><em>Required.</em>
                Specifies a <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/appender/rolling/action/Duration.html#parse(CharSequence)">duration</a>.
                The condition accepts files that are as old or older than the specified duration.
              </td>
            </tr>
            <tr>
              <td>nestedConditions</td>
              <td>PathCondition[]</td>
              <td>An optional set of nested <a href="#DeletePathCondition">PathConditions</a>. If any nested conditions
                exist they all need to accept the file before it is deleted. Nested conditions are only evaluated if the
                outer condition accepts a file (if the file is old enough).
              </td>
            </tr>
          </table>
          <a name="DeleteIfAccumulatedFileCount"/>
          <table>
            <caption align="top">IfAccumulatedFileCount Condition Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>exceeds</td>
              <td>int</td>
              <td><em>Required.</em>
                The threshold count from which files will be deleted.
              </td>
            </tr>
            <tr>
              <td>nestedConditions</td>
              <td>PathCondition[]</td>
              <td>An optional set of nested <a href="#DeletePathCondition">PathConditions</a>. If any nested conditions
                exist they all need to accept the file before it is deleted. Nested conditions are only evaluated if the
                outer condition accepts a file (if the threshold count has been exceeded).
              </td>
            </tr>
          </table>
          <a name="DeleteIfAccumulatedFileSize"/>
          <table>
            <caption align="top">IfAccumulatedFileSize Condition Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>exceeds</td>
              <td>String</td>
              <td><em>Required.</em>
                The threshold accumulated file size from which files will be deleted.
                The size can be specified in bytes, with the suffix KB, MB or GB, for example <tt>20MB</tt>.
              </td>
            </tr>
            <tr>
              <td>nestedConditions</td>
              <td>PathCondition[]</td>
              <td>An optional set of nested <a href="#DeletePathCondition">PathConditions</a>. If any nested conditions
                exist they all need to accept the file before it is deleted. Nested conditions are only evaluated if the
                outer condition accepts a file (if the threshold accumulated file size has been exceeded).
              </td>
            </tr>
          </table>
          <p>
            Below is a sample configuration that uses a RollingFileAppender with the cron
            triggering policy configured to trigger every day at midnight.
            Archives are stored in a directory based on the current year and month.
            All files under the base directory that match the "*/app-*.log.gz" glob and are 60 days old
            or older are deleted at rollover time.
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Properties>
    <Property name="baseDir">logs</Property>
  </Properties>
  <Appenders>
    <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
          filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd}.log.gz">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
      <CronTriggeringPolicy schedule="0 0 0 * * ?"/>
      <DefaultRolloverStrategy>
        <Delete basePath="${baseDir}" maxDepth="2">
          <IfFileName glob="*/app-*.log.gz" />
          <IfLastModified age="60d" />
        </Delete>
      </DefaultRolloverStrategy>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            Below is a sample configuration that uses a RollingFileAppender with both the time and size based
            triggering policies, will create up to 100 archives on the same day (1-100) that are stored in a directory
            based on the current year and month, and will compress each
            archive using gzip and will roll every hour.

            During every rollover, this configuration will delete files that match "*/app-*.log.gz"
            and are 30 days old or older,
            but keep the most recent 100 GB or the most recent 10 files, whichever comes first.
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Properties>
    <Property name="baseDir">logs</Property>
  </Properties>
  <Appenders>
    <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
          filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="100">
        <!--
        Nested conditions: the inner condition is only evaluated on files
        for which the outer conditions are true.
        -->
        <Delete basePath="${baseDir}" maxDepth="2">
          <IfFileName glob="*/app-*.log.gz">
            <IfLastModified age="30d">
              <IfAny>
                <IfAccumulatedFileSize exceeds="100 GB" />
                <IfAccumulatedFileCount exceeds="10" />
              </IfAny>
            </IfLastModified>
          </IfFileName>
        </Delete>
      </DefaultRolloverStrategy>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <a name="ScriptCondition"/>
          <table>
            <caption align="top">ScriptCondition Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>script</td>
              <td>Script, ScriptFile or ScriptRef</td>
              <td>The Script element that specifies the logic to be executed. The script is passed
                a list of paths found under the base path and must return the paths to delete as a
                <tt>java.util.List&lt;<a href="../log4j-core/apidocs/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html">PathWithAttributes</a>&gt;</tt>.
                See also the <a href="filters.html#Script">ScriptFilter</a> documentation for an example of
                how ScriptFiles and ScriptRefs can be configured.
              </td>
            </tr>
          </table>
          <a name="ScriptParameters"/>
          <table>
            <caption align="top">Script Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>basePath</td>
              <td><tt>java.nio.file.Path</tt></td>
              <td>The directory from where the Delete action started scanning for
                 files to delete. Can be used to relativize the paths in the pathList.</td>
            </tr>
            <tr>
              <td>pathList</td>
              <td><tt>java.util.List&lt;<a href="../log4j-core/apidocs/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html">PathWithAttributes</a>&gt;</tt></td>
              <td>The list of paths found under the base path up to the specified max depth,
                sorted most recently modified files first.
                The script is free to modify and return this list.</td>
            </tr>
            <tr>
              <td>statusLogger</td>
              <td>StatusLogger</td>
              <td>The StatusLogger that can be used to log internal events during script execution.</td>
            </tr>
            <tr>
              <td>configuration</td>
              <td>Configuration</td>
              <td>The Configuration that owns this ScriptCondition.</td>
            </tr>
            <tr>
              <td>substitutor</td>
              <td>StrSubstitutor</td>
              <td>The StrSubstitutor used to replace lookup variables.</td>
            </tr>
            <tr>
              <td>?</td>
              <td>String</td>
              <td>Any properties declared in the configuration.</td>
            </tr>
          </table>
          <p>
            Below is a sample configuration that uses a RollingFileAppender with the cron
            triggering policy configured to trigger every day at midnight.
            Archives are stored in a directory based on the current year and month.
            The script returns a list of rolled over files under the base directory dated Friday the 13th.
            The Delete action will delete all files returned by the script.
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace" name="MyApp" packages="">
  <Properties>
    <Property name="baseDir">logs</Property>
  </Properties>
  <Appenders>
    <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
          filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyyMMdd}.log.gz">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
      <CronTriggeringPolicy schedule="0 0 0 * * ?"/>
      <DefaultRolloverStrategy>
        <Delete basePath="${baseDir}" maxDepth="2">
          <ScriptCondition>
            <Script name="superstitious" language="groovy"><![CDATA[
                import java.nio.file.*;

                def result = [];
                def pattern = ~/\d*\/app-(\d*)\.log\.gz/;

                pathList.each { pathWithAttributes ->
                  def relative = basePath.relativize pathWithAttributes.path
                  statusLogger.trace 'SCRIPT: relative path=' + relative + " (base=$basePath)";

                  // remove files dated Friday the 13th

                  def matcher = pattern.matcher(relative.toString());
                  if (matcher.find()) {
                    def dateString = matcher.group(1);
                    def calendar = Date.parse("yyyyMMdd", dateString).toCalendar();
                    def friday13th = calendar.get(Calendar.DAY_OF_MONTH) == 13 \
                                  && calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY;
                    if (friday13th) {
                      result.add pathWithAttributes;
                      statusLogger.trace 'SCRIPT: deleting path ' + pathWithAttributes;
                    }
                  }
                }
                statusLogger.trace 'SCRIPT: returning ' + result;
                result;
              ]] >
            </Script>
          </ScriptCondition>
        </Delete>
      </DefaultRolloverStrategy>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>

			<a name="RollingRandomAccessFileAppender" />
			<subsection name="RollingRandomAccessFileAppender">
				<p>
					The RollingRandomAccessFileAppender is similar to the standard
					<a href="#RollingFileAppender">RollingFileAppender</a>
					except it is always buffered (this cannot be switched off) and
					internally it uses a <tt>ByteBuffer + RandomAccessFile</tt>
					instead of a <tt>BufferedOutputStream</tt>.
					We saw a 20-200% performance improvement compared to
					RollingFileAppender with "bufferedIO=true"
					in our <a href="../performance.html#whichAppender">measurements</a>.

					The RollingRandomAccessFileAppender writes to the File named in the
					fileName parameter and rolls the file over according the
					TriggeringPolicy and the RolloverPolicy.

					Similar to the RollingFileAppender, RollingRandomAccessFileAppender uses a RollingRandomAccessFileManager
					to actually perform the file I/O and perform the rollover. While RollingRandomAccessFileAppender
					from different Configurations cannot be shared, the RollingRandomAccessFileManagers can be
					if the Manager is accessible. For example, two web applications in a servlet
					container can have their own configuration and safely write to the
					same file if Log4j is in a ClassLoader that is common to both of them.
				</p>
				<p>
					A RollingRandomAccessFileAppender requires a
					<a href="#TriggeringPolicies">TriggeringPolicy</a> and a
					<a href="#RolloverStrategies">RolloverStrategy</a>.
					The triggering policy determines if a rollover should be performed
					while the RolloverStrategy defines how the rollover should be done.
					If no RolloverStrategy is configured, RollingRandomAccessFileAppender will use the
					<a href="#DefaultRolloverStrategy">DefaultRolloverStrategy</a>.
            Since log4j-2.5, a <a href="#CustomDeleteOnRollover">custom delete action</a> can be configured in the
            DefaultRolloverStrategy to run at rollover.
				</p>
				<p>
					File locking is not supported by the RollingRandomAccessFileAppender.
				</p>
				<table>
          <caption align="top">RollingRandomAccessFileAppender Parameters</caption>
          <tr>
						<th>Parameter Name</th>
						<th>Type</th>
						<th>Description</th>
					</tr>
          <tr>
						<td>append</td>
						<td>boolean</td>
						<td>When true - the default, records will be appended to the end
							of the file. When set to false,
							the file will be cleared before
							new records are written.
						</td>
					</tr>
          <tr>
						<td>filter</td>
						<td>Filter</td>
						<td>A Filter to determine if the event should be handled by this
							Appender. More than one Filter
							may be used by using a
							CompositeFilter.
						</td>
					</tr>
          <tr>
						<td>fileName</td>
						<td>String</td>
						<td>The name of the file to write to. If the file, or any of its
							parent directories, do not exist,
							they will be created.
						</td>
					</tr>
          <tr>
						<td>filePattern</td>
						<td>String</td>
						<td>
							The pattern of the file name of the archived log file. The format
							of the pattern should is
							dependent on the RolloverPolicy that is
							used. The DefaultRolloverPolicy
							will accept both
							a date/time
							pattern compatible with
							<a
								href="http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html">
								SimpleDateFormat</a>

							and/or a %i which represents an integer counter. The pattern
							also supports interpolation at
							runtime so any of the Lookups (such
							as the
							<a href="./lookups.html#DateLookup">DateLookup</a>
							can
							be included in the pattern.
						</td>
					</tr>
          <tr>
						<td>immediateFlush</td>
						<td>boolean</td>
		              <td><p>When set to true - the default, each write will be followed by a flush.
		                This will guarantee the data is written
		                to disk but could impact performance.</p>
		                <p>Flushing after every write is only useful when using this
						appender with synchronous loggers. Asynchronous loggers and
						appenders will automatically flush at the end of a batch of events,
						even if immediateFlush is set to false. This also guarantees
						the data is written to disk but is more efficient.</p>
		              </td>
					</tr>
          <tr>
                      <td>bufferSize</td>
                      <td>int</td>
                      <td>The buffer size, defaults to 262,144 bytes (256 * 1024).</td>
                    </tr>
          <tr>
						<td>layout</td>
						<td>Layout</td>
						<td>The Layout to use to format the LogEvent. If no layout is supplied the default pattern layout
              of "%m%n" will be used.</td>
					</tr>

          <tr>
						<td>name</td>
						<td>String</td>
						<td>The name of the Appender.</td>
					</tr>
          <tr>
						<td>policy</td>
						<td>TriggeringPolicy</td>
						<td>The policy to use to determine if a rollover should occur.
						</td>
					</tr>
          <tr>
						<td>strategy</td>
						<td>RolloverStrategy</td>
						<td>The strategy to use to determine the name and location of the
							archive file.
						</td>
					</tr>
          <tr>
            <td>ignoreExceptions</td>
            <td>boolean</td>
            <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
              internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
              caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
              <a href="#FailoverAppender">FailoverAppender</a>.</td>
          </tr>
				</table>
				<a name="FRFA_TriggeringPolicies" />
				<h4>Triggering Policies</h4>
				<p>
					See
					<a href="#TriggeringPolicies">RollingFileAppender Triggering Policies</a>.
				</p>
				<a name="FRFA_RolloverStrategies" />
				<h4>Rollover Strategies</h4>
				<p>
					See
					<a href="#RolloverStrategies">RollingFileAppender Rollover Strategies</a>.
				</p>

				<p>
					Below is a sample configuration that uses a RollingRandomAccessFileAppender
					with both the time and size based
					triggering policies, will create
					up to 7 archives on the same day (1-7) that
					are stored in a
					directory
					based on the current year and month, and will compress
					each
					archive using gzip:
        </p>

					<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log"
                 filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
    </RollingRandomAccessFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingRandomAccessFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
				<p>
					This second example shows a rollover strategy that will keep up to
					20 files before removing them.
        </p>
					<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log"
                 filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="20"/>
    </RollingRandomAccessFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingRandomAccessFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
				<p>
					Below is a sample configuration that uses a RollingRandomAccessFileAppender
					with both the time and size based
					triggering policies, will create
					up to 7 archives on the same day (1-7) that
					are stored in a
					directory
					based on the current year and month, and will compress
					each
					archive using gzip and will roll every 6 hours when the hour is
					divisible
					by 6:
        </p>

					<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log"
                 filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
    </RollingRandomAccessFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingRandomAccessFile"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
			</subsection>
        <a name="RoutingAppender"/>
        <subsection name="RoutingAppender">
           <p>
             The RoutingAppender evaluates LogEvents and then routes them to a subordinate Appender. The target
             Appender may be an appender previously configured and may be referenced by its name or the
             Appender can be dynamically created as needed. The RoutingAppender should be configured after any
             Appenders it references to allow it to shut down properly.
           </p>
           <p>
             You can also configure a RoutingAppender with scripts: you can run a script when the appender starts
             and when a route is chosen for an log event.
           </p>
          <table>
            <caption align="top">RoutingAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>Filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>RewritePolicy</td>
              <td>RewritePolicy</td>
              <td>The RewritePolicy that will manipulate the LogEvent.</td>
            </tr>
            <tr>
              <td>Routes</td>
              <td>Routes</td>
              <td>Contains one or more Route declarations to identify the criteria for choosing Appenders.</td>
            </tr>
            <tr>
              <td>Script</td>
              <td>Script</td>
              <td>
                <p>
                  This Script runs when Log4j starts the RoutingAppender and returns a String Route key to
                  determine the default Route.
                </p>
                <p>
                  This script is passed the following variables:
                </p>
                <table>
                  <caption align="top">RoutingAppender Script Parameters</caption>
                  <tr>
                    <th>Parameter Name</th>
                    <th>Type</th>
                    <th>Description</th>
                  </tr>
                  <tr>
                    <td>configuration</td>
                    <td>Configuration</td>
                    <td>The active Configuration.</td>
                  </tr>
                  <tr>
                    <td>staticVariables</td>
                    <td>Map</td>
                    <td>
                      A Map shared between all script invocations for this appender instance. This is
                      the same map passed to the Routes Script.
                    </td>
                  </tr>
                </table>
              </td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
          </table>
          <p>
            In this example, the script causes the "ServiceWindows" route to be the default route on Windows and
            "ServiceOther" on all other operating systems. Note that the List Appender is one of our test appenders,
            any appender can be used, it is only used as a shorthand.
          </p>
<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="RoutingTest">
  <Appenders>
    <Routing name="Routing">
      <Script name="RoutingInit" language="JavaScript"><![CDATA[
        importPackage(java.lang);
        System.getProperty("os.name").search("Windows") > -1 ? "ServiceWindows" : "ServiceOther";]]]]><![CDATA[>
      </Script>
      <Routes>
        <Route key="ServiceOther">
          <List name="List1" />
        </Route>
        <Route key="ServiceWindows">
          <List name="List2" />
        </Route>
      </Routes>
    </Routing>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Routing" />
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <h4>Routes</h4>
            <p>
              The Routes element accepts a single attribute named "pattern". The pattern is evaluated
              against all the registered Lookups and the result is used to select a Route. Each Route may be
              configured with a key. If the key matches the result of evaluating the pattern then that Route
              will be selected. If no key is specified on a Route then that Route is the default. Only one Route
              can be configured as the default.
            </p>
            <p>
              The Routes element may contain a Script child element. If specified, the Script is run for each
              log event and returns the String Route key to use.
            </p>
            <p>
              You must specify either the pattern attribute or the Script element, but not both.
            </p>
            <p>
              Each Route must reference an Appender. If the Route contains a ref attribute then the
              Route will reference an Appender that was defined in the configuration. If the Route contains an
              Appender definition then an Appender will be created within the context of the RoutingAppender and
              will be reused each time a matching Appender name is referenced through a Route.
            </p>
            <p>
              This script is passed the following variables:
            </p>
            <table>
              <caption align="top">RoutingAppender Routes Script Parameters</caption>
              <tr>
                <th>Parameter Name</th>
                <th>Type</th>
                <th>Description</th>
              </tr>
              <tr>
                <td>configuration</td>
                <td>Configuration</td>
                <td>The active Configuration.</td>
              </tr>
              <tr>
                <td>staticVariables</td>
                <td>Map</td>
                <td>
                  A Map shared between all script invocations for this appender instance. This is
                  the same map passed to the Routes Script.
                </td>
              </tr>
              <tr>
                <td>logEvent</td>
                <td>LogEvent</td>
                <td>The log event.</td>
              </tr>
            </table>
            <p>
              In this example, the script runs for each log event and picks a route based on the presence of a
              Marker named "AUDIT".
            </p>
<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="RoutingTest">
  <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT" />
    <Flume name="AuditLogger" compress="true">
      <Agent host="192.168.10.101" port="8800"/>
      <Agent host="192.168.10.102" port="8800"/>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
    </Flume>
    <Routing name="Routing">
      <Routes>
        <Script name="RoutingInit" language="JavaScript"><![CDATA[
          if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("AUDIT")) {
                return "AUDIT";
            } else if (logEvent.getContextMap().containsKey("UserId")) {
                return logEvent.getContextMap().get("UserId");
            }
            return "STDOUT";]]]]><![CDATA[>
        </Script>
        <Route>
          <RollingFile
              name="Rolling-${mdc:UserId}"
              fileName="${mdc:UserId}.log"
              filePattern="${mdc:UserId}.%i.log.gz">
            <PatternLayout>
              <pattern>%d %p %c{1.} [%t] %m%n</pattern>
            </PatternLayout>
            <SizeBasedTriggeringPolicy size="500" />
          </RollingFile>
        </Route>
        <Route ref="AuditLogger" key="AUDIT"/>
        <Route ref="STDOUT" key="STDOUT"/>
      </Routes>
      <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/>
    </Routing>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Routing" />
    </Root>
  </Loggers>
</Configuration>
]]></pre>
          <h4>Purge Policy</h4>
          <p>The RoutingAppender can be configured with a PurgePolicy whose purpose is to stop and remove dormant
            Appenders that have been dynamically created by the RoutingAppender. Log4j currently provides the
            IdlePurgePolicy as the only PurgePolicy available for cleaning up the Appenders. The IdlePurgePolicy
            accepts 2 attributes; timeToLive, which is the number of timeUnits the Appender should survive without
            having any events sent to it, and timeUnit, the String representation of java.util.concurrent.TimeUnit
            which is used with the timeToLive attribute.</p>
          <p>
            Below is a sample configuration that uses a RoutingAppender to route all Audit events to
            a FlumeAppender and all other events will be routed to a RollingFileAppender that captures only
            the specific event type. Note that the AuditAppender was predefined while the RollingFileAppenders
            are created as needed.
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Flume name="AuditLogger" compress="true">
      <Agent host="192.168.10.101" port="8800"/>
      <Agent host="192.168.10.102" port="8800"/>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
    </Flume>
    <Routing name="Routing">
      <Routes pattern="$${sd:type}">
        <Route>
          <RollingFile name="Rolling-${sd:type}" fileName="${sd:type}.log"
                       filePattern="${sd:type}.%i.log.gz">
            <PatternLayout>
              <pattern>%d %p %c{1.} [%t] %m%n</pattern>
            </PatternLayout>
            <SizeBasedTriggeringPolicy size="500" />
          </RollingFile>
        </Route>
        <Route ref="AuditLogger" key="Audit"/>
      </Routes>
      <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/>
    </Routing>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Routing"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="SMTPAppender"/>
        <subsection name="SMTPAppender">
          <p>
            Sends an e-mail when a specific logging event occurs, typically on errors or fatal errors.
          </p>
          <p>
            The number of logging events delivered in this e-mail depend on the value of
            <b>BufferSize</b> option. The <code>SMTPAppender</code> keeps only the last
            <code>BufferSize</code> logging events in its cyclic buffer. This keeps
            memory requirements at a reasonable level while still delivering useful
            application context. All events in the buffer are included in the email.
            The buffer will contain the most recent events of level TRACE to WARN
            preceding the event that triggered the email.
          </p>
          <p>
            The default behavior is to trigger sending an email whenever an ERROR or higher
            severity event is logged and to format it as HTML. The circumstances on when the
            email is sent can be controlled by setting one or more filters on the Appender.
            As with other Appenders, the formatting can be controlled by specifying a Layout
            for the Appender.
          </p>
          <table>
            <caption align="top">SMTPAppender Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>bcc</td>
              <td>String</td>
              <td>The comma-separated list of BCC email addresses.</td>
            </tr>
            <tr>
              <td>cc</td>
              <td>String</td>
              <td>The comma-separated list of CC email addresses.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>integer</td>
              <td>The maximum number of log events to be buffered for inclusion in the message. Defaults to 512.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
                may be used by using a CompositeFilter.
              </td>
            </tr>
            <tr>
              <td>from</td>
              <td>String</td>
              <td>The email address of the sender.</td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>The Layout to use to format the LogEvent. If no layout is supplied <a href="layouts.html#HTMLLayout">HTML layout</a> will be used.</td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>replyTo</td>
              <td>String</td>
              <td>The comma-separated list of reply-to email addresses.</td>
            </tr>
            <tr>
              <td>smtpDebug</td>
              <td>boolean</td>
              <td>When set to true enables session debugging on STDOUT. Defaults to false.</td>
            </tr>
            <tr>
              <td>smtpHost</td>
              <td>String</td>
              <td>The SMTP hostname to send to. This parameter is required.</td>
            </tr>
            <tr>
              <td>smtpPassword</td>
              <td>String</td>
              <td>The password required to authenticate against the SMTP server.</td>
            </tr>
            <tr>
              <td>smtpPort</td>
              <td>integer</td>
              <td>The SMTP port to send to. </td>
            </tr>
            <tr>
              <td>smtpProtocol</td>
              <td>String</td>
              <td>The SMTP transport protocol (such as "smtps", defaults to "smtp").</td>
            </tr>
            <tr>
              <td>smtpUsername</td>
              <td>String</td>
              <td>The username required to authenticate against the SMTP server.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>to</td>
              <td>String</td>
              <td>The comma-separated list of recipient email addresses.</td>
            </tr>
          </table>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <SMTP name="Mail" subject="Error Log" to="errors@logging.apache.org" from="test@logging.apache.org"
          smtpHost="localhost" smtpPort="25" bufferSize="50">
    </SMTP>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Mail"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="ScriptAppenderSelector"/>
        <subsection name="ScriptAppenderSelector">
          <p>
            When the configuration is built, the <code>ScriptAppenderSelector</code> appender calls a <code>Script</code>
            to compute an appender name. Log4j then creates one of the appender named listed under
            <code>AppenderSet</code> using the name of the <code>ScriptAppenderSelector</code>. After configuration, Log4j
            ignores the <code>ScriptAppenderSelector</code>. Log4j only builds the one selected appender from the
            configuration tree, and ignores other <code>AppenderSet</code> child nodes.
          </p>
          <p>
            In the following example, the script returns the name "List2". The appender name is recorded under
            the name of the <code>ScriptAppenderSelector</code>, not the name of the selected appender, in this example,
            "SelectIt".
          </p>
<pre class="prettyprint linenums"><![CDATA[<Configuration status="WARN" name="ScriptAppenderSelectorExample">
  <Appenders>
    <ScriptAppenderSelector name="SelectIt">
      <Script language="JavaScript"><![CDATA[
        importPackage(java.lang);
        System.getProperty("os.name").search("Windows") > -1 ? "MyCustomWindowsAppender" : "MySyslogAppender";]]]]><![CDATA[>
      </Script>
      <AppenderSet>
        <MyCustomWindowsAppender name="MyAppender" ... />
        <SyslogAppender name="MySyslog" ... />
      </AppenderSet>
    </ScriptAppenderSelector>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="SelectIt" />
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>
        <a name="SocketAppender"/>
        <subsection name="SocketAppender">
          <p>
            The <code>SocketAppender</code> is an OutputStreamAppender that writes its output to a remote destination
            specified by a host and port. The data can be sent over either TCP or UDP and can be sent in any format.
            The default format is to send a Serialized LogEvent. Log4j 2 contains a SocketServer which is capable
            of receiving serialized LogEvents and routing them through the logging system on the server. You can optionally
            secure communication with SSL.
          </p>
          <table>
            <caption align="top"><code>SocketAppender</code> Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>host</td>
              <td>String</td>
              <td>The name or address of the system that is listening for log events. This parameter is required.</td>
            </tr>
            <tr>
              <td>port</td>
              <td>integer</td>
              <td>The port on the host that is listening for log events. This parameter must be specified.</td>
            </tr>
            <tr>
              <td>protocol</td>
              <td>String</td>
              <td>"TCP" (default), "SSL" or "UDP".</td>
            </tr>
            <tr>
              <td>SSL</td>
              <td>SslConfiguration</td>
              <td>Contains the configuration for the KeyStore and TrustStore.</td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>immediateFail</td>
              <td>boolean</td>
              <td>When set to true, log events will not wait to try to reconnect and will fail immediately if the
              socket is not available.</td>
            </tr>
            <tr>
              <td>immediateFlush</td>
              <td>boolean</td>
              <td>When set to true - the default, each write will be followed by a flush.
                This will guarantee the data is written
                to disk but could impact performance.</td>
            </tr>
            <tr>
              <td>bufferedIO</td>
              <td>boolean</td>
              <td>When true - the default, events are written to a buffer and the data will be written to
                the socket when the buffer is full or, if immediateFlush is set, when the record is written.</td>
            </tr>
            <tr>
              <td>bufferSize</td>
              <td>int</td>
              <td>When bufferedIO is true, this is the buffer size, the default is 8192 bytes.</td>
            </tr>
            <tr>
              <td>layout</td>
              <td>Layout</td>
              <td>The Layout to use to format the LogEvent. The default is SerializedLayout.</td>
            </tr>
            <tr>
              <td>reconnectionDelayMillis</td>
              <td>integer</td>
              <td>If set to a value greater than 0, after an error the SocketManager will attempt to reconnect to
                the server after waiting the specified number of milliseconds. If the reconnect fails then
                an exception will be thrown (which can be caught by the application if <code>ignoreExceptions</code> is
                set to <code>false</code>).</td>
            </tr>
            <tr>
              <td>connectTimeoutMillis</td>
              <td>integer</td>
              <td>The connect timeout in milliseconds. The default is 0 (infinite timeout, like Socket.connect()
                methods).</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
          </table>

          <p>
            This is an unsecured TCP configuration:
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Socket name="socket" host="localhost" port="9500">
      <SerializedLayout />
    </Socket>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="socket"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>

          <p>
            This is a secured SSL configuration:
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Socket name="socket" host="localhost" port="9500">
      <SerializedLayout />
      <SSL>
        <KeyStore location="log4j2-keystore.jks" password="changeme"/>
        <TrustStore location="truststore.jks" password="changeme"/>
      </SSL>
    </Socket>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="socket"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>

        </subsection>
        <a name="SyslogAppender"/>
        <subsection name="SyslogAppender">
          <p>
            The <code>SyslogAppender</code> is a <code>SocketAppender</code> that writes its output to a remote destination
            specified by a host and port in a format that conforms with either the BSD Syslog format or the RFC 5424
            format. The data can be sent over either TCP or UDP.
          </p>
          <table>
            <caption align="top"><code>SyslogAppender</code> Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>advertise</td>
              <td>boolean</td>
              <td>Indicates whether the appender should be advertised.</td>
            </tr>
            <tr>
              <td>appName</td>
              <td>String</td>
              <td>The value to use as the APP-NAME in the RFC 5424 syslog record.</td>
            </tr>
            <tr>
              <td>charset</td>
              <td>String</td>
              <td>The character set to use when converting the syslog String to a byte array. The String must be
                a valid <a href="http://download.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html">Charset</a>.
                If not specified, the default system Charset will be used.</td>
            </tr>
            <tr>
              <td>connectTimeoutMillis</td>
              <td>integer</td>
              <td>The connect timeout in milliseconds. The default is 0 (infinite timeout, like Socket.connect()
                methods).</td>
            </tr>
            <tr>
              <td>enterpriseNumber</td>
              <td>integer</td>
              <td>The IANA enterprise number as described in
                <a href="http://tools.ietf.org/html/rfc5424#section-7.2.2">RFC 5424</a></td>
            </tr>
            <tr>
              <td>filter</td>
              <td>Filter</td>
              <td>A Filter to determine if the event should be handled by this Appender. More than one Filter
              may be used by using a CompositeFilter.</td>
            </tr>
            <tr>
              <td>facility</td>
              <td>String</td>
              <td>The facility is used to try to classify the message. The facility option must be set to one of
                "KERN", "USER", "MAIL", "DAEMON", "AUTH", "SYSLOG", "LPR", "NEWS", "UUCP", "CRON", "AUTHPRIV",
                "FTP", "NTP", "AUDIT", "ALERT", "CLOCK", "LOCAL0", "LOCAL1", "LOCAL2", "LOCAL3", "LOCAL4", "LOCAL5",
                "LOCAL6", or "LOCAL7". These values may be specified as upper or lower case characters.</td>
            </tr>
            <tr>
              <td>format</td>
              <td>String</td>
              <td>If set to "RFC5424" the data will be formatted in accordance with RFC 5424. Otherwise, it will
                be formatted as a BSD Syslog record. Note that although BSD Syslog records are required to be
                1024 bytes or shorter the SyslogLayout does not truncate them. The RFC5424Layout also does not
                truncate records since the receiver must accept records of up to 2048 bytes and may accept records
                that are longer.</td>
            </tr>
            <tr>
              <td>host</td>
              <td>String</td>
              <td>The name or address of the system that is listening for log events. This parameter is required.</td>
            </tr>
            <tr>
              <td>id</td>
              <td>String</td>
              <td>The default structured data id to use when formatting according to RFC 5424. If the LogEvent contains
                a StructuredDataMessage the id from the Message will be used instead of this value.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>The default is <code>true</code>, causing exceptions encountered while appending events to be
                internally logged and then ignored. When set to <code>false</code> exceptions will be propagated to the
                caller, instead. You must set this to <code>false</code> when wrapping this Appender in a
                <a href="#FailoverAppender">FailoverAppender</a>.</td>
            </tr>
            <tr>
              <td>immediateFail</td>
              <td>boolean</td>
              <td>When set to true, log events will not wait to try to reconnect and will fail immediately if the
                socket is not available.</td>
            </tr>
            <tr>
              <td>immediateFlush</td>
              <td>boolean</td>
              <td>When set to true - the default, each write will be followed by a flush.
                This will guarantee the data is written
                to disk but could impact performance.</td>
            </tr>
            <tr>
              <td>includeMDC</td>
              <td>boolean</td>
              <td>Indicates whether data from the ThreadContextMap will be included in the RFC 5424 Syslog record.
                Defaults to true.</td>
            </tr>
            <tr>
              <td>Layout</td>
              <td>Layout</td>
              <td>A custom layout which overrides the <code>format</code> setting.</td>
            </tr>
            <tr>
              <td>loggerFields</td>
              <td>List of KeyValuePairs</td>
              <td>Allows arbitrary PatternLayout patterns to be included as specified ThreadContext fields; no default
                specified. To use, include a &gt;LoggerFields&lt; nested element, containing one or more
                &gt;KeyValuePair&lt; elements. Each &gt;KeyValuePair&lt; must have a key attribute, which
                specifies the key name which will be used to identify the field within the MDC Structured Data element,
                and a value attribute, which specifies the PatternLayout pattern to use as the value.</td>
            </tr>
            <tr>
              <td>mdcExcludes</td>
              <td>String</td>
              <td>A comma separated list of mdc keys that should be excluded from the LogEvent. This is mutually
                exclusive with the mdcIncludes attribute. This attribute only applies to RFC 5424 syslog records.</td>
            </tr>
            <tr>
              <td>mdcIncludes</td>
              <td>String</td>
              <td>A comma separated list of mdc keys that should be included in the FlumeEvent. Any keys in the MDC
                not found in the list will be excluded. This option is mutually exclusive with the mdcExcludes
                attribute. This attribute only applies to RFC 5424 syslog records.</td>
            </tr>
            <tr>
              <td>mdcRequired</td>
              <td>String</td>
              <td>A comma separated list of mdc keys that must be present in the MDC. If a key is not present a
                LoggingException will be thrown. This attribute only applies to RFC 5424 syslog records.</td>
            </tr>
            <tr>
              <td>mdcPrefix</td>
              <td>String</td>
              <td>A string that should be prepended to each MDC key in order to distinguish it from event attributes.
                The default string is "mdc:". This attribute only applies to RFC 5424 syslog records.</td>
            </tr>
            <tr>
              <td>messageId</td>
              <td>String</td>
              <td>The default value to be used in the MSGID field of RFC 5424 syslog records. </td>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender.</td>
            </tr>
            <tr>
              <td>newLine</td>
              <td>boolean</td>
              <td>If true, a newline will be appended to the end of the syslog record. The default is false.</td>
            </tr>
            <tr>
              <td>port</td>
              <td>integer</td>
              <td>The port on the host that is listening for log events. This parameter must be specified.</td>
            </tr>
            <tr>
              <td>protocol</td>
              <td>String</td>
              <td>"TCP" or "UDP". This parameter is required.</td>
            </tr>
            <tr>
              <td>SSL</td>
              <td>SslConfiguration</td>
              <td>Contains the configuration for the KeyStore and TrustStore.</td>
            </tr>
            <tr>
              <td>reconnectionDelayMillis</td>
              <td>integer</td>
              <td>If set to a value greater than 0, after an error the SocketManager will attempt to reconnect to
                the server after waiting the specified number of milliseconds. If the reconnect fails then
                an exception will be thrown (which can be caught by the application if <code>ignoreExceptions</code> is
                set to <code>false</code>).</td>
            </tr>
          </table>
          <p>
            A sample syslogAppender configuration that is configured with two <code>SyslogAppender</code>s, one using the BSD
            format and one using RFC 5424.
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Syslog name="bsd" host="localhost" port="514" protocol="TCP"/>
    <Syslog name="RFC5424" format="RFC5424" host="localhost" port="8514"
            protocol="TCP" appName="MyApp" includeMDC="true"
            facility="LOCAL0" enterpriseNumber="18060" newLine="true"
            messageId="Audit" id="App"/>
  </Appenders>
  <Loggers>
    <Logger name="com.mycorp" level="error">
      <AppenderRef ref="RFC5424"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="bsd"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>

          <p>
            For SSL this appender writes its output to a remote destination specified by a host and port over SSL in
            a format that conforms with either the BSD Syslog format or the RFC 5424 format.
          </p>

            <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <TLSSyslog name="bsd" host="localhost" port="6514">
      <SSL>
        <KeyStore location="log4j2-keystore.jks" password="changeme"/>
        <TrustStore location="truststore.jks" password="changeme"/>
      </SSL>
    </TLSSyslog>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="bsd"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
        </subsection>

        <a name="JeroMQAppender"/>
        <subsection name="ZeroMQ/JeroMQ Appender">
          <p>
            The ZeroMQ appender uses the <a href="https://github.com/zeromq/jeromq">JeroMQ</a> library to send log
            events to one or more ZeroMQ endpoints.
          </p>
          <p>
            This is a simple JeroMQ configuration:
          </p>
          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="JeroMQAppenderTest" status="TRACE">
  <Appenders>
    <JeroMQ name="JeroMQAppender">
      <Property name="endpoint">tcp://*:5556</Property>
      <Property name="endpoint">ipc://info-topic</Property>
    </JeroMQ>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="JeroMQAppender"/>
    </Root>
  </Loggers>
</Configuration>]]></pre>
          <p>
            The table below describes all options. Please consult the JeroMQ and ZeroMQ documentation for details.
          </p>
          <table>
            <caption align="top">JeroMQ Parameters</caption>
            <tr>
              <th>Parameter Name</th>
              <th>Type</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>name</td>
              <td>String</td>
              <td>The name of the Appender. Required.</td>
            </tr>
            <tr>
              <td>Layout</td>
              <td>layout</td>
              <td>The Layout to use to format the LogEvent. If no layout is supplied the default pattern layout
                of "%m%n" will be used.</td>
            </tr>
            <tr>
              <td>Filters</td>
              <td>Filter</td>
              <td>The Filter(s) of the Appender.</td>
            </tr>
            <tr>
              <td>Properties</td>
              <td>Property[]</td>
              <td>One or more Property elements, named <code>endpoint</code>.</td>
            </tr>
            <tr>
              <td>ignoreExceptions</td>
              <td>boolean</td>
              <td>If true, exceptions will be logged and suppressed. If false errors will be logged and then passed to the application.</td>
            </tr>
            <tr>
              <td>affinity</td>
              <td>long</td>
              <td>The ZMQ_AFFINITY option. Defaults to 0.</td>
            </tr>
            <tr>
              <td>backlog</td>
              <td>long</td>
              <td>The ZMQ_BACKLOG option. Defaults to 100.</td>
            </tr>
            <tr>
              <td>delayAttachOnConnect</td>
              <td>boolean</td>
              <td>The ZMQ_DELAY_ATTACH_ON_CONNECT option. Defaults to false.</td>
            </tr>
            <tr>
              <td>identity</td>
              <td>byte[]</td>
              <td>The ZMQ_IDENTITY option. Defaults to none.</td>
            </tr>
            <tr>
              <td>ipv4Only</td>
              <td>boolean</td>
              <td>The ZMQ_IPV4ONLY option. Defaults to true.</td>
            </tr>
            <tr>
              <td>linger</td>
              <td>long</td>
              <td>The ZMQ_LINGER option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>maxMsgSize</td>
              <td>long</td>
              <td>The ZMQ_MAXMSGSIZE option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>rcvHwm</td>
              <td>long</td>
              <td>The ZMQ_RCVHWM option. Defaults to 1000.</td>
            </tr>
            <tr>
              <td>receiveBufferSize</td>
              <td>long</td>
              <td>The ZMQ_RCVBUF option. Defaults to 0.</td>
            </tr>
            <tr>
              <td>receiveTimeOut</td>
              <td>int</td>
              <td>The ZMQ_RCVTIMEO option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>reconnectIVL</td>
              <td>long</td>
              <td>The ZMQ_RECONNECT_IVL option. Defaults to 100.</td>
            </tr>
            <tr>
              <td>reconnectIVLMax</td>
              <td>long</td>
              <td>The ZMQ_RECONNECT_IVL_MAX option. Defaults to 0.</td>
            </tr>
            <tr>
              <td>sendBufferSize</td>
              <td>long</td>
              <td>The ZMQ_SNDBUF option. Defaults to 0.</td>
            </tr>
            <tr>
              <td>sendTimeOut</td>
              <td>int</td>
              <td>The ZMQ_SNDTIMEO option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>sndHwm</td>
              <td>long</td>
              <td>The ZMQ_SNDHWM option. Defaults to 1000.</td>
            </tr>
            <tr>
              <td>tcpKeepAlive</td>
              <td>int</td>
              <td>The ZMQ_TCP_KEEPALIVE option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>tcpKeepAliveCount</td>
              <td>long</td>
              <td>The ZMQ_TCP_KEEPALIVE_CNT option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>tcpKeepAliveIdle</td>
              <td>long</td>
              <td>The ZMQ_TCP_KEEPALIVE_IDLE option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>tcpKeepAliveInterval</td>
              <td>long</td>
              <td>The ZMQ_TCP_KEEPALIVE_INTVL option. Defaults to -1.</td>
            </tr>
            <tr>
              <td>xpubVerbose</td>
              <td>boolean</td>
              <td>The ZMQ_XPUB_VERBOSE option. Defaults to false.</td>
            </tr>
          </table>
        </subsection>

      </section>
  </body>
</document>
