You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by Matt Sicker <bo...@gmail.com> on 2017/01/15 18:29:05 UTC
Fwd: logging-log4j2 git commit: [LOG4J2-1787]: Document how to
exclude transitive conflicting dependencies in Maven and Gradle
Oh no, it appears that I've converted the line endings to LF.
---------- Forwarded message ----------
From: <ma...@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: commits@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 <bo...@gmail.com>
Authored: Sun Jan 15 12:24:27 2017 -0600
Committer: Matt Sicker <bo...@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="remkop@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="remkop@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 <bo...@gmail.com>