<?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.
-->

#set($dollar = '$')

<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>Configuring Log4j 2</title>
        <author email="rgoers@apache.org">Ralph Goers</author>
    </properties>

    <body>
      <section name="Configuration">
        #if (!$alignedFileName)
            #set ($isPDF = true)
        #else
            #set ($isPDF = false)
        #end
        <p>Inserting log requests into the application code requires a fair
          amount of planning and effort. Observation shows that approximately 4
          percent of code is dedicated to logging. Consequently, even moderately
          sized applications will have thousands of logging statements embedded
          within their code.  Given their number, it becomes imperative to
          manage these log statements without the need to modify them manually.
        </p>
        <p>
          Configuration of Log4j 2 can be accomplished in 1 of 4 ways:
        </p>
          <ol>
            <li>Through a configuration file written in XML, JSON, or YAML.</li>
            <li>Programmatically, by creating a ConfigurationFactory and Configuration implementation.</li>
            <li>Programmatically, by calling the APIs exposed in the Configuration interface to add
              components to the default configuration.</li>
            <li>Programmatically, by calling methods on the internal Logger class.</li>
          </ol>
        <p>
          This page focuses primarily on configuring Log4j through a configuration file. Information on
          programmatically configuring Log4j can be found at <a href="./extending.html">Extending Log4j 2</a>.
        </p>
        <p>
          Note that unlike Log4j 1.x, the public Log4j 2 API does not expose methods to add, modify or remove
          appenders and filters or manipulate the configuration in any way.
        </p>
        <a name="AutomaticConfiguration"/>
        <subsection name="Automatic Configuration">
          <p>
            Log4j has the ability to automatically configure itself during initialization.
            When Log4j starts it will locate all the ConfigurationFactory plugins and arrange then in weighted
            order from highest to lowest. As delivered, Log4j contains three ConfigurationFactory implementations:
            one for JSON, one for YAML, and one for XML.
          </p>
            <ol>
              <li>Log4j will inspect the <code>"log4j.configurationFile"</code> system property and, if set,  will attempt to
                load the configuration using the <code>ConfigurationFactory</code> that matches the file
                extension.</li>
              <li>If no system property is set the YAML ConfigurationFactory will look for 
                <code>log4j2-test.yaml</code> or <code>log4j2-test.yml</code> in the classpath.</li>
              <li>If no such file is found the JSON ConfigurationFactory will look for
                <code>log4j2-test.json</code> or <code>log4j2-test.jsn</code> in the classpath.</li>
              <li>If no such file is found the XML ConfigurationFactory will look for
                <code>log4j2-test.xml</code> in the classpath.</li>
              <li>If a test file cannot be located the YAML ConfigurationFactory will look for
                <code>log4j2.yaml</code> or <code>log4j2.yml</code> on the classpath.</li>
              <li>If a YAML file cannot be located the JSON ConfigurationFactory will look for
                <code>log4j2.json</code> or <code>log4j2.jsn</code> on the classpath.</li>
              <li>If a JSON file cannot be located the XML ConfigurationFactory will try to locate
                <code>log4j2.xml</code> on the classpath.</li>
              <li>If no configuration file could be located the <code>DefaultConfiguration</code> will
                be used. This will cause logging output to go to the console.</li>
            </ol>
          <p>An example application named <code>MyApp</code> that uses log4j can be used to illustrate how
            this is done.
          </p>
<pre class="prettyprint linenums"><![CDATA[
import com.foo.Bar;

// Import log4j classes.
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public class MyApp {

    // Define a static logger variable so that it references the
    // Logger instance named "MyApp".
    private static final Logger logger = LogManager.getLogger(MyApp.class);

    public static void main(final String... args) {

        // Set up a simple configuration that logs on the console.

        logger.trace("Entering application.");
        Bar bar = new Bar();
        if (!bar.doIt()) {
            logger.error("Didn't do it.");
        }
        logger.trace("Exiting application.");
    }
}
]]></pre>
          <p>
            <code>MyApp</code> begins by importing log4j related classes. It
            then defines a static logger variable with the name <code>MyApp</code>
            which happens to be the fully qualified name of the class.
          </p>
          <p>
            <code>MyApp</code> uses the <code>Bar</code> class defined in the package<code>com.foo</code>.
          </p>
<pre class="prettyprint linenums"><![CDATA[
package com.foo;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public class Bar {
  static final Logger logger = LogManager.getLogger(Bar.class.getName());

  public boolean doIt() {
    logger.entry();
    logger.error("Did it again!");
    return logger.exit(false);
  }
}
]]></pre>
          <p>
            Log4j will provide a default configuration if it cannot locate a configuration file. The default
            configuration, provided in the DefaultConfiguration class, will set up:
          </p>
            <ul>
              <li>A <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/appender/ConsoleAppender.html">ConsoleAppender</a>
                attached to the root logger.</li>
              <li>A <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/layout/PatternLayout.html">PatternLayout</a>
                set to the pattern "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" attached to the ConsoleAppender</li>
            </ul>
          <p>
            Note that by default Log4j assigns the root logger to <code>Level.ERROR</code>.
          </p>
          <p>The output of MyApp would be similar to:
          </p>
