Oh no, it appears that I've converted the line endings to LF. ---------- Forwarded message ---------- From: <mattsic...@apache.org> Date: 15 January 2017 at 12:24 Subject: logging-log4j2 git commit: [LOG4J2-1787]: Document how to exclude transitive conflicting dependencies in Maven and Gradle To: comm...@logging.apache.org
Repository: logging-log4j2 Updated Branches: refs/heads/master a840a4f1b -> f1f0b21bf [LOG4J2-1787]: Document how to exclude transitive conflicting dependencies in Maven and Gradle * Changes faq.xml to a velocity template to include log4j release version property. Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/ commit/f1f0b21b Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/f1f0b21b Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/f1f0b21b Branch: refs/heads/master Commit: f1f0b21bfdb8a0e48cf5a64a9530464f9f57a30b Parents: a840a4f Author: Matt Sicker <boa...@gmail.com> Authored: Sun Jan 15 12:24:27 2017 -0600 Committer: Matt Sicker <boa...@gmail.com> Committed: Sun Jan 15 12:24:27 2017 -0600 ---------------------------------------------------------------------- src/changes/changes.xml | 3 + src/site/xdoc/faq.xml | 400 -------------------------------- src/site/xdoc/faq.xml.vm | 518 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 521 insertions(+), 400 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ f1f0b21b/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a9d16c1..2d51ffe 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -246,6 +246,9 @@ <action issue="LOG4J2-1302" dev="rpopma" type="update"> The log4j-slf4j-impl module now declares a runtime dependency on log4j-core. While not technically required, this makes the log4j-slf4j-impl module behave similarly to slf4j-log4j12, and facilitates migration to Log4j 2. </action> + <action issue="LOG4J2-1787" dev="mattsicker" type="add"> + Document how to exclude transitive conflicting dependencies in Maven and Gradle. + </action> <action issue="LOG4J2-1773" dev="mattsicker" type="add"> Add StatusLoggerRule to allow unit tests to set a status level. </action> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ f1f0b21b/src/site/xdoc/faq.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/faq.xml b/src/site/xdoc/faq.xml deleted file mode 100644 index c3dbc75..0000000 --- a/src/site/xdoc/faq.xml +++ /dev/null @@ -1,400 +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. ---> - -<document> - <properties> - <title>Frequently Asked Questions</title> - <author email="rem...@yahoo.com">Remko Popma</author> - </properties> - - <body> - <section name="Frequently Asked Questions"> - <ul> - <li><a href="#missing_core">I'm seeing this error "Unable to locate a logging implementation, using SimpleLogger". - What is wrong?</a></li> - <li><a href="#which_jars">Which JAR files do I need?</a></li> - <li><a href="#config_location">How do I specify the configuration file location?</a></li> - <li><a href="#config_from_code">How do I configure log4j2 in code without a configuration file?</a></li> - <li><a href="#reconfig_from_code">How do I reconfigure log4j2 in code with a specific configuration file?</a></li> - <li><a href="#shutdown">How do I shut down log4j2 in code?</a></li> - <li><a href="#config_sep_appender_level">How do I send log messages with different levels to different appenders?</a></li> - <li><a href="#troubleshooting">How do I debug my configuration?</a></li> - <li><a href="#separate_log_files">How do I dynamically write to separate log files?</a></li> - <li><a href="#reconfig_level_from_code">How do I set a logger's level programmatically?</a></li> - <li><a href="#retention">How do I set my log archive retention policy? How do I delete old log archives?</a></li> - <li><a href="#api-tradeoffs">What are the trade-offs of using the Log4j 2 API versus the SLF4J API?</a></li> - <li><a href="#gc-free-slf4j">Is Log4j 2 still garbage-free when I use the SLF4J API?</a></li> - <li><a href="#gc-free-domain-object">How do I log my domain object without creating garbage?</a> </li> - <li><a href="#logger-wrapper">How do I create a custom logger wrapper that shows the correct class, method and line number?</a></li> - - </ul> - <subsection> - <a name="missing_core"/> - <h4>I'm seeing this error "Unable to locate a logging implementation, using SimpleLogger". - What is wrong? - </h4> - <p>You have the log4j-api-2.x jar file in your classpath but you still need to add the log4j-core-2.x jar to the - classpath. (Also, it looks like you are using an old version of Log4j 2. You may want to upgrade.) - </p> - - <a name="which_jars"/> - <h4>Which JAR files do I need?</h4> - <p>You need at least the log4j-api-2.x and the log4j-core-2.x jar files.</p> - <p>The other jars are necessary if your application calls the API - of another logging framework and you want to route logging calls to the Log4j 2 implementation. - </p> - <p> - <img src="images/whichjar-2.x.png" alt="Diagram showing which JARs correspond to which systems"/> - </p> - <a name="which_jars_log4j-to-slf4j" /> - <p>You can use the log4j-to-slf4j adapter jar when your application calls the Log4j 2 API and you - want to route logging calls to a SLF4J implementation. - </p> - <p> - <img src="images/whichjar-slf4j-2.x.png" - alt="Diagram showing the dependency flow to use Log4j 2 API with SLF4J"/> - </p> - <p>Some of the Log4j components have features with optional dependencies. - The component page will have more detail. - For example, the - <a href="log4j-core/index.html">log4j-core component page</a> - has an outline of which log4j-core features have external dependencies. - </p> - - <a name="config_location"/> - <h4>How do I specify the configuration file location?</h4> - <p>By default, Log4j looks for a configuration file named - <b>log4j2.xml</b> - (not log4j.xml) in the classpath. - </p> - <p> - You can also specify the full path of the configuration file with this system property: - <br/> - <code>-Dlog4j.configurationFile=path/to/log4j2.xml</code> - </p> - <p>Web applications can specify the Log4j configuration file location with a servlet context parameter. - See - <a href="http://logging.apache.org/log4j/2.x/manual/webapp. html#ContextParams">this section</a> - of the Using Log4j 2 in Web Applications manual page. - </p> - - <a name="config_from_code"/> - <h4>How do I configure log4j2 in code without a configuration file?</h4> - <p>Starting with version 2.4, Log4j 2 provides an <a href="manual/customconfig.html">API - for programmatic configuration</a>. - The new - <a href="log4j-core/apidocs/org/apache/logging/log4j/core/ config/builder/api/ConfigurationBuilder.html">ConfigurationBuilder - API - </a> - allows you to create Configurations in code by constructing component definitions - without requiring you to know about the internals of actual configuration objects like Loggers and Appenders. - </p> - - <a name="reconfig_from_code"/> - <h4>How do I reconfigure log4j2 in code with a specific configuration file?</h4> - <p>See the below example. - Be aware that this LoggerContext class is not part of the public API so your code may break with any minor release. - </p> - <pre class="prettyprint linenums"><![CDATA[ -// import org.apache.logging.log4j.core.LoggerContext; - -LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false); -File file = new File("path/to/a/different/log4j2.xml"); - -// this will force a reconfiguration -context.setConfigLocation(file.toURI()); -]]></pre> - - <a name="shutdown"/> - <h4>How do I shut down log4j2 in code?</h4> - <p>Normally there is no need to do this manually. - Each LoggerContext registers a shutdown hook that takes care of releasing resources - when the JVM exits (unless system property - <code>log4j.shutdownHookEnabled</code> - is set to<code>false</code>). - Web applications should include the log4j-web - module in their classpath which disables the shutdown hook but instead - cleans up log4j resources when the web application is stopped. - </p> - <p>However, if you need to manually shut down log4j, you can do so - as in the below example. - Be aware that these classes are not part of the public API so your code may break with any minor release. - </p> - <pre class="prettyprint linenums">// import org.apache.logging.log4j.core.LoggerContext; -// import org.apache.logging.log4j.core.config.Configurator; - -// get the current context -LoggerContext context = (LoggerContext) LogManager.getContext(); -Configurator.shutdown(context); - </pre> - - <a name="config_sep_appender_level"/> - <h4>How do I send log messages with different levels to different appenders?</h4> - You don't need to declare separate loggers to achieve this. - You can set the logging level on the - <code>AppenderRef</code> - element. - <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?> -<Configuration status="WARN"> - <Appenders> - <File name="file" fileName="app.log"> - <PatternLayout> - <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern> - </PatternLayout> - </File> - <Console name="STDOUT" target="SYSTEM_OUT"> - <PatternLayout pattern="%m%n"/> - </Console> - </Appenders> - <Loggers> - <Root level="trace"> - <AppenderRef ref="file" level="DEBUG"/> - <AppenderRef ref="STDOUT" level="INFO"/> - </Root> - </Loggers> -</Configuration>]]></pre> - - <a name="troubleshooting"/> - <h4>How do I debug my configuration?</h4> - <p>First, make sure you have - <a href="#which_jars">the right jar files</a> - on your classpath. - You need at least log4j-api and log4j-core. - </p> - <p>Next, check the name of your configuration file. By default, log4j2 will look - for a configuration file named - <code>log4j2.xml</code> - on the classpath. Note the "2" in the file name! - (See the - <a href="manual/configuration.html#AutomaticConfiguration">configuration manual page</a> - for more details.) - </p> - <p>If the configuration file is found correctly, log4j2 internal status logging can be controlled by - setting - <code><Configuration status="trace"></code> - in the configuration file. - This will display detailed log4j2-internal - log statements on the console about what happens during the configuration process. - This may be useful to trouble-shoot configuration issues. - By default the status logger level is WARN, so you only see notifications when there is a problem. - </p> - <p>If the configuration file is not found correctly, you can still enable - log4j2 internal status logging by setting system property - <code>-Dorg.apache.logging.log4j.simplelog.StatusLogger. level=TRACE</code>. - </p> - - <a name="separate_log_files"/> - <h4>How do I dynamically write to separate log files?</h4> - <p> - Look at the - <a href="http://logging.apache.org/log4j/2.x/manual/ appenders.html#RoutingAppender">RoutingAppender</a>. - You can define multiple routes in the configuration, - and put values in the - <code>ThreadContext</code> - map that determine - which log file subsequent events in this thread get logged to. - </p> - <p> - You can use the - <code>ThreadContext</code> - map value to determine the log file name. - </p> - <pre class="prettyprint linenums"><![CDATA[<Routing name="Routing"> - <Routes pattern="$${ctx:ROUTINGKEY}"> - - <!-- This route is chosen if ThreadContext has value 'special' for key ROUTINGKEY. --> - <Route key="special"> - <RollingFile name="Rolling-${ctx:ROUTINGKEY}" fileName="logs/special-${ctx:ROUTINGKEY}.log" - filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}- special-%d{yyyy-MM-dd}-%i.log.gz"> - <PatternLayout> - <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> - </PatternLayout> - <Policies> - <TimeBasedTriggeringPolicy interval="6" modulate="true" /> - <SizeBasedTriggeringPolicy size="10 MB" /> - </Policies> - </RollingFile> - </Route> - - <!-- This route is chosen if ThreadContext has no value for key ROUTINGKEY. --> - <Route key="$${ctx:ROUTINGKEY}"> - <RollingFile name="Rolling-default" fileName="logs/default.log" - filePattern="./logs/${date:yyyy-MM}/default-%d{yyyy-MM- dd}-%i.log.gz"> - <PatternLayout> - <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> - </PatternLayout> - <Policies> - <TimeBasedTriggeringPolicy interval="6" modulate="true" /> - <SizeBasedTriggeringPolicy size="10 MB" /> - </Policies> - </RollingFile> - </Route> - - <!-- This route is chosen if ThreadContext has a value for ROUTINGKEY - (other than the value 'special' which had its own route above). - The value dynamically determines the name of the log file. --> - <Route> - <RollingFile name="Rolling-${ctx:ROUTINGKEY}" fileName="logs/other-${ctx:ROUTINGKEY}.log" - filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}- other-%d{yyyy-MM-dd}-%i.log.gz"> - <PatternLayout> - <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> - </PatternLayout> - <Policies> - <TimeBasedTriggeringPolicy interval="6" modulate="true" /> - <SizeBasedTriggeringPolicy size="10 MB" /> - </Policies> - </RollingFile> - </Route> - </Routes> -</Routing>]]></pre> - - <a name="reconfig_level_from_code"/> - <h4>How do I set a logger's level programmatically?</h4> - <p>You can set a logger's level with the class Configurator from Core module. - Be aware that the Configuration class is not part of the public API. - </p> - <pre class="prettyprint linenums">// org.apache.logging.log4j.core. config.Configurator; - -Configurator.setLevel("com.example.Foo", Level.DEBUG); - -// You can also set the root logger: -Configurator.setRootLevel(Level.DEBUG); - </pre> - - <a name="retention"/> - <h4>How do I set my log archive retention policy? How do I delete old log archives?</h4> - <p>The - <tt>DefaultRolloverStrategy</tt> - of the Rolling File appender (and Rolling Random Access File - appender) supports a - <a href="manual/appenders.html#CustomDeleteOnRollover">Delete</a> - element. - </p> - <p>Starting at a specified base directory, you can delete all files for which some condition - holds true, for example all files that match a given file name pattern and are older - than some number of days. More complex conditions are possible, and if the built-in - conditions are not sufficient, users can provide - custom conditions by creating - <a href="manual/appenders.html#DeletePathCondition">plugin conditions</a> - or by - writing a - <a href="manual/appenders.html#ScriptCondition">script condition</a> - </p> - <a name="api-tradeoffs" /> - <h4>What are the trade-offs of using the Log4j 2 API versus the SLF4J API?</h4> - <p> - The Log4j 2 API and SLF4J have a lot in common. - They both share the objective of cleanly separating the logging API from the implementation. - We believe that the Log4j 2 API can help make your application more performant - while offering more functionality and more flexibility. - </p> - <p> - There may be a concern that using the Log4j 2 API will tightly couple your application to Log4j 2. - This is not the case: applications coded to the Log4j 2 API always have the option to use any SLF4J-compliant - library as their logging implementation with the log4j-to-slf4j adapter. - See the <a href="#which_jars_log4j-to-slf4j">which jars</a> FAQ entry for details. - </p> - <p> - There are several advantages to using the Log4j 2 API: - </p> - <ul> - <li>SLF4J forces your application to log Strings. - The Log4j 2 API supports logging any CharSequence if you want to log text, but also - supports logging any Object as is. - It is the responsibility of the logging <em>implementation</em> to handle this object, - and we consider it a design mistake to limit applications to logging Strings.</li> - <li> - The Log4j 2 API offers support for logging <a href="manual/messages.html">Message objects</a>. - Messages allow support for interesting and complex constructs to be passed - through the logging system and be efficiently manipulated. - Users are free to create their own Message types and write custom Layouts, - Filters and Lookups to manipulate them. - </li> - <li>The Log4j 2 API has support for Java 8 - <a href="manual/api.html#LambdaSupport">lambda expressions</a>.</li> - <li> - The Log4j 2 API has better support for <a href="manual/garbagefree.html">garbage-free logging</a>: - it avoids creating vararg arrays and avoids creating Strings when logging CharSequence objects. - </li> - </ul> - - - <a name="gc-free-slf4j" /> - <h4>Is Log4j 2 still garbage-free when I use the SLF4J API?</h4> - <p>Yes, the log4j-slf4j-impl binding (together with log4j-core) implements the - <tt>org.slf4j.Logger</tt> methods to be GC-free. - However, bear in mind that there are some limitations:</p> - <p>The SLF4J API only offers up to two parameters for a parameterized message. - More than that uses varargs which creates a temporary object for the parameter array. - The Log4j 2.6 API has methods for up to ten unrolled parameters.</p> - <p> - Another consideration is that the SLF4J API forces your application to log Strings. - Log4j 2 API lets you log any java.lang.CharSequence, and even any Objects. - Log4j can log any Object that implements <tt>java.lang.CharSequence</tt> - or <tt>org.apache.logging.log4j.util.StringBuilderFormattable</tt> without creating garbage. - </p> - <p> - The <tt>org.slf4j.spi.LocationAwareLogger::<a href=" http://www.slf4j.org/api/org/slf4j/spi/LocationAwareLogger.html#log( org.slf4j.Marker, java.lang.String, int, java.lang.String, java.lang.Object[], java.lang.Throwable)">log</a></tt> - method is not yet implemented - in a garbage-free manner in the log4j-slf4j-impl binding. It creates a new message object for each call. - </p> - - <a name="gc-free-domain-object" /> - <h4>How do I log my domain object without creating garbage?</h4> - <p>One option is to let the domain object implement java.lang.CharSequence. - However, for many domain objects it may not be trivial to implement this without allocating temporary - objects.</p> - <p>An alternative is to implement the <tt>org.apache.logging.log4j. util.StringBuilderFormattable</tt> interface. - If an object is logged that implements this interface, its <tt>formatTo</tt> method is called instead of - <tt>toString()</tt>. - </p> - <pre class="prettyprint linenums">package org.apache.logging.log4j.util; -public interface StringBuilderFormattable { - /** - * Writes a text representation of this object into the specified {@code StringBuilder}, - * ideally without allocating temporary objects. - * - * @param buffer the StringBuilder to write into - */ - void formatTo(StringBuilder buffer); -} -</pre> - - <a name="logger-wrapper" /> - <h4>How do I create a custom logger wrapper that shows the correct class, method and line number?</h4> - <p> - Log4j remembers the fully qualified class name (FQCN) of the logger and uses this to walk the stack trace - for every log event when configured to print location. - (Be aware that logging with location is slow and may impact the performance of your application.) - </p><p> - The problem with custom logger wrappers is that they have a different FQCN than the actual logger, - so Log4j can't find the place where your custom logger was called. - </p><p> - The solution is to provide the correct FQCN. The easiest way to do this is to let Log4j generate - the logger wrapper for you. Log4j comes with a Logger wrapper generator tool. - This tool was originally meant to support custom log levels and is documented - <a href="https://logging.apache.org/log4j/2.x/manual/ customloglevels.html#CustomLoggers">here</a>. - </p><p> - The generated logger code will take care of the FQCN. - </p> - - </subsection> - </section> - - </body> -</document> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ f1f0b21b/src/site/xdoc/faq.xml.vm ---------------------------------------------------------------------- diff --git a/src/site/xdoc/faq.xml.vm b/src/site/xdoc/faq.xml.vm new file mode 100644 index 0000000..e2b3483 --- /dev/null +++ b/src/site/xdoc/faq.xml.vm @@ -0,0 +1,518 @@ +<?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> + <properties> + <title>Frequently Asked Questions</title> + <author email="rem...@yahoo.com">Remko Popma</author> + </properties> + + <body> + <section name="Frequently Asked Questions"> + <ul> + <li><a href="#missing_core">I'm seeing this error "Unable to locate a logging implementation, using SimpleLogger". + What is wrong?</a></li> + <li><a href="#which_jars">Which JAR files do I need?</a></li> + <li><a href="#exclusions">How do I exclude conflicting dependencies?</a></li> + <li><a href="#config_location">How do I specify the configuration file location?</a></li> + <li><a href="#config_from_code">How do I configure log4j2 in code without a configuration file?</a></li> + <li><a href="#reconfig_from_code">How do I reconfigure log4j2 in code with a specific configuration file?</a></li> + <li><a href="#shutdown">How do I shut down log4j2 in code?</a></li> + <li><a href="#config_sep_appender_level">How do I send log messages with different levels to different appenders?</a></li> + <li><a href="#troubleshooting">How do I debug my configuration?</a></li> + <li><a href="#separate_log_files">How do I dynamically write to separate log files?</a></li> + <li><a href="#reconfig_level_from_code">How do I set a logger's level programmatically?</a></li> + <li><a href="#retention">How do I set my log archive retention policy? How do I delete old log archives?</a></li> + <li><a href="#api-tradeoffs">What are the trade-offs of using the Log4j 2 API versus the SLF4J API?</a></li> + <li><a href="#gc-free-slf4j">Is Log4j 2 still garbage-free when I use the SLF4J API?</a></li> + <li><a href="#gc-free-domain-object">How do I log my domain object without creating garbage?</a> </li> + <li><a href="#logger-wrapper">How do I create a custom logger wrapper that shows the correct class, method and line number?</a></li> + + </ul> + <subsection> + <a name="missing_core"/> + <h4>I'm seeing this error "Unable to locate a logging implementation, using SimpleLogger". + What is wrong? + </h4> + <p>You have the log4j-api-2.x jar file in your classpath but you still need to add the log4j-core-2.x jar to the + classpath. (Also, it looks like you are using an old version of Log4j 2. You may want to upgrade.) + </p> + + <a name="which_jars"/> + <h4>Which JAR files do I need?</h4> + <p>You need at least the log4j-api-2.x and the log4j-core-2.x jar files.</p> + <p>The other jars are necessary if your application calls the API + of another logging framework and you want to route logging calls to the Log4j 2 implementation. + </p> + <p> + <img src="images/whichjar-2.x.png" alt="Diagram showing which JARs correspond to which systems"/> + </p> + <a name="which_jars_log4j-to-slf4j" /> + <p>You can use the log4j-to-slf4j adapter jar when your application calls the Log4j 2 API and you + want to route logging calls to a SLF4J implementation. + </p> + <p> + <img src="images/whichjar-slf4j-2.x.png" + alt="Diagram showing the dependency flow to use Log4j 2 API with SLF4J"/> + </p> + <p>Some of the Log4j components have features with optional dependencies. + The component page will have more detail. + For example, the + <a href="log4j-core/index.html">log4j-core component page</a> + has an outline of which log4j-core features have external dependencies. + </p> + + <a name="exclusions"/> + <h4>How do I exclude conflicting dependencies?</h4> + <p> + There are several scenarios where you may end up with conflicting dependencies, especially transitively + included ones. The following table shows for each Log4j dependency on the left (implicit groupId of + <code>org.apache.logging.log4j</code>), the following dependencies on the right can be safely excluded + (given in the format <code>groupId:artifactId</code>). + </p> + <table class="table table-bordered"> + <tr> + <th>Log4j Dependency</th> + <th colspan="3">Dependencies to Exclude</th> + </tr> + <tr> + <td><a href="log4j-1.2-api">log4j-1.2-api</a></td> + <td>log4j:log4j</td> + <td>org.slf4j:log4j-over-slf4j</td> + <td/> + </tr> + <tr> + <td><a href="log4j-core">log4j-core</a></td> + <td>log4j:log4j</td> + <td>ch.qos.logback:logback-core</td> + <td>org.apache.logging.log4j:log4j-to-slf4j</td> + </tr> + <tr> + <td><a href="log4j-jcl">log4j-jcl</a></td> + <td>org.slf4j:jcl-over-slf4j</td> + <td/> + <td/> + </tr> + <tr> + <td><a href="log4j-jul">log4j-jul</a></td> + <td>org.slf4j:jul-to-slf4j</td> + <td/> + <td/> + </tr> + <tr> + <td><a href="log4j-slf4j-impl">log4j-slf4j-impl</a></td> + <td>org.apache.logging.log4j:log4j-to-slf4j</td> + <td>ch.qos.logback:logback-core</td> + <td/> + </tr> + </table> + <p> + Using Apache Maven, dependencies can be globally excluded in your project like so: + </p> + <pre class="prettyprint linenums"><![CDATA[ +<dependencies> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>1.2.17</version> + <scope>provided</scope> + </dependency> +</dependencies> +]]></pre> + <p> + Dependencies can be explicitly excluded for specific dependencies as well. For example, to use a project + with Log4j 2 instead of Log4j 1.x: + </p> + <pre class="prettyprint linenums"><![CDATA[ +<dependencies> + <dependency> + <groupId>com.example</groupId> + <artifactId>example-project</artifactId> + <version>1.0</version> + <exclusions> + <exclusion> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>${Log4jReleaseVersion}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <version>${Log4jReleaseVersion}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-1.2-api</artifactId> + <version>${Log4jReleaseVersion}</version> + </dependency> +</dependencies> +]]></pre> + <p> + Dependencies can be globally excluded in Gradle like so: + </p> + <pre class="prettyprint linenums"><![CDATA[ +configurations { + all*.exclude group: 'log4j', module: 'log4j' +} +]]></pre> + <p> + The equivalent Gradle config for the above Maven exclusion would look like: + </p> + <pre class="prettyprint linenums"><![CDATA[ +dependencies { + compile('com.example:example-project:1.0') { + exclude group: 'log4j', module: 'log4j' + exclude group: 'org.slf4j', module: 'slf4j-log4j12' + } + compile('org.apache.logging.log4j:log4j-core:${Log4jReleaseVersion}') + compile('org.apache.logging.log4j:log4j-slf4j-impl:${ Log4jReleaseVersion}') + compile('org.apache.logging.log4j:log4j-1.2-api:${Log4jReleaseVersion}') +]]></pre> + + <a name="config_location"/> + <h4>How do I specify the configuration file location?</h4> + <p>By default, Log4j looks for a configuration file named + <b>log4j2.xml</b> + (not log4j.xml) in the classpath. + </p> + <p> + You can also specify the full path of the configuration file with this system property: + <br/> + <code>-Dlog4j.configurationFile=path/to/log4j2.xml</code> + </p> + <p>Web applications can specify the Log4j configuration file location with a servlet context parameter. + See + <a href="http://logging.apache.org/log4j/2.x/manual/webapp. html#ContextParams">this section</a> + of the Using Log4j 2 in Web Applications manual page. + </p> + + <a name="config_from_code"/> + <h4>How do I configure log4j2 in code without a configuration file?</h4> + <p>Starting with version 2.4, Log4j 2 provides an <a href="manual/customconfig.html">API + for programmatic configuration</a>. + The new + <a href="log4j-core/apidocs/org/apache/logging/log4j/core/ config/builder/api/ConfigurationBuilder.html">ConfigurationBuilder + API + </a> + allows you to create Configurations in code by constructing component definitions + without requiring you to know about the internals of actual configuration objects like Loggers and Appenders. + </p> + + <a name="reconfig_from_code"/> + <h4>How do I reconfigure log4j2 in code with a specific configuration file?</h4> + <p>See the below example. + Be aware that this LoggerContext class is not part of the public API so your code may break with any minor release. + </p> + <pre class="prettyprint linenums"><![CDATA[ +// import org.apache.logging.log4j.core.LoggerContext; + +LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false); +File file = new File("path/to/a/different/log4j2.xml"); + +// this will force a reconfiguration +context.setConfigLocation(file.toURI()); +]]></pre> + + <a name="shutdown"/> + <h4>How do I shut down log4j2 in code?</h4> + <p>Normally there is no need to do this manually. + Each LoggerContext registers a shutdown hook that takes care of releasing resources + when the JVM exits (unless system property + <code>log4j.shutdownHookEnabled</code> + is set to<code>false</code>). + Web applications should include the log4j-web + module in their classpath which disables the shutdown hook but instead + cleans up log4j resources when the web application is stopped. + </p> + <p>However, if you need to manually shut down log4j, you can do so + as in the below example. + Be aware that these classes are not part of the public API so your code may break with any minor release. + </p> + <pre class="prettyprint linenums">// import org.apache.logging.log4j.core.LoggerContext; +// import org.apache.logging.log4j.core.config.Configurator; + +// get the current context +LoggerContext context = (LoggerContext) LogManager.getContext(); +Configurator.shutdown(context); + </pre> + + <a name="config_sep_appender_level"/> + <h4>How do I send log messages with different levels to different appenders?</h4> + You don't need to declare separate loggers to achieve this. + You can set the logging level on the + <code>AppenderRef</code> + element. + <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?> +<Configuration status="WARN"> + <Appenders> + <File name="file" fileName="app.log"> + <PatternLayout> + <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern> + </PatternLayout> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%m%n"/> + </Console> + </Appenders> + <Loggers> + <Root level="trace"> + <AppenderRef ref="file" level="DEBUG"/> + <AppenderRef ref="STDOUT" level="INFO"/> + </Root> + </Loggers> +</Configuration>]]></pre> + + <a name="troubleshooting"/> + <h4>How do I debug my configuration?</h4> + <p>First, make sure you have + <a href="#which_jars">the right jar files</a> + on your classpath. + You need at least log4j-api and log4j-core. + </p> + <p>Next, check the name of your configuration file. By default, log4j2 will look + for a configuration file named + <code>log4j2.xml</code> + on the classpath. Note the "2" in the file name! + (See the + <a href="manual/configuration.html#AutomaticConfiguration">configuration manual page</a> + for more details.) + </p> + <p>If the configuration file is found correctly, log4j2 internal status logging can be controlled by + setting + <code><Configuration status="trace"></code> + in the configuration file. + This will display detailed log4j2-internal + log statements on the console about what happens during the configuration process. + This may be useful to trouble-shoot configuration issues. + By default the status logger level is WARN, so you only see notifications when there is a problem. + </p> + <p>If the configuration file is not found correctly, you can still enable + log4j2 internal status logging by setting system property + <code>-Dorg.apache.logging.log4j.simplelog.StatusLogger. level=TRACE</code>. + </p> + + <a name="separate_log_files"/> + <h4>How do I dynamically write to separate log files?</h4> + <p> + Look at the + <a href="http://logging.apache.org/log4j/2.x/manual/ appenders.html#RoutingAppender">RoutingAppender</a>. + You can define multiple routes in the configuration, + and put values in the + <code>ThreadContext</code> + map that determine + which log file subsequent events in this thread get logged to. + </p> + <p> + You can use the + <code>ThreadContext</code> + map value to determine the log file name. + </p> + <pre class="prettyprint linenums"><![CDATA[<Routing name="Routing"> + <Routes pattern="${dollar}${dollar}{ctx:ROUTINGKEY}"> + + <!-- This route is chosen if ThreadContext has value 'special' for key ROUTINGKEY. --> + <Route key="special"> + <RollingFile name="Rolling-${dollar}{ctx:ROUTINGKEY}" fileName="logs/special-${dollar}{ctx:ROUTINGKEY}.log" + filePattern="./logs/${dollar}{date:yyyy-MM}/${dollar}{ctx: ROUTINGKEY}-special-%d{yyyy-MM-dd}-%i.log.gz"> + <PatternLayout> + <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> + </PatternLayout> + <Policies> + <TimeBasedTriggeringPolicy interval="6" modulate="true" /> + <SizeBasedTriggeringPolicy size="10 MB" /> + </Policies> + </RollingFile> + </Route> + + <!-- This route is chosen if ThreadContext has no value for key ROUTINGKEY. --> + <Route key="$${dollar}{ctx:ROUTINGKEY}"> + <RollingFile name="Rolling-default" fileName="logs/default.log" + filePattern="./logs/${dollar}{date:yyyy-MM}/default-%d{yyyy- MM-dd}-%i.log.gz"> + <PatternLayout> + <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> + </PatternLayout> + <Policies> + <TimeBasedTriggeringPolicy interval="6" modulate="true" /> + <SizeBasedTriggeringPolicy size="10 MB" /> + </Policies> + </RollingFile> + </Route> + + <!-- This route is chosen if ThreadContext has a value for ROUTINGKEY + (other than the value 'special' which had its own route above). + The value dynamically determines the name of the log file. --> + <Route> + <RollingFile name="Rolling-${dollar}{ctx:ROUTINGKEY}" fileName="logs/other-${dollar}{ctx:ROUTINGKEY}.log" + filePattern="./logs/${dollar}{date:yyyy-MM}/${dollar}{ctx: ROUTINGKEY}-other-%d{yyyy-MM-dd}-%i.log.gz"> + <PatternLayout> + <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> + </PatternLayout> + <Policies> + <TimeBasedTriggeringPolicy interval="6" modulate="true" /> + <SizeBasedTriggeringPolicy size="10 MB" /> + </Policies> + </RollingFile> + </Route> + </Routes> +</Routing>]]></pre> + + <a name="reconfig_level_from_code"/> + <h4>How do I set a logger's level programmatically?</h4> + <p>You can set a logger's level with the class Configurator from Core module. + Be aware that the Configuration class is not part of the public API. + </p> + <pre class="prettyprint linenums">// org.apache.logging.log4j.core. config.Configurator; + +Configurator.setLevel("com.example.Foo", Level.DEBUG); + +// You can also set the root logger: +Configurator.setRootLevel(Level.DEBUG); + </pre> + + <a name="retention"/> + <h4>How do I set my log archive retention policy? How do I delete old log archives?</h4> + <p>The + <tt>DefaultRolloverStrategy</tt> + of the Rolling File appender (and Rolling Random Access File + appender) supports a + <a href="manual/appenders.html#CustomDeleteOnRollover">Delete</a> + element. + </p> + <p>Starting at a specified base directory, you can delete all files for which some condition + holds true, for example all files that match a given file name pattern and are older + than some number of days. More complex conditions are possible, and if the built-in + conditions are not sufficient, users can provide + custom conditions by creating + <a href="manual/appenders.html#DeletePathCondition">plugin conditions</a> + or by + writing a + <a href="manual/appenders.html#ScriptCondition">script condition</a> + </p> + <a name="api-tradeoffs" /> + <h4>What are the trade-offs of using the Log4j 2 API versus the SLF4J API?</h4> + <p> + The Log4j 2 API and SLF4J have a lot in common. + They both share the objective of cleanly separating the logging API from the implementation. + We believe that the Log4j 2 API can help make your application more performant + while offering more functionality and more flexibility. + </p> + <p> + There may be a concern that using the Log4j 2 API will tightly couple your application to Log4j 2. + This is not the case: applications coded to the Log4j 2 API always have the option to use any SLF4J-compliant + library as their logging implementation with the log4j-to-slf4j adapter. + See the <a href="#which_jars_log4j-to-slf4j">which jars</a> FAQ entry for details. + </p> + <p> + There are several advantages to using the Log4j 2 API: + </p> + <ul> + <li>SLF4J forces your application to log Strings. + The Log4j 2 API supports logging any CharSequence if you want to log text, but also + supports logging any Object as is. + It is the responsibility of the logging <em>implementation</em> to handle this object, + and we consider it a design mistake to limit applications to logging Strings.</li> + <li> + The Log4j 2 API offers support for logging <a href="manual/messages.html">Message objects</a>. + Messages allow support for interesting and complex constructs to be passed + through the logging system and be efficiently manipulated. + Users are free to create their own Message types and write custom Layouts, + Filters and Lookups to manipulate them. + </li> + <li>The Log4j 2 API has support for Java 8 + <a href="manual/api.html#LambdaSupport">lambda expressions</a>.</li> + <li> + The Log4j 2 API has better support for <a href="manual/garbagefree.html">garbage-free logging</a>: + it avoids creating vararg arrays and avoids creating Strings when logging CharSequence objects. + </li> + </ul> + + + <a name="gc-free-slf4j" /> + <h4>Is Log4j 2 still garbage-free when I use the SLF4J API?</h4> + <p>Yes, the log4j-slf4j-impl binding (together with log4j-core) implements the + <tt>org.slf4j.Logger</tt> methods to be GC-free. + However, bear in mind that there are some limitations:</p> + <p>The SLF4J API only offers up to two parameters for a parameterized message. + More than that uses varargs which creates a temporary object for the parameter array. + The Log4j 2.6 API has methods for up to ten unrolled parameters.</p> + <p> + Another consideration is that the SLF4J API forces your application to log Strings. + Log4j 2 API lets you log any java.lang.CharSequence, and even any Objects. + Log4j can log any Object that implements <tt>java.lang.CharSequence</tt> + or <tt>org.apache.logging.log4j.util.StringBuilderFormattable</tt> without creating garbage. + </p> + <p> + The <tt>org.slf4j.spi.LocationAwareLogger::<a href=" http://www.slf4j.org/api/org/slf4j/spi/LocationAwareLogger.html#log( org.slf4j.Marker, java.lang.String, int, java.lang.String, java.lang.Object[], java.lang.Throwable)">log</a></tt> + method is not yet implemented + in a garbage-free manner in the log4j-slf4j-impl binding. It creates a new message object for each call. + </p> + + <a name="gc-free-domain-object" /> + <h4>How do I log my domain object without creating garbage?</h4> + <p>One option is to let the domain object implement java.lang.CharSequence. + However, for many domain objects it may not be trivial to implement this without allocating temporary + objects.</p> + <p>An alternative is to implement the <tt>org.apache.logging.log4j. util.StringBuilderFormattable</tt> interface. + If an object is logged that implements this interface, its <tt>formatTo</tt> method is called instead of + <tt>toString()</tt>. + </p> + <pre class="prettyprint linenums">package org.apache.logging.log4j.util; +public interface StringBuilderFormattable { + /** + * Writes a text representation of this object into the specified {@code StringBuilder}, + * ideally without allocating temporary objects. + * + * @param buffer the StringBuilder to write into + */ + void formatTo(StringBuilder buffer); +} +</pre> + + <a name="logger-wrapper" /> + <h4>How do I create a custom logger wrapper that shows the correct class, method and line number?</h4> + <p> + Log4j remembers the fully qualified class name (FQCN) of the logger and uses this to walk the stack trace + for every log event when configured to print location. + (Be aware that logging with location is slow and may impact the performance of your application.) + </p><p> + The problem with custom logger wrappers is that they have a different FQCN than the actual logger, + so Log4j can't find the place where your custom logger was called. + </p><p> + The solution is to provide the correct FQCN. The easiest way to do this is to let Log4j generate + the logger wrapper for you. Log4j comes with a Logger wrapper generator tool. + This tool was originally meant to support custom log levels and is documented + <a href="https://logging.apache.org/log4j/2.x/manual/ customloglevels.html#CustomLoggers">here</a>. + </p><p> + The generated logger code will take care of the FQCN. + </p> + + </subsection> + </section> + + </body> +</document> -- Matt Sicker <boa...@gmail.com>