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>&lt;Configuration status="trace"&gt;</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>&lt;Configuration status="trace"&gt;</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>

Reply via email to