<pre><![CDATA[
17:13:01.540 [main] ERROR com.foo.Bar - Did it again!
17:13:01.540 [main] ERROR MyApp - Didn't do it.
]]></pre>
          <p>
            As was described previously, Log4j will first attempt to configure itself from configuration files. A
            configuration equivalent to the default would look like:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>
]]></pre>
          <p>
            Once the file above is placed into the classpath as log4j2.xml you will get results identical to
            those listed above. Changing the root level to trace will result in results similar to:
          </p>
          <pre><![CDATA[
17:13:01.540 [main] TRACE MyApp - Entering application.
17:13:01.540 [main] TRACE com.foo.Bar - entry
17:13:01.540 [main] ERROR com.foo.Bar - Did it again!
17:13:01.540 [main] TRACE com.foo.Bar - exit with (false)
17:13:01.540 [main] ERROR MyApp - Didn't do it.
17:13:01.540 [main] TRACE MyApp - Exiting application.
]]></pre>
          <p>
            Note that status logging is disabled when the default configuration is used.
          </p>
          <p>
            Perhaps it is desired to eliminate all the TRACE output from everything except <code>com.foo.Bar</code>.
            Simply changing the log level would not accomplish the task. Instead, the solution is to
            add a new logger definition to the configuration:
          </p>
            <pre class="prettyprint linenums"><![CDATA[
<Logger name="com.foo.Bar" level="TRACE"/>
<Root level="ERROR">
  <AppenderRef ref="STDOUT">
</Root>
]]></pre>
          <p>
            With this configuration all log events from <code>com.foo.Bar</code> will be recorded while only error
            events will be recorded from all other components.
          </p>
        </subsection>
        <a name="Additivity"/>
        <subsection name="Additivity">
          <p>
            In the previous example all the events from <code>com.foo.Bar</code> were still written to the Console. This is
            because the logger for <code>com.foo.Bar</code> did not have any appenders configured while its parent did. In fact,
            the following configuration
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="com.foo.Bar" level="trace">
      <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>
]]></pre>
          <p>would result in</p>
          <pre><![CDATA[
17:13:01.540 [main] TRACE com.foo.Bar - entry
17:13:01.540 [main] TRACE com.foo.Bar - entry
17:13:01.540 [main] ERROR com.foo.Bar - Did it again!
17:13:01.540 [main] TRACE com.foo.Bar - exit (false)
17:13:01.540 [main] TRACE com.foo.Bar - exit (false)
17:13:01.540 [main] ERROR MyApp - Didn't do it.
]]></pre>
          <p>Notice that the trace messages from <code>com.foo.Bar</code> appear twice. This is because the appender associated
            with logger <code>com.foo.Bar</code> is first used, which writes the first instance to the Console. Next, the parent
            of <code>com.foo.Bar</code>, which in this case is the root logger, is referenced. The event is then passed to its
            appender, which is also writes to the Console, resulting in the second instance. This is known as
            additivity. While additivity can be quite a convenient feature (as in the first previous example where
            no appender reference needed to be configured), in many cases this behavior is considered undesirable
            and so it is possible to disable it by setting the additivity attribute on the logger to false:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="com.foo.Bar" level="trace" additivity="false">
      <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>
]]></pre>
          <p>
            Once an event reaches a logger with its additivity set to false the event will not be passed to
            any of its parent loggers, regardless of their additivity setting.
          </p>
        </subsection>
        <a name="AutomaticReconfiguration"/>
        <subsection name="Automatic Reconfiguration">
          <p>
            When configured from a File, Log4j has the ability to automatically detect changes to the configuration
            file and reconfigure itself. If the <code>monitorInterval</code> attribute is specified on the configuration 
            element and is set to a non-zero value then the file will be checked the next time a log event is evaluated
            and/or logged and the monitorInterval has elapsed since the last check. The example below shows how
            to configure the attribute so that the configuration file will be checked for changes only after at
            least 30 seconds have elapsed.  The minimum interval is 5 seconds.
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
...
</Configuration>
]]></pre>
        </subsection>
        <a name="ChainsawSupport"/>
        <subsection name="Chainsaw can automatically process your log files (Advertising appender configurations)">
          <p>
            Log4j provides the ability to 'advertise' appender configuration details for all file-based appenders as well
            as socket-based appenders.  For example, for file-based appenders, the file location and the pattern layout in the file
            are included in the advertisement.  Chainsaw and other external systems can discover these advertisements and
            use that information to intelligently process the log file.
          </p>
          <p>
            The mechanism by which an advertisement is exposed, as well as the advertisement format, is specific to each
            Advertiser implementation.  An external system which would like to work with a specific Advertiser implementation
            must understand how to locate the advertised configuration as well as the format of the advertisement.  For example,
            a 'database' Advertiser may store configuration details in a database table.  An external system can read
            that database table in order to discover the file location and the file format.
          </p>
          <p>
            Log4j provides one Advertiser implementation, a 'multicastdns' Advertiser, which advertises appender configuration
            details via IP multicast using the <a href="http://jmdns.sourceforge.net">http://jmdns.sourceforge.net</a> library.
          </p>
          <p>
            Chainsaw automatically discovers log4j's multicastdns-generated advertisements and displays those discovered
            advertisements in Chainsaw's Zeroconf tab (if the jmdns library is in Chainsaw's classpath).  To begin parsing and tailing
            a log file provided in an advertisement, just double-click the advertised entry in Chainsaw's Zeroconf tab.
            Currently, Chainsaw only supports FileAppender advertisements.
          </p>
          <p>
            To advertise an appender configuration:
          </p>
            <ul>
              <li>Add the JmDns library from <a href="http://jmdns.sourceforge.net">http://jmdns.sourceforge.net</a> to the application classpath</li>
              <li>Set the 'advertiser' attribute of the configuration element to 'multicastdns'</li>
              <li>Set the 'advertise' attribute on the appender element to 'true'</li>
              <li>If advertising a FileAppender-based configuration, set the 'advertiseURI' attribute on the appender element to an appropriate URI</li>
            </ul>
          <p>
            FileAppender-based configurations require an additional 'advertiseURI' attribute to be specified on the appender.
            The 'advertiseURI' attribute provides Chainsaw with information on how the file can be accessed.
            For example, the file may be remotely accessible to Chainsaw via ssh/sftp by specifying a Commons VFS
            (<a href="http://commons.apache.org/proper/commons-vfs/">http://commons.apache.org/proper/commons-vfs/</a>) sftp:// URI,
            an http:// URI may be used if the file is accessible through a web server, or a file:// URI can be specified
            if accessing the file from a locally-running instance of Chainsaw.
          </p>
          <p>
            Here is an example advertisement-enabled appender configuration which can be used by a locally-running Chainsaw to
            automatically tail the log file (notice the file:// advertiseURI):
          </p>
          <p>
            <b>Please note, you must add the JmDns library from <a href="http://jmdns.sourceforge.net">http://jmdns.sourceforge.net</a>
            to your application classpath in order to advertise with the 'multicastdns' advertiser.</b>
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration advertiser="multicastdns">
...
</Configuration>
<Appenders>
  <File name="File1" fileName="output.log" bufferedIO="false" advertiseURI="file://path/to/output.log" advertise="true">
  ...
  </File>
</Appenders>
]]></pre>
</subsection>
        <a name="ConfigurationSyntax"/>
        <subsection name="Configuration Syntax">
          <p>
            As the previous examples have shown as well as those to follow, Log4j allows you to easily
            redefine logging behavior without needing to modify your application. It is possible to
            disable logging for certain parts of the application, log only when specific criteria are met such
            as the action being performed for a specific user, route output to Flume or a log reporting system,
            etc. Being able to do this requires understanding the syntax of the configuration files.
          </p>
        <a name="XML"/>
          <h4>Configuration with XML</h4>
          <p>
            The configuration element in the XML file accepts several attributes:
          </p>
            <table>
              <tr>
                <th>Attribute Name</th>
                <th>Description</th>
              </tr>
              <tr>
                <td>advertiser</td>
                <td>(Optional) The Advertiser plugin name which will be used to advertise individual
                FileAppender or SocketAppender configurations.  The only Advertiser plugin provided is 'multicastdns".</td>
              </tr>
              <tr>
                <td>dest</td>
                <td>Either "err", which will send output to stderr, or a file path or URL.</td>
              </tr>

              <tr>
                <td>monitorInterval</td>
                <td>The minimum amount of time, in seconds, that must elapse before the file configuration
                  is checked for changes.</td>
              </tr>
              <tr>
                <td>name</td>
                <td>The name of the configuration.</td>
              </tr>
              <tr>
                <td>packages</td>
                <td>A comma separated list of package names to search for plugins. Plugins are only loaded
                  once per classloader so changing this value may not have any effect upon reconfiguration.</td>
              </tr>
              <tr>
                <td>schema</td>
                <td>Identifies the location for the classloader to located the XML Schema to use to validate
                  the configuration. Only valid when strict is set to true. If not set no schema validation
                  will take place.</td>
              </tr>
              <tr>
                 <td>shutdownHook</td>
                 <td>Specifies whether or not Log4j should automatically shutdown when the JVM shuts down. The
                 shutdown hook is enabled by default but may be disabled by setting this attribute to "disable"</td>
              </tr>
              <tr>
                <td>status</td>
                <td>The level of internal Log4j events that should be logged to the console.
                Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
                Log4j will log details about initialization, rollover and other internal actions to the status logger.
                Setting <tt>status="trace"</tt> is one of the first tools available to you if you need to
                troubleshoot log4j.</td>
              </tr>
              <tr>
                <td>strict</td>
                <td>Enables the use of the strict XML format. Not supported in JSON configurations.</td>
              </tr>
              <tr>
                <td>verbose</td>
                <td>Enables diagnostic information while loading plugins.</td>
              </tr>
            </table>
          <p>
            Log4j can be configured using two XML flavors; concise and strict. The concise format makes
            configuration very easy as the element names match the components they represent however it
            cannot be validated with an XML schema. For example, the ConsoleAppender is configured by
            declaring an XML element named Console under its parent appenders element. However, element
            and attribute names are are not case sensitive. In addition, attributes can either be specified
            as an XML attribute or as an XML element that has no attributes and has a text value. So
          </p>
          <pre class="prettyprint"><![CDATA[<PatternLayout pattern="%m%n"/>]]></pre>
          <p>and</p>
          <pre class="prettyprint"><![CDATA[
<PatternLayout>
  <Pattern>%m%n</Pattern>
</PatternLayout>]]></pre>
          <p>
            are equivalent.
          </p>
          <p>
            The file below represents the structure of an XML configuration, but note
            that the elements in italics below represent the concise element names that would appear in their place.
          </p>

          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>;
