blob: 72e9eb35ffff662239dd8c9c11eef03e2f9230f5 [file] [log] [blame]
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.9.1 from src/site/xdoc/manual/thread-context.xml at 2020-04-25
| Rendered using Apache Maven Fluido Skin 1.8
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="generator" content="Apache Maven Doxia Site Renderer 1.9.1" />
<meta name="author" content="Ralph Goers" />
<meta name="author" content="Gary Gregory" />
<title>Log4j &#x2013; Log4j 2 Thread Context</title>
<link rel="stylesheet" href="../css/apache-maven-fluido-1.8.min.css" />
<link rel="stylesheet" href="../css/site.css" />
<link rel="stylesheet" href="../css/print.css" media="print" />
<script src="../js/apache-maven-fluido-1.8.min.js"></script>
</head>
<body class="topBarDisabled">
<div class="container-fluid">
<header>
<div id="banner">
<div class="pull-left"><a href="http://logging.apache.org" id="bannerLeft"><img src="../images/ls-logo.jpg" alt=""/></a></div>
<div class="pull-right"><a href="http://logging.apache.org/log4j/2.x" id="bannerRight"><img src="../images/logo.png" alt=""/></a></div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 2020-04-25<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 2.13.2</li>
<li class="pull-right"><span class="divider">|</span>
<a href="https://github.com/apache/logging-log4j2" class="externalLink" title="GitHub">GitHub</a></li>
<li class="pull-right"><span class="divider">|</span>
<a href="https://analysis.apache.org/dashboard/index/org.apache.logging.log4j:log4j" class="externalLink" title="Sonar">Sonar</a></li>
<li class="pull-right"><span class="divider">|</span>
<a href="../../../" title="Logging Services">Logging Services</a></li>
<li class="pull-right"><span class="divider">|</span>
<a href="https://www.apache.org/" class="externalLink" title="Apache">Apache</a></li>
<li class="pull-right"><a href="https://cwiki.apache.org/confluence/display/LOGGING/Log4j" class="externalLink" title="Logging Wiki">Logging Wiki</a></li>
</ul>
</div>
</header>
<div class="row-fluid">
<header id="leftColumn" class="span2">
<nav class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/home.png" alt="Apache Log4j™ 2" border="0"/> Apache Log4j™ 2</li>
<li><a href="../index.html" title="About"><span class="none"></span>About</a></li>
<li><a href="../download.html" title="Download"><span class="none"></span>Download</a></li>
<li><a href="../javadoc.html" title="Javadoc"><span class="icon-chevron-right"></span>Javadoc</a></li>
<li><a href="../maven-artifacts.html" title="Maven, Ivy, Gradle Artifacts"><span class="icon-chevron-right"></span>Maven, Ivy, Gradle Artifacts</a></li>
<li><a href="../runtime-dependencies.html" title="Runtime Dependencies"><span class="none"></span>Runtime Dependencies</a></li>
<li><a href="../changelog.html" title="Changelog"><span class="none"></span>Changelog</a></li>
<li><a href="../faq.html" title="FAQ"><span class="none"></span>FAQ</a></li>
<li><a href="../performance.html" title="Performance"><span class="icon-chevron-right"></span>Performance</a></li>
<li><a href="../articles.html" title="Articles and Tutorials"><span class="none"></span>Articles and Tutorials</a></li>
<li><a href="../security.html" title="Security"><span class="none"></span>Security</a></li>
<li><a href="../support.html" title="Support"><span class="none"></span>Support</a></li>
<li><a href="../thanks.html" title="Thanks"><span class="none"></span>Thanks</a></li>
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/pencil.png" alt="For Contributors" border="0"/> For Contributors</li>
<li><a href="../build.html" title="Building Log4j from Source"><span class="none"></span>Building Log4j from Source</a></li>
<li><a href="../guidelines.html" title="Guidelines"><span class="none"></span>Guidelines</a></li>
<li><a href="../javastyle.html" title="Style Guide"><span class="none"></span>Style Guide</a></li>
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/book.png" alt="Manual" border="0"/> Manual</li>
<li><a href="../manual/index.html" title="Introduction"><span class="none"></span>Introduction</a></li>
<li><a href="../manual/architecture.html" title="Architecture"><span class="none"></span>Architecture</a></li>
<li><a href="../manual/compatibility.html" title="Log4j 1.x Compatibility"><span class="none"></span>Log4j 1.x Compatibility</a></li>
<li><a href="../manual/migration.html" title="Log4j 1.x Migration"><span class="none"></span>Log4j 1.x Migration</a></li>
<li><a href="../manual/api.html" title="Java API"><span class="icon-chevron-down"></span>Java API</a>
<ul class="nav nav-list">
<li><a href="../manual/logbuilder.html" title="Log Builder"><span class="none"></span>Log Builder</a></li>
<li><a href="../manual/flowtracing.html" title="Flow Tracing"><span class="none"></span>Flow Tracing</a></li>
<li><a href="../manual/markers.html" title="Markers"><span class="none"></span>Markers</a></li>
<li><a href="../manual/eventlogging.html" title="Event Logging"><span class="none"></span>Event Logging</a></li>
<li><a href="../manual/messages.html" title="Messages"><span class="none"></span>Messages</a></li>
<li class="active"><a href="#"><span class="none"></span>ThreadContext</a></li>
</ul></li>
<li><a href="../manual/scala-api.html" title="Scala API"><span class="none"></span>Scala API</a></li>
<li><a href="../manual/configuration.html" title="Configuration"><span class="icon-chevron-right"></span>Configuration</a></li>
<li><a href="../manual/usage.html" title="Usage"><span class="icon-chevron-right"></span>Usage</a></li>
<li><a href="../manual/webapp.html" title="Web Applications and JSPs"><span class="icon-chevron-right"></span>Web Applications and JSPs</a></li>
<li><a href="../manual/lookups.html" title="Lookups"><span class="icon-chevron-right"></span>Lookups</a></li>
<li><a href="../manual/appenders.html" title="Appenders"><span class="icon-chevron-right"></span>Appenders</a></li>
<li><a href="../manual/layouts.html" title="Layouts"><span class="icon-chevron-right"></span>Layouts</a></li>
<li><a href="../manual/filters.html" title="Filters"><span class="icon-chevron-right"></span>Filters</a></li>
<li><a href="../manual/async.html" title="Async Loggers"><span class="icon-chevron-right"></span>Async Loggers</a></li>
<li><a href="../manual/garbagefree.html" title="Garbage-free Logging"><span class="icon-chevron-right"></span>Garbage-free Logging</a></li>
<li><a href="../manual/jmx.html" title="JMX"><span class="none"></span>JMX</a></li>
<li><a href="../manual/logsep.html" title="Logging Separation"><span class="none"></span>Logging Separation</a></li>
<li><a href="../manual/extending.html" title="Extending Log4j"><span class="icon-chevron-right"></span>Extending Log4j</a></li>
<li><a href="../manual/plugins.html" title="Plugins"><span class="icon-chevron-right"></span>Plugins</a></li>
<li><a href="../manual/customconfig.html" title="Programmatic Log4j Configuration"><span class="icon-chevron-right"></span>Programmatic Log4j Configuration</a></li>
<li><a href="../manual/customloglevels.html" title="Custom Log Levels"><span class="icon-chevron-right"></span>Custom Log Levels</a></li>
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/tag.png" alt="Related Projects" border="0"/> Related Projects</li>
<li><a href="http://logging.apache.org/log4j/scala/index.html" class="externalLink" title="Log4j-Scala"><span class="none"></span>Log4j-Scala</a></li>
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/link.png" alt="Legacy Sites" border="0"/> Legacy Sites</li>
<li><a href="http://logging.apache.org/log4j/1.2/" class="externalLink" title="Log4j 1.2 - End of Life"><span class="none"></span>Log4j 1.2 - End of Life</a></li>
<li><a href="http://logging.apache.org/log4j/log4j-2.3/" class="externalLink" title="Log4j 2.3 - Java 6"><span class="none"></span>Log4j 2.3 - Java 6</a></li>
<li><a href="http://logging.apache.org/log4j/log4j-2.12.1" class="externalLink" title="Log4j 2.12.1 - Java 7"><span class="none"></span>Log4j 2.12.1 - Java 7</a></li>
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/cog.png" alt="Components" border="0"/> Components</li>
<li><a href="../log4j-api/index.html" title="API"><span class="none"></span>API</a></li>
<li><a href="../log4j-core/index.html" title="Implementation"><span class="none"></span>Implementation</a></li>
<li><a href="../log4j-jcl/index.html" title="Commons Logging Bridge"><span class="none"></span>Commons Logging Bridge</a></li>
<li><a href="../log4j-1.2-api/index.html" title="Log4j 1.2 API"><span class="none"></span>Log4j 1.2 API</a></li>
<li><a href="../log4j-slf4j-impl/index.html" title="SLF4J Binding"><span class="none"></span>SLF4J Binding</a></li>
<li><a href="../log4j-jul/index.html" title="JUL Adapter"><span class="none"></span>JUL Adapter</a></li>
<li><a href="../log4j-jpl/index.html" title="JDK Platform Logger"><span class="none"></span>JDK Platform Logger</a></li>
<li><a href="../log4j-to-slf4j/index.html" title="Log4j 2 to SLF4J Adapter"><span class="none"></span>Log4j 2 to SLF4J Adapter</a></li>
<li><a href="../log4j-flume-ng/index.html" title="Apache Flume Appender"><span class="none"></span>Apache Flume Appender</a></li>
<li><a href="../log4j-taglib/index.html" title="Log4j Tag Library"><span class="none"></span>Log4j Tag Library</a></li>
<li><a href="../log4j-jmx-gui/index.html" title="Log4j JMX GUI"><span class="none"></span>Log4j JMX GUI</a></li>
<li><a href="../log4j-web/index.html" title="Log4j Web Application Support"><span class="none"></span>Log4j Web Application Support</a></li>
<li><a href="../log4j-appserver/index.html" title="Log4j Application Server Integration"><span class="none"></span>Log4j Application Server Integration</a></li>
<li><a href="../log4j-couchdb/index.html" title="Log4j CouchDB appender"><span class="none"></span>Log4j CouchDB appender</a></li>
<li><a href="../log4j-mongodb2/index.html" title="Log4j MongoDB2 appender"><span class="none"></span>Log4j MongoDB2 appender</a></li>
<li><a href="../log4j-mongodb3/index.html" title="Log4j MongoDB3 appender"><span class="none"></span>Log4j MongoDB3 appender</a></li>
<li><a href="../log4j-cassandra/index.html" title="Log4j Cassandra appender"><span class="none"></span>Log4j Cassandra appender</a></li>
<li><a href="../log4j-iostreams/index.html" title="Log4j IO Streams"><span class="none"></span>Log4j IO Streams</a></li>
<li><a href="../log4j-liquibase/index.html" title="Log4j Liquibase Binding"><span class="none"></span>Log4j Liquibase Binding</a></li>
<li><a href="../log4j-docker/index.html" title="Log4j Docker Support"><span class="none"></span>Log4j Docker Support</a></li>
<li><a href="../log4j-spring-cloud-config/log4j-spring-cloud-config-client/index.html" title="Log4j Spring Cloud Config Client"><span class="none"></span>Log4j Spring Cloud Config Client</a></li>
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/info.png" alt="Project Information" border="0"/> Project Information</li>
<li><a href="../dependency-convergence.html" title="Dependency Convergence"><span class="none"></span>Dependency Convergence</a></li>
<li><a href="../dependency-management.html" title="Dependency Management"><span class="none"></span>Dependency Management</a></li>
<li><a href="../team-list.html" title="Project Team"><span class="none"></span>Project Team</a></li>
<li><a href="../mail-lists.html" title="Mailing Lists"><span class="none"></span>Mailing Lists</a></li>
<li><a href="../issue-tracking.html" title="Issue Tracking"><span class="none"></span>Issue Tracking</a></li>
<li><a href="../license.html" title="Project License"><span class="none"></span>Project License</a></li>
<li><a href="../source-repository.html" title="Source Repository"><span class="none"></span>Source Repository</a></li>
<li><a href="../project-summary.html" title="Project Summary"><span class="none"></span>Project Summary</a></li>
<li class="nav-header"><img class="imageLink" src="../img/glyphicons/layers.png" alt="Project Reports" border="0"/> Project Reports</li>
<li><a href="../changes-report.html" title="Changes Report"><span class="none"></span>Changes Report</a></li>
<li><a href="../jira-report.html" title="JIRA Report"><span class="none"></span>JIRA Report</a></li>
<li><a href="../rat-report.html" title="RAT Report"><span class="none"></span>RAT Report</a></li>
</ul>
</nav>
<div class="well sidebar-nav">
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="../images/logos/maven-feather.png" /></a>
</div>
</div>
</header>
<main id="bodyColumn" class="span10" >
<section>
<h2><a name="Log4j_2_API"></a>Log4j 2 API</h2>
<section>
<h3><a name="Thread_Context"></a>Thread Context</h3>
<section>
<h4><a name="Introduction"></a>Introduction</h4>
<p>Log4j introduced the concept of the Mapped Diagnostic Context or MDC. It has been documented and
discussed in numerous places including
<a class="externalLink" href="http://veerasundar.com/blog/2009/10/log4j-mdc-mapped-diagnostic-context-what-and-why/">Log4j MDC: What and Why</a> and
<a class="externalLink" href="http://blog.f12.no/wp/2004/12/09/log4j-and-the-mapped-diagnostic-context/">Log4j and the Mapped Diagnostic Context</a>.
In addition, Log4j 1.x provides support for a Nested Diagnostic Context or NDC. It too has been documented
and discussed in various places such as
<a class="externalLink" href="http://lstierneyltd.com/blog/development/log4j-nested-diagnostic-contexts-ndc/">Log4j NDC</a>.
SLF4J/Logback followed with its own implementation of the MDC, which is documented very well at
<a class="externalLink" href="http://logback.qos.ch/manual/mdc.html">Mapped Diagnostic Context</a>.
</p>
<p>Log4j 2 continues with the idea of the MDC and the NDC but merges them into a single Thread Context.
The Thread Context Map is the equivalent of the MDC and the Thread Context Stack is the equivalent of the
NDC. Although these are frequently used for purposes other than diagnosing problems, they are still
frequently referred to as the MDC and NDC in Log4j 2 since they are already well known by those acronyms.
</p>
</section><section>
<h4><a name="Fish_Tagging"></a>Fish Tagging</h4>
<p>Most real-world systems have to deal with multiple clients simultaneously. In a typical multithreaded
implementation of such a system, different threads will handle different clients. Logging is
especially well suited to trace and debug complex distributed applications. A common approach to
differentiate the logging output of one client from another is to instantiate a new separate logger for
each client. This promotes the proliferation of loggers and increases the management overhead of logging.
</p>
<p>A lighter technique is to uniquely stamp each log request initiated from the same client interaction.
Neil Harrison described this method in the book &quot;Patterns for Logging Diagnostic Messages,&quot; in <i>Pattern
Languages of Program Design 3</i>, edited by R. Martin, D. Riehle, and F. Buschmann
(Addison-Wesley, 1997). Just as a fish can be tagged and have its movement tracked, stamping log
events with a common tag or set of data elements allows the complete flow of a transaction or a request
to be tracked. We call this <i>Fish Tagging</i>.
</p>
<p>Log4j provides two mechanisms for performing Fish Tagging; the Thread Context Map and the Thread
Context Stack. The Thread Context Map allows any number of items to be added and be identified
using key/value pairs. The Thread Context Stack allows one or more items to be pushed on the
Stack and then be identified by their order in the Stack or by the data itself. Since key/value
pairs are more flexible, the Thread Context Map is recommended when data items may be added during
the processing of the request or when there are more than one or two items.
</p>
<p>To uniquely stamp each request using the Thread Context Stack, the user pushes contextual information
on to the Stack.
</p>
<div>
<pre class="prettyprint linenums">
ThreadContext.push(UUID.randomUUID().toString()); // Add the fishtag;
logger.debug(&quot;Message 1&quot;);
.
.
.
logger.debug(&quot;Message 2&quot;);
.
.
ThreadContext.pop();</pre></div>
<p>
The alternative to the Thread Context Stack is the Thread Context Map. In this case, attributes
associated with the request being processed are adding at the beginning and removed at the end
as follows:
</p>
<div>
<pre class="prettyprint linenums">
ThreadContext.put(&quot;id&quot;, UUID.randomUUID().toString()); // Add the fishtag;
ThreadContext.put(&quot;ipAddress&quot;, request.getRemoteAddr());
ThreadContext.put(&quot;loginId&quot;, session.getAttribute(&quot;loginId&quot;));
ThreadContext.put(&quot;hostName&quot;, request.getServerName());
.
logger.debug(&quot;Message 1&quot;);
.
.
logger.debug(&quot;Message 2&quot;);
.
.
ThreadContext.clear();</pre></div>
</section><section>
<h4><a name="CloseableThreadContext"></a>CloseableThreadContext</h4>
<p>When placing items on the stack or map, it's necessary to remove then again when appropriate. To assist with
this, the CloseableThreadContext implements the <a class="externalLink" href="http://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html">AutoCloseable
interface</a>. This allows items to be pushed to the stack or put in the map, and removed when the close() method is called -
or automatically as part of a try-with-resources. For example, to temporarily push something on to the stack and then remove it:
</p>
<div>
<pre class="prettyprint linenums">
// Add to the ThreadContext stack for this try block only;
try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.push(UUID.randomUUID().toString())) {
logger.debug(&quot;Message 1&quot;);
.
.
logger.debug(&quot;Message 2&quot;);
.
.
}</pre></div>
<p>
Or, to temporarily put something in the map:
</p>
<div>
<pre class="prettyprint linenums">
// Add to the ThreadContext map for this try block only;
try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.put(&quot;id&quot;, UUID.randomUUID().toString())
.put(&quot;loginId&quot;, session.getAttribute(&quot;loginId&quot;))) {
logger.debug(&quot;Message 1&quot;);
.
.
logger.debug(&quot;Message 2&quot;);
.
.
}</pre></div>
If you're using a thread pool, then you can initialise a CloseableThreadContext by using the
putAll(final Map&lt;String, String&gt; values) and/or
pushAll(List&lt;String&gt; messages) methods;
<div>
<pre class="prettyprint linenums">
for( final Session session : sessions ) {
try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.put(&quot;loginId&quot;, session.getAttribute(&quot;loginId&quot;))) {
logger.debug(&quot;Starting background thread for user&quot;);
final Map&lt;String, String&gt; values = ThreadContext.getImmutableContext();
final List&lt;String&gt; messages = ThreadContext.getImmutableStack().asList();
executor.submit(new Runnable() {
public void run() {
try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.putAll(values).pushAll(messages)) {
logger.debug(&quot;Processing for user started&quot;);
.
logger.debug(&quot;Processing for user completed&quot;);
}
});
}
}</pre></div>
</section><section>
<h4><a name="Implementation_details"></a>Implementation details</h4>
<p>The Stack and the Map are managed per thread and are based on
<a class="externalLink" href="http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html">ThreadLocal</a>
by default. The Map can be configured to use an
<a class="externalLink" href="http://docs.oracle.com/javase/6/docs/api/java/lang/InheritableThreadLocal.html">InheritableThreadLocal</a>
(see the <a href="#Configuration">Configuration</a> section).
When configured this way, the contents of the Map will be passed to child threads. However, as
discussed in the
<a class="externalLink" href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#privilegedThreadFactory()">Executors</a>
class and in other cases where thread pooling is utilized, the ThreadContext may not always be
automatically passed to worker threads. In those cases the pooling mechanism should provide a means for
doing so. The getContext() and cloneStack() methods can be used to obtain copies of the Map and Stack
respectively.
</p>
<p>
Note that all methods of the
<a href="../log4j-api/apidocs/org/apache/logging/log4j/ThreadContext.html">ThreadContext</a>
class are static.
</p>
<a name="Configuration"></a>
</section><section>
<h4><a name="Configuration"></a>Configuration</h4>
<ul>
<li>Set the system property `disableThreadContextMap` to `true` to disable the Thread Context Map.</li>
<li>Set the system property `disableThreadContextStack` to `true` to disable the Thread Context Stack.</li>
<li>Set the system property `disableThreadContext` to `true` to disable both the Thread Context Map and Stack.</li>
<li>Set the system property `log4j2.isThreadContextMapInheritable` to `true` to enable child threads to inherit the Thread
Context Map.</li>
</ul>
</section><section>
<h4><a name="Including_the_ThreadContext_when_writing_logs"></a>Including the ThreadContext when writing logs</h4>
<p>
The <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/layout/PatternLayout.html">PatternLayout</a>
provides mechanisms to print the contents of the
<a href="../log4j-api/apidocs/org/apache/logging/log4j/ThreadContext.html">ThreadContext</a>
Map and Stack.
</p>
<ul>
<li>
Use %X by itself to include the full contents of the Map.
</li>
<li>
Use %X{key} to include the specified key.
</li>
<li>
Use %x to include the full contents of the <a class="externalLink" href="http://docs.oracle.com/javase/6/docs/api/java/util/Stack.html">Stack</a>.
</li>
</ul>
</section><section>
<h4><a name="Custom_context_data_injectors_for_non_thread-local_context_data"></a>Custom context data injectors for non thread-local context data</h4>
<p>
With the ThreadContext logging statements can be tagged so log entries that were related in some way
can be linked via these tags. The limitation is that this only works for logging done on the same application thread
(or child threads when configured).
</p>
<p>
Some applications have a thread model that delegates work to other threads, and
in such models, tagging attributes that are put into a thread-local map in one thread are not visible
in the other threads and logging done in the other threads will not show these attributes.
</p>
<p>
Log4j 2.7 adds a flexible mechanism to tag logging statements with context data coming from
other sources than the ThreadContext.
See the manual page on <a href="extending.html#Custom_ContextDataInjector">extending Log4j</a> for details.
</p>
</section></section>
</section>
</main>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p align="center">Copyright &copy; 1999-2020 <a class="external" href="http://www.apache.org">The Apache Software Foundation</a>. All Rights Reserved.<br>
Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, and the Apache Logging project logo are trademarks of The Apache Software Foundation.</p>
</div>
</div>
</footer>
</body>
</html>