http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b53b8118/src/site/xdoc/manual/configuration.xml.vm ---------------------------------------------------------------------- diff --git a/src/site/xdoc/manual/configuration.xml.vm b/src/site/xdoc/manual/configuration.xml.vm deleted file mode 100644 index 8acdd40..0000000 --- a/src/site/xdoc/manual/configuration.xml.vm +++ /dev/null @@ -1,2383 +0,0 @@ -<?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="rgo...@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, YAML, or properties format.</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> - and <a href="customconfig.html">Programmatic Log4j Configuration</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 them in weighted - order from highest to lowest. As delivered, Log4j contains four ConfigurationFactory implementations: - one for JSON, one for YAML, one for properties, 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 properties ConfigurationFactory will look for - <code>log4j2-test.properties</code> in the classpath.</li> - <li>If no such file is found 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 properties ConfigurationFactory will look for - <code>log4j2.properties</code> on the classpath.</li> - <li>If a properties 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> - </subsection> - <a name="Additivity"/> - <subsection name="Additivity"> - <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> - <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 of version 2.9, for security reasons, Log4j does not process DTD in XML files. - If you want to split the configuration in multiple files, use <a href="#XInclude">XInclude</a> or - <a href="#CompositeConfiguration">Composite Configuration</a>. - </p> - <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> - <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>shutdownTimeout</td> - <td>Specifies how many milliseconds appenders and background tasks will get to shutdown when the JVM shuts - down. Default is zero which mean that each appender uses its default timeout, and don't wait for background - tasks. Not all appenders will honor this, it is a hint and not an absolute guarantee that the shutdown - procedure will not take longer. Setting this too low increase the risk of losing outstanding log events - not yet written to the final destination. See <a class="javadoc" - href="../log4j-core/target/site/apidocs/org/apache/logging/log4j/core/LoggerContext.html${esc.hash}stop(long, java.util.concurrent.TimeUnit)">LoggerContext.stop(long, - java.util.concurrent.TimeUnit)</a>. - (Not used if <tt>shutdownHook</tt> is set to "disable".)</td> - </tr> - <tr> - <td>status</td> - <td><p>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. - </p><p> - (Alternatively, setting system property <tt>log4j2.debug</tt> will also print internal Log4j2 logging - to the console, including internal logging that took place before the configuration file was found.) - </p></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> - <a name="XML"/> - <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> - </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="STDOUT"/> - </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" }, - "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"} - ] - } - } - }, - "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" }, "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"} - ] - } - } - ] - }, - "loggers": { - "logger": [ - { "name": "EventLogger", "level": "info", "additivity": "false", - "AppenderRef": { "ref": "Routing" }}, - { "name": "com.foo.bar", "level": "error", "additivity": "false", - "AppenderRef": { "ref": "STDOUT" }} - ], - "root": { "level": "error", "AppenderRef": { "ref": "STDOUT" }} - } - } -} -]]></pre> - <p> - Additional <a href="../runtime-dependencies.html">runtime dependencies</a> are required for using - JSON configuration files. - </p> - <a name="YAML"/> - <h4>Configuration with YAML</h4> - <p> - Log4j also supports using YAML for configuration files. The structure follows the same pattern as both the - XML and YAML configuration formats. For example: - </p> - <pre class="prettyprint linenums"><![CDATA[ -Configuration: - status: warn - name: YAMLConfigTest - properties: - property: - name: filename - value: target/test-yaml.log - thresholdFilter: - level: debug - appenders: - Console: - name: STDOUT - PatternLayout: - Pattern: "%m%n" - File: - name: File - fileName: ${dollar}{filename} - PatternLayout: - Pattern: "%d %p %C{1.} [%t] %m%n" - Filters: - ThresholdFilter: - level: error - - Loggers: - logger: - - - name: org.apache.logging.log4j.test1 - level: debug - additivity: false - ThreadContextMapFilter: - KeyValuePair: - key: test - value: 123 - AppenderRef: - ref: STDOUT - - - name: org.apache.logging.log4j.test2 - level: debug - additivity: false - AppenderRef: - ref: File - Root: - level: error - AppenderRef: - ref: STDOUT - ]]></pre> - <p> - Additional <a href="../runtime-dependencies.html">runtime dependencies</a> are required for using - YAML configuration files. - </p> - <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 true 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> - </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="STDOUT"/> - </Root> - </Loggers> - -</Configuration> -]]></pre> - <a name="Properties"/> - <h4>Configuration with Properties</h4> - <p> - As of version 2.4, Log4j now supports configuration via properties files. Note that the property - syntax is NOT the same as the syntax used in Log4j 1. Like the XML and JSON configurations, properties - configurations define the configuration in terms of plugins and attributes to the plugins. - </p> - <p> - Prior to version 2.6, - the properties configuration requires that you list the identifiers of the appenders, filters and loggers, - in a comma separated list in properties with those names. Each of those components will then be expected - to be defined in sets of properties that begin with <i>component.<.identifier>.</i>. The identifier does not - have to match the name of the component being defined but must uniquely identify all the attributes and - subcomponents that are part of the component. If the list of identifiers is not present the - identier must not contain a '.'. Each individual component MUST have a "type" attribute - specified that identifies the component's Plugin type. - </p> - <p> - As of version 2.6, this list of identifiers is no longer required as names are inferred upon first usage, - however if you wish to use more complex identifies you must still use the list. If the list is present - it will be used. - </p> - <p> - Unlike the base components, when creating subcomponents you cannot specify an element containing a list of - identifiers. Instead, you must define the wrapper element with its type as is shown in the policies - definition in the rolling file appender below. You then define each of the subcomponents below that - wrapper element, as the TimeBasedTriggeringPolicy and SizeBasedTriggeringPolicy are defined below. - </p> - <p> - Properties configuration files support the advertiser, monitorInterval, name, packages, shutdownHook, - shutdownTimeout, status, verbose, and dest attrbutes. See <a href="#ConfigurationSyntax">Configuration Syntax</a> - for the definitions of these attributes. - </p> - <pre class="prettyprint linenums"> -status = error -dest = err -name = PropertiesConfig - -property.filename = target/rolling/rollingtest.log - -filter.threshold.type = ThresholdFilter -filter.threshold.level = debug - -appender.console.type = Console -appender.console.name = STDOUT -appender.console.layout.type = PatternLayout -appender.console.layout.pattern = %m%n -appender.console.filter.threshold.type = ThresholdFilter -appender.console.filter.threshold.level = error - -appender.rolling.type = RollingFile -appender.rolling.name = RollingFile -appender.rolling.fileName = ${filename} -appender.rolling.filePattern = target/rolling2/test1-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz -appender.rolling.layout.type = PatternLayout -appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n -appender.rolling.policies.type = Policies -appender.rolling.policies.time.type = TimeBasedTriggeringPolicy -appender.rolling.policies.time.interval = 2 -appender.rolling.policies.time.modulate = true -appender.rolling.policies.size.type = SizeBasedTriggeringPolicy -appender.rolling.policies.size.size=100MB -appender.rolling.strategy.type = DefaultRolloverStrategy -appender.rolling.strategy.max = 5 - -logger.rolling.name = com.example.my.app -logger.rolling.level = debug -logger.rolling.additivity = false -logger.rolling.appenderRef.rolling.ref = RollingFile - -rootLogger.level = info -rootLogger.appenderRef.stdout.ref = STDOUT - </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"/> - <ThresholdFilter level="debug"/> - </Console> - <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"/> - </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. - See the <a href="lookups.html">Lookups</a> manual page for more details. - 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. The formats are <code>${dollar}{env:ENV_NAME}</code> and <code>${dollar}{env:ENV_NAME:-default_value}</code>.</td> - </tr> - <tr> - <td>jndi</td> - <td>A value set in the default JNDI Context.</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>log4j</td> - <td>Log4j configuration properties. The expressions <code>${dollar}{log4j:configLocation}</code> and - <code>${dollar}{log4j:configParentLocation}</code> respectively provide the absolute path - to the log4j configuration file and its parent folder.</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. The formats are <code>${dollar}{sys:some.property}</code> and <code>${dollar}{sys:some.property:-default_value}</code>.</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> - </subsection> - <a name="RuntimeLookup"/> - <subsection name="Lookup Variables with Multiple Leading '$' Characters"> - <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 '$' character 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="Scripts"/> - <subsection name="Scripts"> - <p> - Log4j provides support for <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/">JSR 223</a> - scripting languages to be used in some of its components. Any language that provides support for the JSR - 223 scripting engine may be used. A list of the languages and bindings for them can be found at the - <a href="https://java.net/projects/scripting/sources/svn/show/trunk/engines">Scripting Engine</a> web site. - However, some of the languages listed there, such as JavaScript, Groovy and Beanshell, directly support the - JSR 223 scripting framework and only require that the jars for that language be installed. - </p> - <p> - The components that support using scripts do so by allowing a <script>, <scriptFile>, or - <scriptRef> element to be configured on - them. The script element contains a name for the script, the language of the script, and the script text. - The scriptFile element contains the name of the script, its location, its language, its charset, and - whether the file should be watched for changes. The scriptRef element contains the name of the - script that is defined in the <scripts> configuration element. - The name of the script is used to store the script, along with its ScriptEngine, so it can quickly be - located each time the script needs to be run. While the name is not required, providing it will help in - debugging problems when the script is running. The language must be provided on the script element and must - specify one of the language names that appear in the Configuration status log as described in the next - section. If the language is not specified on the scriptFile element the language will be determined by - the file extension of the script path. If file monitoring is requested it will only be enabled if - a non-zero monitorInterval is specified on the configuration element. That interval will be used to - check for changes in the file. - </p> - <pre class="prettyprint linenums"><![CDATA[ -<?xml version="1.0" encoding="UTF-8"?> -<Configuration status="debug" name="RoutingTest"> - <Scripts> - <Script name="selector" language="javascript"><![CDATA[ - var result; - if (logEvent.getLoggerName().equals("JavascriptNoLocation")) { - result = "NoLocation"; - } else if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("FLOW")) { - result = "Flow"; - } - result; - ]]]]><![CDATA[></Script> - <ScriptFile name="groovy.filter" path="scripts/filter.groovy"/> - </Scripts> - - <Appenders> - <Console name="STDOUT"> - <ScriptPatternSelector defaultPattern="%d %p %m%n"> - <ScriptRef ref="selector"/> - <PatternMatch key="NoLocation" pattern="[%-5level] %c{1.} %msg%n"/> - <PatternMatch key="Flow" pattern="[%-5level] %c{1.} ====== %C{1.}.%M:%L %msg ======%n"/> - </ScriptPatternSelector> - <PatternLayout pattern="%m%n"/> - </Console> - </Appenders> - - <Loggers> - <Logger name="EventLogger" level="info" additivity="false"> - <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY"> - <Script name="GroovyFilter" language="groovy"><![CDATA[ - if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("FLOW")) { - return true; - } else if (logEvent.getContextMap().containsKey("UserId")) { - return true; - } - return false; - ]]]]><![CDATA[> - </Script> - </ScriptFilter> - <AppenderRef ref="STDOUT"/> - </Logger> - - <Root level="error"> - <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY"> - <ScriptRef ref="groovy.filter"/> - </ScriptFilter> - <AppenderRef ref="STDOUT"/> - </Root> - </Loggers> - -</Configuration>]]> - </pre> - <p> - If the status attribute on the Configuration element is set to DEBUG the list of script engines currently - installed and their attributes will be listed. Although some engines may say they are not thread safe, - Log4j takes steps to insure that the scripts will run in a thread-safe manner if the engine advertises - that it is not thread safe. - </p> - <pre> -2015-09-27 16:13:22,925 main DEBUG Installed script engines -2015-09-27 16:13:22,963 main DEBUG AppleScriptEngine Version: 1.1, Language: AppleScript, Threading: Not Thread Safe, - Compile: false, Names: {AppleScriptEngine, AppleScript, OSA} -2015-09-27 16:13:22,983 main DEBUG Groovy Scripting Engine Version: 2.0, Language: Groovy, Threading: MULTITHREADED, - Compile: true, Names: {groovy, Groovy} -2015-09-27 16:13:23,030 main DEBUG BeanShell Engine Version: 1.0, Language: BeanShell, Threading: MULTITHREADED, - Compile: true, Names: {beanshell, bsh, java} -2015-09-27 16:13:23,039 main DEBUG Mozilla Rhino Version: 1.7 release 3 PRERELEASE, Language: ECMAScript, Threading: MULTITHREADED, - Compile: true, Names: {js, rhino, JavaScript, javascript, ECMAScript, ecmascript} - </pre> - <p> - When the scripts are executed they will be provided with a set of variables that should allow them to - accomplish whatever task they are expected to perform. See the documentation for the individual components - for the list of variables that are available to the script. - </p> - <p> - The components that support scripting expect a return value to be passed back to the calling Java code. - This is not a problem for several of the scripting languages, but Javascript does not allow a - return statement unless it is within a function. However, Javascript will return the value of the last - statement executed in the script. As a consequence, code such as that shown below will result in the - desired behavior. - </p> - <pre><![CDATA[ - var result; - if (logEvent.getLoggerName().equals("JavascriptNoLocation")) { - result = "NoLocation"; - } else if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("FLOW")) { - result = "Flow"; - } - result; - ]]></pre> - <h4>A special note on Beanshell</h4> - <p> - JSR 223 scripting engines are supposed to identify that they support the Compilable interface if they - support compiling their scripts. Beanshell does this. However, whenever the compile method is called it - throws an Error (not an Exception). Log4j catches this but will log the warning shown below for each - Beanshell script when it tries to compile them. All Beanshell scripts will then be interpreted on each - execution. - </p> - <pre><![CDATA[ -2015-09-27 16:13:23,095 main DEBUG Script BeanShellSelector is compilable -2015-09-27 16:13:23,096 main WARN Error compiling script java.lang.Error: unimplemented - at bsh.engine.BshScriptEngine.compile(BshScriptEngine.java:175) - at bsh.engine.BshScriptEngine.compile(BshScriptEngine.java:154) - at org.apache.logging.log4j.core.script.ScriptManager$MainScriptRunner.<init>(ScriptManager.java:125) - at org.apache.logging.log4j.core.script.ScriptManager.addScript(ScriptManager.java:94) - ]]></pre> - </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="CompositeConfiguration"/> - <subsection name="Composite Configuration"> - <p> - Log4j allows multiple configuration files to be used by specifying them as a list of comma separated - file paths on log4j.configurationFile. The merge logic can be controlled by specifying a class - that implements the MergeStrategy interface on the log4j.mergeStrategy property. The default - merge strategy will merge the files using the following rules: - <ol> - <li>The global configuration attributes are aggregated with those in later configurations replacing - those in previous configurations, with the exception that the highest status level and the lowest - monitorInterval greater than 0 will be used.</li> - <li>Properties from all configurations are aggregated. Duplicate properties replace those in previous - configurations.</li> - <li>Filters are aggregated under a CompositeFilter if more than one Filter is defined. Since Filters - are not named duplicates may be present.</li> - <li>Scripts and ScriptFile references are aggregated. Duplicate definiations replace those in previous - configurations.</li> - <li>Appenders are aggregated. Appenders with the same name are replaced by those in later - configurations, including all of the Appender's subcomponents.</li> - <li>Loggers are all aggregated. Logger attributes are individually merged with duplicates being - replaced by those in later configurations. Appender references on a Logger are aggregated with - duplicates being replaced by those in later configurations. Filters on a Logger are aggregated - under a CompositeFilter if more than one Filter is defined. Since Filters are not named - duplicates may be present. Filters under Appender references included or discarded depending on - whether their parent Appender reference is kept or discarded.</li> - </ol> - </p> - </subsection> - <a name="StatusMessages"/> - <subsection name="Status Messages"> - <table> - <tr> - <td> - <b>Troubleshooting tip for the impatient:</b> - <p>From log4j-2.9 onward, log4j2 will print all internal logging to the console if system property - <tt>log4j2.debug</tt> is defined (with any or no value).</p> - <p>Prior to log4j-2.9, there are two places where internal logging can be controlled:</p> - <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><Configuration status="trace"></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"/> - <ThresholdFilter level="debug"/> - </Console> - <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"/> - </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,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,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'))}) -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')}), 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, 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,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,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')}) -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')}), 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, 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>LoggerContextRule</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 LoggerContextRule init = new LoggerContextRule("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> - The Log4j documentation references a number of System Properties that can be used to control various aspects - of Log4j 2 behavior. The table below lists these properties along with their default value and a - description of what they control. - Any spaces present in the property name are for visual flow and should be removed. - </p> - <p> - Note that beginning in Log4j 2.10, all system property names have been normalized to follow a consistent - naming scheme. While the old property names are still supported for backwards compatibility, it is - recommended to update configurations to use the new style. This system is extensible and is enabled - through the - <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/util/PropertySource.html">PropertySource</a> - interface. Additional property source classes can be added through the standard <code>ServiceLoader</code> - mechanism in Java SE. - </p> - <p> - Properties can be overridden by sources with a lower number priority (e.g.., -100 comes before 100). The - following sources are all available by default: - </p> - <table> - <caption align="top">PropertySource priorities and descriptions</caption> - <tr> - <th>Source</th> - <th>Priority</th> - <th>Description</th> - </tr> - <tr> - <td>Environment Variables</td> - <td>-100</td> - <td> - Environment variables are all prefixed with <code>LOG4J_</code>, are in all caps, and words are all - separated by underscores. Only this naming scheme is support for environment variables as there were - no old naming schemes to maintain compatibility with. - </td> - </tr> - <tr> - <td><code>log4j2.component.properties</code> file</td> - <td>0</td> - <td> - Including this file on the classpath can be used as an alternative to providing properties as system - properties. This has priority over system properties, but they can be overridden by environment - variables as described above. - </td> - </tr> - <tr> - <td>System Properties</td> - <td>100</td> - <td> - All properties can be set using normal system property patterns. These have the lowest priority and - can be overridden by included properties files or environment variables. - </td> - </tr> - </table> - <p> - The following is a list of available global configuration properties. Note that these can only be set once - per JVM process unlike configuration settings available in configuration files. The <i>Property Name</i> - column contains the name used in properties files and system properties; <i>Environemt Variable</i> - for the equivalent environment variable; and <i>Legacy Property Name</i> for the pre-2.10 name. - </p> -<style> - * { // this works for all but td - word-wrap:break-word; - } - - table { // this somehow makes it work for td - table-layout:fixed; - width:100%; - } -</style> -<table style="table-layout: fixed; width: 100%"> - <caption align="top">Log4j 2 global configuration properties</caption> - <tr> - <th>Property Name <br /> (Legacy Property Name)</th> - <th>Environment Variable</th> - <th>Default Value</th> - <th>Description</th> - </tr> - - <tr> - <td><a name="configurationFile"/>log4j2.configurationFile - <br /> - (<a name="log4j.configurationFile"/>log4j.configurationFile) - </td> - <td>LOG4J_CONFIGURATION_FILE</td> - <td> </td> - <td> - Path to an Log4j 2 configuration file. May also contain a comma separated list of configuration file names. - </td> - </tr> - <tr> - <td><a name="debug"/>log4j2.debug - <br /> - (<a name="log4j2.debug"/>log4j2.debug) - </td> - <td>LOG4J_DEBUG</td> - <td> </td> - <td> - Log4j2 will print all internal logging to the console if system property - <tt>log4j2.debug</tt> is defined (with any or no value). - </td> - </tr> - <tr> - <td><a name="mergeFactory"/>log4j2.mergeFactory - <br /> - (<a name="log4j.mergeFactory"/>log4j.mergeFactory) - </td> - <td>LOG4J_MERGE_FACTORY</td> - <td> </td> - <td> - The name of the class that implements the MergeStrategy interface. If not specified - <code>DefaultMergeStrategy</code> will be used when creating a Composi
<TRUNCATED>