<Configuration>
  <Properties>
    <Property name="name1">value</property>
    <Property name="name2" value="value2"/>
  </Properties>
  <]]><i>filter</i>  ... <![CDATA[/>
  <Appenders>
    <]]><i>appender</i> ... <![CDATA[>
      <]]><i>filter</i>  ... <![CDATA[/>
    </]]><i>appender</i><![CDATA[>
    ...
  </Appenders>
  <Loggers>
    <Logger name="name1">
      <]]><i>filter</i>  ... <![CDATA[/>
    </Logger>
    ...
    <Root level="level">
      <AppenderRef ref="name"/>
    </Root>
  </Loggers>
</Configuration>
]]></pre>
          <p>
            See the many examples on this page for sample appender, filter and logger declarations.
          </p>
            <h5>Strict XML</h5>
          <p>
            In addition to the concise XML format above, Log4j allows configurations to be specified in a
            more "normal" XML manner that can be validated using an XML Schema. This is accomplished by
            replacing the friendly element names above with their object type as shown below. For example,
            instead of the ConsoleAppender being configuerd using an element named Console it is instead
            configured as an appender element with a type attribute containing "Console".
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>;
<Configuration>
  <Properties>
    <Property name="name1">value</property>
    <Property name="name2" value="value2"/>
  </Properties>
  <Filter type="type" ... />
  <Appenders>
    <Appender type="type" name="name">
      <Filter type="type" ... />
    </Appender>
    ...
  </Appenders>
  <Loggers>
    <Logger name="name1">
      <Filter type="type" ... />
    </Logger>
    ...
    <Root level="level">
      <AppenderRef ref="name"/>
    </Root>
  </Loggers>
</Configuration>
]]></pre>
          <p>
            Below is a sample configuration using the strict format.
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" strict="true" name="XMLConfigTest"
               packages="org.apache.logging.log4j.test">
  <Properties>
    <Property name="filename">target/test.log</Property>
  </Properties>
  <Filter type="ThresholdFilter" level="trace"/>

  <Appenders>
    <Appender type="Console" name="STDOUT">
      <Layout type="PatternLayout" pattern="%m MDC%X%n"/>
      <Filters>
        <Filter type="MarkerFilter" marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
        <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="DENY" onMismatch="ACCEPT"/>
      </Filters>
    </Appender>
    <Appender type="Console" name="FLOW">
      <Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/><!-- class and line number -->
      <Filters>
        <Filter type="MarkerFilter" marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
        <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
      </Filters>
    </Appender>
    <Appender type="File" name="File" fileName="${dollar}{filename}">
      <Layout type="PatternLayout">
        <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
      </Layout>
    </Appender>
    <Appender type="List" name="List">
    </Appender>
  </Appenders>

  <Loggers>
    <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
      <Filter type="ThreadContextMapFilter">
        <KeyValuePair key="test" value="123"/>
      </Filter>
      <AppenderRef ref="STDOUT"/>
    </Logger>

    <Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
      <AppenderRef ref="File"/>
    </Logger>

    <Root level="trace">
      <AppenderRef ref="List"/>
    </Root>
  </Loggers>

</Configuration>
]]></pre>
        <a name="JSON"/>
          <h4>Configuration with JSON</h4>
          <p>
            In addition to XML, Log4j can be configured using JSON. The JSON format is very similar to the
            concise XML format. Each key represents the name of a plugin and the key/value pairs associated
            with it are its attributes. Where a key contains more than a simple value it itself will be a
            subordinate plugin. In the example below, ThresholdFilter, Console, and PatternLayout are all
            plugins while the Console plugin will be assigned a value of STDOUT for its name attribute and the
            ThresholdFilter will be assigned a level of debug.
          </p>
          <pre class="prettyprint linenums"><![CDATA[
{ "configuration": { "status": "error", "name": "RoutingTest",
                     "packages": "org.apache.logging.log4j.test",
      "properties": {
        "property": { "name": "filename",
                      "value" : "target/rolling1/rollingtest-${dollar}${dollar}{sd:type}.log" }
      },
    "ThresholdFilter": { "level": "debug" },
    "appenders": {
      "Console": { "name": "STDOUT",
        "PatternLayout": { "pattern": "%m%n" }
      },
      "List": { "name": "List",
        "ThresholdFilter": { "level": "debug" }
      },
      "Routing": { "name": "Routing",
        "Routes": { "pattern": "${dollar}${dollar}{sd:type}",
          "Route": [
            {
              "RollingFile": {
                "name": "Rolling-${dollar}{sd:type}", "fileName": "${dollar}{filename}",
                "filePattern": "target/rolling1/test1-${dollar}{sd:type}.%i.log.gz",
                "PatternLayout": {"pattern": "%d %p %c{1.} [%t] %m%n"},
                "SizeBasedTriggeringPolicy": { "size": "500" }
              }
            },
            { "AppenderRef": "STDOUT", "key": "Audit"},
            { "AppenderRef": "List", "key": "Service"}
          ]
        }
      }
    },
    "loggers": {
      "logger": { "name": "EventLogger", "level": "info", "additivity": "false",
                  "AppenderRef": { "ref": "Routing" }},
      "root": { "level": "error", "AppenderRef": { "ref": "STDOUT" }}
    }
  }
}
]]></pre>
           <p>
            Note that in the RoutingAppender the Route element has been declared as an array. This is
            valid because each array element will be a Route component. This won't work for elements such as
            appenders and filters, where each element has a different name in the concise format. Appenders and
            filters can be defined as array elements if each appender or filter declares an attribute named "type"
            that contains the type of the appender. The following example illustrates this as well as how to
            declare multiple loggers as an array.
          </p>
           <pre class="prettyprint linenums"><![CDATA[
{ "configuration": { "status": "debug", "name": "RoutingTest",
                      "packages": "org.apache.logging.log4j.test",
      "properties": {
        "property": { "name": "filename",
                      "value" : "target/rolling1/rollingtest-${dollar}${dollar}{sd:type}.log" }
      },
    "ThresholdFilter": { "level": "debug" },
    "appenders": {
      "appender": [
         { "type": "Console", "name": "STDOUT", "PatternLayout": { "pattern": "%m%n" }},
         { "type": "List", "name": "List", "ThresholdFilter": { "level": "debug" }},
         { "type": "Routing",  "name": "Routing",
          "Routes": { "pattern": "${dollar}${dollar}{sd:type}",
            "Route": [
              {
                "RollingFile": {
                  "name": "Rolling-${dollar}{sd:type}", "fileName": "${dollar}{filename}",
                  "filePattern": "target/rolling1/test1-${dollar}{sd:type}.%i.log.gz",
                  "PatternLayout": {"pattern": "%d %p %c{1.} [%t] %m%n"},
                  "SizeBasedTriggeringPolicy": { "size": "500" }
                }
              },
              { "AppenderRef": "STDOUT", "key": "Audit"},
              { "AppenderRef": "List", "key": "Service"}
            ]
          }
        }
      ]
    },
    "loggers": {
      "logger": [
        { "name": "EventLogger", "level": "info", "additivity": "false",
          "AppenderRef": { "ref": "Routing" }},
        { "name": "com.foo.bar", "level": "error", "additivity": "false",
          "AppenderRef": { "ref": "Console" }}
      ],
      "root": { "level": "error", "AppenderRef": { "ref": "STDOUT" }}
    }
  }
}
]]></pre>
          <p>
            The JSON support uses the Jackson Data Processor to parse the JSON files. These dependencies must be added
            to a project that wants to use JSON for configuration:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>${jackson2Version}</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>${jackson2Version}</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>${jackson2Version}</version>
</dependency>
]]></pre>
        <a name="Loggers"/>
          <h4>Configuring loggers</h4>
          <p>
            An understanding of how loggers work in Log4j is critical before trying to configure them.
            Please reference the Log4j <a href="./architecture.html">architecture</a> if more information is
            required. Trying to configure Log4j without understanding those concepts will lead to frustration.
          </p>
          <p>
            A LoggerConfig is configured using the <code>logger</code> element. The <code>logger</code> element
            must have a name attribute specified, will usually have a level attribute specified and may
            also have an additivity attribute specified.  The level may be configured with one of TRACE,
            DEBUG, INFO, WARN, ERROR, ALL or OFF. If no level is specified it will default to ERROR. The
            additivity attribute may be assigned a value of true or false. If the attribute is omitted
            the default value of false will be used.
          </p>
          <p>
            A LoggerConfig (including the root LoggerConfig) can be configured with properties that will be added
            to the properties copied from the ThreadContextMap. These properties can be referenced from Appenders,
            Filters, Layouts, etc just as if they were part of the ThreadContext Map. The properties can contain
            variables that will be resolved either when the configuration is parsed or dynamically when each
            event is logged. See <a href="#PropertySubstitution">Property Substitution</a> for more information on
            using variables.
          </p>
          <p>
            The LoggerConfig may also be configured with one or more AppenderRef elements. Each appender
            referenced will become associated with the specified LoggerConfig. If multiple appenders
            are configured on the LoggerConfig each of them be called when processing logging events.
          </p>
          <p>
            <b><em>Every configuration must have a root logger</em></b>. If one is not configured the default root LoggerConfig,
            which has a level of ERROR and has a Console appender attached, will be used. The main differences
            between the root logger and other loggers are
          </p>
            <ol>
              <li>The root logger does not have a name attribute.</li>
              <li>The root logger does not support the additivity attribute since it has no parent.</li>
            </ol>
        <a name="Appenders"/>
          <h4>Configuring Appenders</h4>
          <p>
            An appender is configured either using the specific appender plugin's name or with an appender
            element and the type attibute containing the appender plugin's name. In addition each appender
            must have a name attribute specified with a value that is unique within the set of appenders.
            The name will be used by loggers to reference the appender as described in the previous section.
          </p>
          <p>
            Most appenders also support a layout to be configured (which again may be specified either
            using the specific Layout plugin's name as the element or with "layout" as the element name
            along with a type attribute that contains the layout plugin's name. The various appenders
            will contain other attributes or elements that are required for them to function properly.
          </p>
        <a name="Filters"/>
          <h4>Configuring Filters</h4>
          <p>
            Log4j allows a filter to be specified in any of 4 places:
          </p>
            <ol>
              <li>At the same level as the appenders, loggers and properties elements. These filters can accept
              or reject events before they have been passed to a LoggerConfig.</li>
              <li>In a logger element. These filters can accept or reject events for specific loggers.</li>
              <li>In an appender element. These filters can prevent or cause events to be processed by
                the appender.</li>
              <li>In an appender reference element. These filters are used to determine if a Logger should route
                the event to an appender.</li>
            </ol>
          <p>
            Although only a single <code>filter</code> element can be configured, that element may be the
            <code>filters</code> element which represents the CompositeFilter. The <code>filters</code> element
            allows any number of <code>filter</code> elements to be configured within it. The following example
            shows how multiple filters can be configured on the ConsoleAppender.
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="XMLConfigTest" packages="org.apache.logging.log4j.test">
  <Properties>
    <Property name="filename">target/test.log</Property>
  </Properties>
  <ThresholdFilter level="trace"/>

  <Appenders>
    <Console name="STDOUT">
      <PatternLayout pattern="%m MDC%X%n"/>
    </Console>
    <Console name="FLOW">
      <!-- this pattern outputs class name and line number -->
      <PatternLayout pattern="%C{1}.%M %m %ex%n"/>
      <filters>
        <MarkerFilter marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
        <MarkerFilter marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
      </filters>
    </Console>
    <File name="File" fileName="${dollar}{filename}">
      <PatternLayout>
        <pattern>%d %p %C{1.} [%t] %m%n</pattern>
      </PatternLayout>
    </File>
    <List name="List">
    </List>
  </Appenders>

  <Loggers>
    <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
      <ThreadContextMapFilter>
        <KeyValuePair key="test" value="123"/>
      </ThreadContextMapFilter>
      <AppenderRef ref="STDOUT"/>
    </Logger>

    <Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
      <Property name="user">${dollar}{sys:user.name}</Property>
      <AppenderRef ref="File">
        <ThreadContextMapFilter>
          <KeyValuePair key="test" value="123"/>
        </ThreadContextMapFilter>
      </AppenderRef>
      <AppenderRef ref="STDOUT" level="error"/>
    </Logger>

    <Root level="trace">
      <AppenderRef ref="List"/>
    </Root>
  </Loggers>

</Configuration>
]]></pre>
        </subsection>
        <a name="PropertySubstitution"/>
        <subsection name="Property Substitution">
          <p>
            Log4j 2 supports the ability to specify tokens in the configuration as references to properties defined
            elsewhere. Some of these properties will be resolved when the configuration file is interpreted while
            others may be passed to components where they will be evaluated at runtime. To accomplish this, Log4j
            uses variations of <a href="https://commons.apache.org/proper/commons-lang/">Apache Commons Lang</a>'s
            <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrSubstitutor.html">StrSubstitutor</a>
            and <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrLookup.html">StrLookup</a>
            classes. In a manner similar to Ant or Maven, this allows variables declared as <code>${dollar}{name}</code>
            to be resolved using properties declared in the configuration itself. For example, the following example
            shows the filename for the rolling file appender being declared as a property.
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="RoutingTest" packages="org.apache.logging.log4j.test">
  <Properties>
    <Property name="filename">target/rolling1/rollingtest-${dollar}${dollar}{sd:type}.log</Property>
  </Properties>
  <ThresholdFilter level="debug"/>

  <Appenders>
    <Console name="STDOUT">
      <PatternLayout pattern="%m%n"/>
    </Console>
    <List name="List">
      <ThresholdFilter level="debug"/>
    </List>
    <Routing name="Routing">
      <Routes pattern="${dollar}${dollar}{sd:type}">
        <Route>
          <RollingFile name="Rolling-${dollar}{sd:type}" fileName="${dollar}{filename}"
                       filePattern="target/rolling1/test1-${dollar}{sd:type}.%i.log.gz">
            <PatternLayout>
              <pattern>%d %p %c{1.} [%t] %m%n</pattern>
            </PatternLayout>
            <SizeBasedTriggeringPolicy size="500" />
          </RollingFile>
        </Route>
        <Route ref="STDOUT" key="Audit"/>
        <Route ref="List" key="Service"/>
      </Routes>
    </Routing>
  </Appenders>

  <Loggers>
    <Logger name="EventLogger" level="info" additivity="false">
      <AppenderRef ref="Routing"/>
    </Logger>

    <Root level="error">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>

</Configuration>
]]></pre>
          <p>
            While this is useful, there are many more places properties can originate from. To accommodate this,
            Log4j also supports the syntax <code>${dollar}{prefix:name}</code> where the prefix identifies tells Log4j
            that variable name should be evaluated in a specific context. The contexts that are built in to Logj4
            are:
          </p>
            <table>
              <tr>
                <th>Prefix</th>
                <th>Context</th>
              </tr>
              <tr>
                <td>bundle</td>
                <td>
                  Resource bundle. The format is <code>${dollar}{bundle:BundleName:BundleKey}</code>.
                  The bundle name follows package naming conventions, for example:
                  <code>${dollar}{bundle:com.domain.Messages:MyKey}</code>.
                </td>
              </tr>
              <tr>
                <td>ctx</td>
                <td>Thread Context Map (MDC)</td>
              </tr>
              <tr>
                <td>date</td>
                <td>Inserts the current date and/or time using the specified format</td>
              </tr>
              <tr>
                <td>env</td>
                <td>System environment variables</td>
              </tr>
              <tr>
                <td>jvmrunargs</td>
                <td>
                  A JVM input argument accessed through JMX, but not a main argument;
                  see <a class="javadoc" href="http://docs.oracle.com/javase/6/docs/api/java/lang/management/RuntimeMXBean.html#getInputArguments--">RuntimeMXBean.getInputArguments()</a>.
                  Not available on Android.</td>
              </tr>
              <tr>
                <td>main</td>
                <td>A value set with <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/MapLookup.html#setMainArguments-java.lang.String:A-">MapLookup.setMainArguments(String[])</a></td>
              </tr>
              <tr>
                <td>map</td>
                <td>A value from a MapMessage</td>
              </tr>
              <tr>
                <td>sd</td>
                <td>A value from a StructuredDataMessage. The key "id" will return the name of the StructuredDataId
                  without the enterprise number. The key "type" will return the message type. Other keys will
                  retrieve individual elements from the Map.</td>
              </tr>
              <tr>
                <td>sys</td>
                <td>System properties</td>
              </tr>
            </table>
          <p>
            A default property map can be declared in the configuration file. If the value cannot be located in
            the specified lookup the value in the default property map will be used. The default map is
            pre-populated with a value for "hostName" that is the current system's host name or IP address and
            the "contextName" with is the value of the current logging context.
          </p>
          <p>
            An interesting feature of StrLookup processing is that when a variable reference is declared with
            multiple leading '$' characters each time the variable is resolved the leading '$' is simply removed.
            In the previous example the "Routes" element is capable of resolving the variable at runtime. To allow
            this the prefix value is specified as a variable with two leading '$' characters. When the configuration
            file is first processed the first variable is simply removed. Thus, when the Routes element is evaluated
            at runtime it is the variable declaration "${dollar}{sd:type}" which causes the event to be inspected for a
            StructuredDataMessage and if one is present the value of its type attribute to be used as the routing key.
            Not all elements support resolving variables at runtime. Components that do will specifically call that
            out in their documentation.
          </p>
          <p>
            If no value is found for the key in the Lookup associated with the prefix then the value associated with
            the key in the properties declaration in the configuration file will be used. If no value is found
            the variable declaration will be returned as the value. Default values may be declared in the configuration
            by doing:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Properties>
    <Property name="type">Audit</property>
  </Properties>
  ...
</Configuration>
]]></pre>
          <p>
            <i>As a footnote, it is worth pointing out that the variables in the RollingFile appender declaration
            will also not be evaluated when the configuration is processed. This is simply because the resolution
            of the whole RollingFile element is deferred until a match occurs.
            See <a href="appenders.html#RoutingAppender">RoutingAppender</a> for more information.</i>
          </p>
        </subsection>
        <a name="XInclude"/>
        <subsection name="XInclude">
          <p>
            XML configuration files can include other files with <a href="http://www.xml.com/lpt/a/1009">XInclude</a>.
            Here is an example log4j2.xml file that includes two other files:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:xi="http://www.w3.org/2001/XInclude"
               status="warn" name="XIncludeDemo">
  <properties>
    <property name="filename">xinclude-demo.log</property>
  </properties>
  <ThresholdFilter level="debug"/>
  <xi:include href="log4j-xinclude-appenders.xml" />
  <xi:include href="log4j-xinclude-loggers.xml" />
</configuration>
]]></pre>
          <p>log4j-xinclude-appenders.xml:</p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<appenders>
  <Console name="STDOUT">
    <PatternLayout pattern="%m%n" />
  </Console>
  <File name="File" fileName="${dollar}{filename}" bufferedIO="true" immediateFlush="true">
    <PatternLayout>
      <pattern>%d %p %C{1.} [%t] %m%n</pattern>
    </PatternLayout>
  </File>
</appenders>
]]></pre>
          <p>log4j-xinclude-loggers.xml:</p>
          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<loggers>
  <logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
    <ThreadContextMapFilter>
      <KeyValuePair key="test" value="123" />
    </ThreadContextMapFilter>
    <AppenderRef ref="STDOUT" />
  </logger>

  <logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
    <AppenderRef ref="File" />
  </logger>

  <root level="error">
    <AppenderRef ref="STDOUT" />
  </root>
</loggers>
]]></pre>
        </subsection>
        <a name="StatusMessages"/>
        <subsection name="Status Messages">
          <table>
            <tr>
            <td>
            <b>Troubleshooting tip for the impatient:</b>
            <ul>
              <li>Before a configuration is found, status logger level can be controlled with system
              property <code>org.apache.logging.log4j.simplelog.StatusLogger.level</code>.</li>
              <li>After a configuration is found, status logger level can be controlled in the configuration
              file with the "status" attribute, for example: <code>&lt;Configuration status="trace"&gt;</code>.</li>
            </ul>
            </td>
            </tr>
          </table>
          <p>
            Just as it is desirable to be able to diagnose problems in applications, it is frequently necessary
            to be able to diagnose problems in the logging configuration or in the configured components. Since
            logging has not been configured, "normal" logging cannot be used during initialization. In addition,
            normal logging within appenders could create infinite recursion which Log4j will detect and cause
            the recursive events to be ignored. To accomodate this need, the Log4j 2 API includes a
            <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/status/StatusLogger.html">StatusLogger</a>.
            Components declare an instance of the StatusLogger similar to:
          </p>
          <pre class="prettyprint">protected final static Logger logger = StatusLogger.getLogger();</pre>
          <p>
            Since StatusLogger implements the Log4j 2 API's Logger interface, all the normal Logger methods may
            be used.
          </p>
          <p>
            When configuring Log4j it is sometimes necessary to view the generated status events. This can be
            accomplished by adding the status attribute to the configuration element or a default value can be
            provided by setting the "Log4jDefaultStatusLevel" system property.  Valid values of the status attribute are
            "trace", "debug", "info", "warn", "error" and "fatal". The following
            configuration has the status attribute set to debug.
          </p>

          <pre class="prettyprint linenums"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>;
<Configuration status="debug" name="RoutingTest">
  <Properties>
    <Property name="filename">target/rolling1/rollingtest-${dollar}${dollar}{sd:type}.log</Property>
  </Properties>
  <ThresholdFilter level="debug"/>

  <Appenders>
    <Console name="STDOUT">
      <PatternLayout pattern="%m%n"/>
    </Console>
    <List name="List">
      <ThresholdFilter level="debug"/>
    </List>
    <Routing name="Routing">
      <Routes pattern="${dollar}${dollar}{sd:type}">
        <Route>
          <RollingFile name="Rolling-${dollar}{sd:type}" fileName="${dollar}{filename}"
                       filePattern="target/rolling1/test1-${dollar}{sd:type}.%i.log.gz">
            <PatternLayout>
              <pattern>%d %p %c{1.} [%t] %m%n</pattern>
            </PatternLayout>
            <SizeBasedTriggeringPolicy size="500" />
          </RollingFile>
        </Route>
        <Route ref="STDOUT" key="Audit"/>
        <Route ref="List" key="Service"/>
      </Routes>
    </Routing>
  </Appenders>

  <Loggers>
    <Logger name="EventLogger" level="info" additivity="false">
      <AppenderRef ref="Routing"/>
    </Logger>

    <Root level="error">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>

</Configuration>
]]></pre>
            <p>
            During startup this configuration produces:
            </p>
#if ($isPDF)
    <pre>
2011-11-23 17:08:00,769 DEBUG Generated plugins in 0.003374000 seconds
2011-11-23 17:08:00,789 DEBUG Calling createProperty on class org.apache.logging.log4j.core.
       config.Property for element property with params(name="filename",
       value="target/rolling1/rollingtest-${dollar}{sd:type}.log")
2011-11-23 17:08:00,792 DEBUG Calling configureSubstitutor on class org.apache.logging.log4j.
       core.config.plugins.PropertiesPlugin for element properties with
       params(properties={filename=target/rolling1/rollingtest-${dollar}{sd:type}.log})
2011-11-23 17:08:00,794 DEBUG Generated plugins in 0.001362000 seconds
2011-11-23 17:08:00,797 DEBUG Calling createFilter on class org.apache.logging.log4j.core.
       filter.ThresholdFilter for element ThresholdFilter with params(level="debug",
       onMatch="null", onMismatch="null")
2011-11-23 17:08:00,800 DEBUG Calling createLayout on class org.apache.logging.log4j.core.
       layout.PatternLayout for element PatternLayout with params(pattern="%m%n",
       Configuration(RoutingTest), null, charset="null")
2011-11-23 17:08:00,802 DEBUG Generated plugins in 0.001349000 seconds
2011-11-23 17:08:00,804 DEBUG Calling createAppender on class org.apache.logging.log4j.core.
       appender.ConsoleAppender for element Console with params(PatternLayout(%m%n), null,
       target="null", name="STDOUT", ignoreExceptions="null")
2011-11-23 17:08:00,804 DEBUG Calling createFilter on class org.apache.logging.log4j.core.
       filter.ThresholdFilter for element ThresholdFilter with params(level="debug",
       onMatch="null", onMismatch="null")
2011-11-23 17:08:00,806 DEBUG Calling createAppender on class org.apache.logging.log4j.test.
       appender.ListAppender for element List with params(name="List", entryPerNewLine="null",
       raw="null", null, ThresholdFilter(DEBUG))
2011-11-23 17:08:00,813 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.
       routing.Route for element Route with params(AppenderRef="null", key="null", Node=Route)
2011-11-23 17:08:00,823 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.
       routing.Route for element Route with params(AppenderRef="STDOUT", key="Audit", Node=Route)
2011-11-23 17:08:00,824 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.
       routing.Route for element Route with params(AppenderRef="List", key="Service", Node=Route)
2011-11-23 17:08:00,825 DEBUG Calling createRoutes on class org.apache.logging.log4j.core.appender.
       routing.Routes for element Routes with params(pattern="${dollar}{sd:type}",
       routes={Route(type=dynamic default), Route(type=static Reference=STDOUT key='Audit'),
       Route(type=static Reference=List key='Service')})
2011-11-23 17:08:00,827 DEBUG Calling createAppender on class org.apache.logging.log4j.core.appender.
       routing.RoutingAppender for element Routing with params(name="Routing",
      ignoreExceptions="null", Routes({Route(type=dynamic default),Route(type=static
       Reference=STDOUT key='Audit'),
       Route(type=static Reference=List key='Service')}), Configuration(RoutingTest), null, null)
2011-11-23 17:08:00,827 DEBUG Calling createAppenders on class org.apache.logging.log4j.core.config.
       plugins.AppendersPlugin for element appenders with params(appenders={STDOUT, List, Routing})
2011-11-23 17:08:00,828 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.
       config.plugins.AppenderRefPlugin for element AppenderRef with params(ref="Routing")
2011-11-23 17:08:00,829 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.
       LoggerConfig for element logger with params(additivity="false", level="info", name="EventLogger",
       AppenderRef={Routing}, null)
2011-11-23 17:08:00,830 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.
       config.plugins.AppenderRefPlugin for element AppenderRef with params(ref="STDOUT")</pre>
            <pre>
2011-11-23 17:08:00,831 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.
       LoggerConfig${dollar}RootLogger for element root with params(additivity="null", level="error",
       AppenderRef={STDOUT}, null)
2011-11-23 17:08:00,833 DEBUG Calling createLoggers on class org.apache.logging.log4j.core.
       config.plugins.LoggersPlugin for element loggers with params(loggers={EventLogger, root})
2011-11-23 17:08:00,834 DEBUG Reconfiguration completed
2011-11-23 17:08:00,846 DEBUG Calling createLayout on class org.apache.logging.log4j.core.
       layout.PatternLayout for element PatternLayout with params(pattern="%d %p %c{1.} [%t] %m%n",
       Configuration(RoutingTest), null, charset="null")
2011-11-23 17:08:00,849 DEBUG Calling createPolicy on class org.apache.logging.log4j.core.
       appender.rolling.SizeBasedTriggeringPolicy for element SizeBasedTriggeringPolicy with
       params(size="500")
2011-11-23 17:08:00,851 DEBUG Calling createAppender on class org.apache.logging.log4j.core.
       appender.RollingFileAppender for element RollingFile with
       params(fileName="target/rolling1/rollingtest-Unknown.log",
       filePattern="target/rolling1/test1-Unknown.%i.log.gz", append="null", name="Rolling-Unknown",
       bufferedIO="null", immediateFlush="null",
       SizeBasedTriggeringPolicy(SizeBasedTriggeringPolicy(size=500)), null,
       PatternLayout(%d %p %c{1.} [%t] %m%n), null, ignoreExceptions="null")
2011-11-23 17:08:00,858 DEBUG Generated plugins in 0.002014000 seconds
2011-11-23 17:08:00,889 DEBUG Reconfiguration started for context sun.misc.
       Launcher${dollar}AppClassLoader@37b90b39
2011-11-23 17:08:00,890 DEBUG Generated plugins in 0.001355000 seconds
2011-11-23 17:08:00,959 DEBUG Generated plugins in 0.001239000 seconds
2011-11-23 17:08:00,961 DEBUG Generated plugins in 0.001197000 seconds
2011-11-23 17:08:00,965 WARN No Loggers were configured, using default
2011-11-23 17:08:00,976 DEBUG Reconfiguration completed</pre>
#else
<pre>
2011-11-23 17:08:00,769 DEBUG Generated plugins in 0.003374000 seconds
2011-11-23 17:08:00,789 DEBUG Calling createProperty on class org.apache.logging.log4j.core.config.Property for element property with params(name="filename", value="target/rolling1/rollingtest-${dollar}{sd:type}.log")
2011-11-23 17:08:00,792 DEBUG Calling configureSubstitutor on class org.apache.logging.log4j.core.config.PropertiesPlugin for element properties with params(properties={filename=target/rolling1/rollingtest-${dollar}{sd:type}.log})
2011-11-23 17:08:00,794 DEBUG Generated plugins in 0.001362000 seconds
2011-11-23 17:08:00,797 DEBUG Calling createFilter on class org.apache.logging.log4j.core.filter.ThresholdFilter for element ThresholdFilter with params(level="debug", onMatch="null", onMismatch="null")
2011-11-23 17:08:00,800 DEBUG Calling createLayout on class org.apache.logging.log4j.core.layout.PatternLayout for element PatternLayout with params(pattern="%m%n", Configuration(RoutingTest), null, charset="null")
2011-11-23 17:08:00,802 DEBUG Generated plugins in 0.001349000 seconds
2011-11-23 17:08:00,804 DEBUG Calling createAppender on class org.apache.logging.log4j.core.appender.ConsoleAppender for element Console with params(PatternLayout(%m%n), null, target="null", name="STDOUT", ignoreExceptions="null")
2011-11-23 17:08:00,804 DEBUG Calling createFilter on class org.apache.logging.log4j.core.filter.ThresholdFilter for element ThresholdFilter with params(level="debug", onMatch="null", onMismatch="null")
2011-11-23 17:08:00,806 DEBUG Calling createAppender on class org.apache.logging.log4j.test.appender.ListAppender for element List with params(name="List", entryPerNewLine="null", raw="null", null, ThresholdFilter(DEBUG))
2011-11-23 17:08:00,813 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.routing.Route for element Route with params(AppenderRef="null", key="null", Node=Route)
2011-11-23 17:08:00,823 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.routing.Route for element Route with params(AppenderRef="STDOUT", key="Audit", Node=Route)
2011-11-23 17:08:00,824 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.routing.Route for element Route with params(AppenderRef="List", key="Service", Node=Route)
2011-11-23 17:08:00,825 DEBUG Calling createRoutes on class org.apache.logging.log4j.core.appender.routing.Routes for element Routes with params(pattern="${dollar}{sd:type}", routes={Route(type=dynamic default), Route(type=static Reference=STDOUT key='Audit'), Route(type=static Reference=List key='Service')})
2011-11-23 17:08:00,827 DEBUG Calling createAppender on class org.apache.logging.log4j.core.appender.routing.RoutingAppender for element Routing with params(name="Routing", ignoreExceptions="null", Routes({Route(type=dynamic default),Route(type=static Reference=STDOUT key='Audit'),Route(type=static Reference=List key='Service')}), Configuration(RoutingTest), null, null)
2011-11-23 17:08:00,827 DEBUG Calling createAppenders on class org.apache.logging.log4j.core.config.AppendersPlugin for element appenders with params(appenders={STDOUT, List, Routing})
2011-11-23 17:08:00,828 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.config.plugins.AppenderRefPlugin for element AppenderRef with params(ref="Routing")
2011-11-23 17:08:00,829 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.LoggerConfig for element logger with params(additivity="false", level="info", name="EventLogger", AppenderRef={Routing}, null)
2011-11-23 17:08:00,830 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.config.plugins.AppenderRefPlugin for element AppenderRef with params(ref="STDOUT")
2011-11-23 17:08:00,831 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.LoggerConfig${dollar}RootLogger for element root with params(additivity="null", level="error", AppenderRef={STDOUT}, null)
2011-11-23 17:08:00,833 DEBUG Calling createLoggers on class org.apache.logging.log4j.core.config.LoggersPlugin for element loggers with params(loggers={EventLogger, root})
2011-11-23 17:08:00,834 DEBUG Reconfiguration completed
2011-11-23 17:08:00,846 DEBUG Calling createLayout on class org.apache.logging.log4j.core.layout.PatternLayout for element PatternLayout with params(pattern="%d %p %c{1.} [%t] %m%n", Configuration(RoutingTest), null, charset="null")
2011-11-23 17:08:00,849 DEBUG Calling createPolicy on class org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy for element SizeBasedTriggeringPolicy with params(size="500")
2011-11-23 17:08:00,851 DEBUG Calling createAppender on class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile with params(fileName="target/rolling1/rollingtest-Unknown.log", filePattern="target/rolling1/test1-Unknown.%i.log.gz", append="null", name="Rolling-Unknown", bufferedIO="null", immediateFlush="null", SizeBasedTriggeringPolicy(SizeBasedTriggeringPolicy(size=500)), null, PatternLayout(%d %p %c{1.} [%t] %m%n), null, ignoreExceptions="null")
2011-11-23 17:08:00,858 DEBUG Generated plugins in 0.002014000 seconds
2011-11-23 17:08:00,889 DEBUG Reconfiguration started for context sun.misc.Launcher${dollar}AppClassLoader@37b90b39
2011-11-23 17:08:00,890 DEBUG Generated plugins in 0.001355000 seconds
2011-11-23 17:08:00,959 DEBUG Generated plugins in 0.001239000 seconds
2011-11-23 17:08:00,961 DEBUG Generated plugins in 0.001197000 seconds
2011-11-23 17:08:00,965 WARN No Loggers were configured, using default
2011-11-23 17:08:00,976 DEBUG Reconfiguration completed</pre>
#end
          <p>
            If the status attribute is set to error than only error messages will be written to the console. This
            makes troubleshooting configuration errors possible. As an example, if the configuration above is changed
            to have the status set to error and the logger declaration is:</p>
          <pre class="prettyprint linenums"><![CDATA[
<logger name="EventLogger" level="info" additivity="false">
  <AppenderRef ref="Routng"/>
</logger>
]]></pre>
          <p>
            the following error message will be produced.
          </p>
          <pre>2011-11-24 23:21:25,517 ERROR Unable to locate appender Routng for logger EventLogger</pre>
          <p>
            Applications may wish to direct the status output to some other destination. This can be accomplished
            by setting the dest attribute to either "err" to send the output to stderr or to a file location or URL.
            This can also be done by insuring the configured status is set to OFF and then configuring the application
            programmatically such as:
          </p>
<pre class="prettyprint linenums"><![CDATA[
StatusConsoleListener listener = new StatusConsoleListener(Level.ERROR);
StatusLogger.getLogger().registerListener(listener);
]]></pre>
        </subsection>
        <a name="UnitTestingInMaven"/>
        <subsection name="Testing in Maven">
        <p>
          Maven can run unit and functional tests during the build cycle. By default, any files placed in
          <code>src/test/resources</code> are automatically copied to target/test-classes and are included
          in the classpath during execution of any tests. As such, placing a log4j2-test.xml into this directory
          will cause it to be used instead of a log4j2.xml or log4j2.json that might be present.  Thus a different
          log configuration can be used during testing than what is used in production.
        </p>
        <p>
          A second approach, which is extensively used by Log4j 2, is to set the log4j.configurationFile property
          in the method annotated with @BeforeClass in the junit test class. This will allow an arbitrarily
          named file to be used during the test.
        </p>
          <p>
            A third approach, also used extensively by Log4j 2, is to use the <code>InitialLoggerContext</code>
            JUnit test rule which provides additional convenience methods for testing. This requires adding the
            <code>log4j-core</code> <code>test-jar</code> dependency to your test scope dependencies. For example:
          </p>
          <pre class="prettyprint linenums"><![CDATA[
public class AwesomeTest {
    @Rule
    public InitialLoggerContext init = new InitialLoggerContext("MyTestConfig.xml");

    @Test
    public void testSomeAwesomeFeature() {
        final LoggerContext ctx = init.getContext();
        final Logger logger = init.getLogger("org.apache.logging.log4j.my.awesome.test.logger");
        final Configuration cfg = init.getConfiguration();
        final ListAppender app = init.getListAppender("List");
        logger.warn("Test message");
        final List<LogEvent> events = app.getEvents();
        // etc.
    }
}
]]></pre>
        </subsection>
        <a name="SystemProperties"/>
        <subsection name="System Properties">
        <p>
          Below follows a number of system properties that can be used to control Log4j 2 behaviour.
          Any spaces present in the property name are for visual flow and should be removed.
        </p>
<table>
  <caption align="top">Log4j 2 System Properties</caption>
  <tr>
    <th>System Property</th>
    <th>Default Value</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>log4j.configurationFile</td>
    <td>&nbsp;</td>
    <td>
      Path to an XML or JSON Log4j 2 configuration file.
    </td>
  </tr>
  <tr>
    <td>Log4jContextSelector</td>
    <td>ClassLoaderContextSelector</td>
    <td>
      Creates the <tt>LoggerContext</tt>s. An application can have one or more active LoggerContexts depending
      on the circumstances.
      See <a href="logsep.html">Log Separation</a> for more details.
      Available context selector implementation classes:<br />
    <!-- deliberately inserted spaces to allow line break -->
      <tt>org.apache.logging.log4j.core.async .AsyncLoggerContextSelector</tt> - makes <a href="async.html">all loggers asynchronous</a>.<br />
      <tt>org.apache.logging.log4j.core.selector .BasicContextSelector</tt> - creates a single shared LoggerContext.<br />
      <tt>org.apache.logging.log4j.core.selector .ClassLoaderContextSelector</tt> - separate LoggerContexts for each web application.<br />
      <tt>org.apache.logging.log4j.core.selector .JndiContextSelector</tt> - use JNDI to locate each web application's LoggerContext.<br/>
      <tt>org.apache.logging.log4j.core.osgi .BundleContextSelector</tt> - separate LoggerContexts for each OSGi bundle.
    </td>
  </tr>
  <tr>
    <td>Log4jLogEventFactory</td>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.core.impl .DefaultLogEventFactory</td>
    <td>
      Factory class used by LoggerConfig to create <tt>LogEvent</tt> instances.
      (Ignored when the <tt>AsyncLoggerContextSelector</tt> is used.)
    </td>
  </tr>
  <tr>
    <td>log4j2.loggerContextFactory</td>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simple .SimpleLoggerContextFactory</td>
    <td>
      Factory class used by LogManager to bootstrap the logging implementation.
      The core jar provides <tt>org.apache.logging.log4j.core.impl.Log4jContextFactory</tt>.
    </td>
  </tr>
  <tr>
    <td>log4j.configurationFactory</td>
    <td>&nbsp;</td>
    <td>
      Fully specified class name of a class extending <tt>org.apache.logging.log4j.core.config.ConfigurationFactory</tt>.
      If specified, an instance of this class is added to the list of configuration factories.
    </td>
  </tr>
  <tr>
    <td>log4j.shutdownHookEnabled</td>
    <td>true</td>
    <td>
      Overrides the global flag for whether or not a shutdown hook should be used to stop a <tt>LoggerContext</tt>.
      By default, this is enabled and can be disabled on a per-configuration basis. When running with the
      <tt>log4j-web</tt> module, this is automatically disabled.
    </td>
  </tr>
  <tr>
    <td>log4j.shutdownCallbackRegistry</td>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.core.util .DefaultShutdownCallbackRegistry</td>
    <td>
      Fully specified class name of a class implementing
      <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/util/ShutdownCallbackRegistry.html">ShutdownCallbackRegistry</a>.
      If specified, an instance of this class is used instead of <tt>DefaultShutdownCallbackRegistry</tt>.
      The specified class must have a default constructor.
    </td>
  </tr>
  <tr>
    <td>log4j.Clock</td>
    <td>SystemClock</td>
    <td>
      Implementation of the <tt>org.apache.logging.log4j.core.util.Clock</tt>
      interface that is used for timestamping the log events.
      <br />
      By default, <tt>System.currentTimeMillis</tt> is called on every log event.
      <br />
      You can also specify a fully qualified class name of a custom class that implements the
      <tt>Clock</tt> interface.
    </td>
  </tr>
  <tr>
    <td>org.apache.logging.log4j.level</td>
    <td>ERROR</td>
    <td>
      Log level of the default configuration. The default configuration is used if the ConfigurationFactory
      could not successfully create a configuration (e.g. no log4j2.xml file was found).
    </td>
  </tr>

  <tr>
    <td>disableThreadContext</td>
    <td>false</td>
    <td>
      If <tt>true</tt>, the ThreadContext stack and map are disabled.
      (May be ignored if a custom ThreadContext map is specified.)
    </td>
  </tr>
  <tr>
    <td>disableThreadContextStack</td>
    <td>false</td>
    <td>
      If <tt>true</tt>, the ThreadContext stack is disabled.
    </td>
  </tr>
  <tr>
    <td>disableThreadContextMap</td>
    <td>false</td>
    <td>
      If <tt>true</tt>, the ThreadContext map is disabled.
      (May be ignored if a custom ThreadContext map is specified.)
    </td>
  </tr>
  <tr>
    <td>log4j2.threadContextMap</td>
    <td>&nbsp;</td>
    <td>
      Fully specified class name of a custom <tt>ThreadContextMap</tt> implementation class.
    </td>
  </tr>
  <tr>
    <td>isThreadContextMapInheritable</td>
    <td>false</td>
    <td>
      If <tt>true</tt> use a <tt>InheritableThreadLocal</tt> to implement the ThreadContext map.
      Otherwise, use a plain <tt>ThreadLocal</tt>.
      (May be ignored if a custom ThreadContext map is specified.)
    </td>
  </tr>
  <tr>
    <td>log4j2.disable.jmx</td>
    <td>false</td>
    <td>
      If <tt>true</tt>, Log4j configuration objects like LoggerContexts, Appenders, Loggers, etc.
      will not be instrumented with MBeans and cannot be remotely monitored and managed.
    </td>
  </tr>
  <tr>
    <td>log4j2.jmx.notify.async</td>
    <td>false for web apps, true otherwise</td>
    <td>
      If <tt>true</tt>, log4j's JMX notifications are sent from a separate background thread,
      otherwise they are sent from the caller thread.
      If the <tt>javax.servlet.Servlet</tt> class is on the classpath, the default behaviour
      is to use the caller thread to send JMX notifications.
    </td>
  </tr>
  <tr>
    <td>log4j.skipJansi</td>
    <td>false</td>
    <td>
      If <tt>true</tt>, the ConsoleAppender will not try to use the Jansi output stream on Windows.
    </td>
  </tr>
  <tr>
    <td>log4j.ignoreTCL</td>
    <td>false</td>
    <td>
      If <tt>true</tt>, classes are only loaded with the default class loader.
      Otherwise, an attempt is made to load classes with the current thread's context class loader
      before falling back to the default class loader.
    </td>
  </tr>
  <tr>
    <td>org.apache.logging.log4j.uuidSequence</td>
    <td>0</td>
    <td>
      System property that may be used to seed the UUID generation with an integer value.
    </td>
  </tr>
  <!--
  <tr>
    <td>org.apache.logging.log4j.assignedSequences</td>
    <td>true</td>
    <td>
      TODO: used to seed UUID generation. Not sure when or why one would use this...
    </td>
  </tr>
  -->
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog .showContextMap</td>
    <td>false</td>
    <td>If <tt>true</tt>, the full ThreadContext map is included in each SimpleLogger log message.</td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog .showlogname</td>
    <td>false</td>
    <td>If <tt>true</tt>, the logger name is included in each SimpleLogger log message.</td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog .showShortLogname</td>
    <td>true</td>
    <td>If <tt>true</tt>, only the last component of a logger name is included in SimpleLogger log messages.
    (E.g., if the logger name is "mycompany.myproject.mycomponent", only "mycomponent" is logged.
    </td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog .showdatetime</td>
    <td>false</td>
    <td>If <tt>true</tt>, SimpleLogger log messages contain timestamp information.
    </td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog .dateTimeFormat</td>
    <td>"yyyy/MM/dd HH:mm:ss:SSS zzz"</td>
    <td>Date-time format to use.
    Ignored if <tt>org.apache.logging.log4j.simplelog.showdatetime</tt> is <tt>false</tt>.
    </td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.logj.simplelog .logFile</td>
    <td>system.err</td>
    <td>"system.err" (case-insensitive) logs to System.err,
    "system.out" (case-insensitive) logs to System.out,
    any other value is interpreted as a file name to save SimpleLogger messages to.
    </td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog .level</td>
    <td>ERROR</td>
    <td>Default level for new SimpleLogger instances.
    </td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog.&lt;loggerName&gt;level</td>
    <td>SimpleLogger default log level</td>
    <td>Log level for a the SimpleLogger instance with the specified name.</td>
  </tr>
  <tr>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.simplelog .StatusLogger.level</td>
    <td>ERROR</td>
    <td>This property is used to control the initial StatusLogger level, and can be overridden in code by calling
    <code>StatusLogger.getLogger().setLevel(someLevel)</code>.
    Note that the StatusLogger level is only used to determine the status log output level
    until a listener is registered. In practice, a listener is registered when a configuration is found,
    and from that point onwards, status messages are only sent to the listeners (depending on their statusLevel).</td>
  </tr>
  <tr>
    <td>Log4jDefaultStatusLevel</td>
    <td>ERROR</td>
    <td>
      <p>The StatusLogger logs events that occur in the logging system to the console.
      During configuration, AbstractConfiguration registers a StatusConsoleListener with the StatusLogger that may
      redirect status log events from the default console output to a file.
      The listener also supports fine-grained filtering.
      This system property specifies the default status log level for the listener to use if the configuration does not
      specify a status level.
      </p><p>
      Note: this property is used by the log4j-core implementation only after a configuration file has been found.</p>
    </td>
  </tr>
  <tr>
    <td>log4j2.StatusLogger.level</td>
    <td>WARN</td>
    <td>
      <p>The initial "listenersLevel" of the StatusLogger. If StatusLogger listeners are added, the "listenerLevel"
      is changed to that of the most verbose listener. If any listeners are registered, the listenerLevel is
      used to quickly determine if an interested listener exists.
      </p><p>
      By default, StatusLogger listeners are added when a configuration is found and by the JMX
      StatusLoggerAdmin MBean. For example, if a configuration contains
      <code>&lt;Configuration status="trace"&gt;</code>, a listener with statusLevel TRACE is registered
      and the StatusLogger listenerLevel is set to TRACE, resulting in verbose status messages displayed on the console.
      </p><p>
      If no listeners are registered, the listenersLevel is not used, and the StatusLogger output level
      is determined by <code>StatusLogger.getLogger().getLevel()</code>
      (see property <code>org.apache.logging.log4j.simplelog .StatusLogger.level</code>).</p>
    </td>
  </tr>
  <tr>
    <td>log4j2.status.entries</td>
    <td>200</td>
    <td>
      Number of StatusLogger events that are kept in a buffer and can be retrieved with
      <tt>StatusLogger.getStatusData()</tt>.
    </td>
  </tr>
  <tr>
    <td>AsyncLogger.ExceptionHandler</td>
    <td>&nbsp;
    </td>
    <td>
      See <a href="async.html#SysPropsAllAsync">Async Logger System Properties</a> for details.
    </td>
  </tr>
  <tr>
    <td>AsyncLogger.RingBufferSize</td>
    <td>256&#160;*&#160;1024</td>
    <td>
      See <a href="async.html#SysPropsAllAsync">Async Logger System Properties</a> for details.
    </td>
  </tr>
  <tr>
    <td>AsyncLogger.WaitStrategy</td>
    <td>
      Sleep
    </td>
    <td>
      See <a href="async.html#SysPropsAllAsync">Async Logger System Properties</a> for details.
    </td>
  </tr>
  <tr>
    <td>AsyncLogger.ThreadNameStrategy</td>
    <td>
      CACHED
    </td>
    <td>
      See <a href="async.html#SysPropsAllAsync">Async Logger System Properties</a> for details.
    </td>
  </tr>
  <tr>
    <td>AsyncLoggerConfig.ExceptionHandler</td>
    <td>&nbsp;    </td>
    <td>
      See <a href="async.html#SysPropsMixedSync-Async">Mixed Async/Synchronous Logger System Properties</a> for details.
    </td>
  </tr>
  <tr>
    <td>AsyncLoggerConfig.RingBufferSize</td>
    <td>256&#160;*&#160;1024</td>
    <td>
      See <a href="async.html#SysPropsMixedSync-Async">Mixed Async/Synchronous Logger System Properties</a> for details.
    </td>
  </tr>
  <tr>
    <td>AsyncLoggerConfig.WaitStrategy</td>
    <td>
      Sleep
    </td>
    <td>
      See <a href="async.html#SysPropsMixedSync-Async">Mixed Async/Synchronous Logger System Properties</a> for details.
    </td>
  </tr>
  <tr>
    <td>log4j.jul.LoggerAdapter</td>
    <!-- deliberately inserted spaces to allow line break -->
    <td>org.apache.logging.log4j.jul .ApiLoggerAdapter</td>
    <td>
      Default LoggerAdapter to use in the JUL adapter. By default, if log4j-core is available, then the class
      <code>org.apache.logging.log4j.jul .CoreLoggerAdapter</code> will be used. Otherwise, the
      <code>ApiLogggerAdapter</code> will be used. Custom implementations must provide a public default constructor.
    </td>
  </tr>
</table>

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