blob: bec2e787fa618cf07b7b1f994dae9163419fb6c7 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Migrating from Logback :: Apache Log4j</title>
<link rel="canonical" href="https://logging.apache.org/log4j/2.x/migrate-from-logback.html">
<meta name="generator" content="Antora 3.2.0-alpha.8">
<link rel="stylesheet" href="./_/css/site.css">
<link rel="icon" href="./_/../_images/favicon.ico" type="image/x-icon">
<!-- `@asciidoctor/tabs` extension styles -->
<link rel="stylesheet" href="./_/css/vendor/tabs.css">
<style>
/* Swap colors of `IMPORTANT` and `WARNING` blocks */
.doc .admonitionblock.important .icon { background-color: #f70; }
.doc .admonitionblock.warning .icon { background-color: #e40046; }
/* Default `h4`, `h5`, and `h6` are smaller than the normal text, fix header font sizing: */
.doc h1 { font-size: 1.9rem; }
.doc h2 { font-size: 1.7rem; }
.doc h3 { font-size: 1.5rem; font-weight: 400; }
.doc h4 { font-size: 1.3rem; font-weight: 500; }
.doc h5 { font-size: 1.1rem; font-weight: 500; text-decoration: underline; }
.doc h6 { font-size: 0.9rem; font-weight: 500; text-decoration: underline; }
/* Default `code`, `pre`, and `.colist` (source code annotations) fonts are too big, adjust them: */
.doc .colist>table code, .doc p code, .doc thead code { font-size: 0.8em; }
.doc pre { font-size: 0.7rem; }
.doc .colist { font-size: 0.75rem; }
/* Make links more visible: */
.doc a { text-decoration: underline; }
.doc a code { text-decoration: underline; color: #1565c0; }
/* Tab header fonts aren't rendered good, adjusting the font weight: */
.tablist > ul li { font-weight: 500; }
/* `page-toclevels` greater than 4 are not supported by Antora UI, patching it: */
.toc .toc-menu li[data-level="4"] a {
padding-left: 2.75rem;
}
/* Replace the default highlight.js color for strings from red (unnecessarily signaling something negative) to green: */
.hljs-string {
color: #0f8532;
}
</style>
</head>
<body class="article">
<header class="header">
<nav class="navbar">
<div class="navbar-brand">
<div class="navbar-item">
<img src="./_/../_images/logo-small-white.png" alt="Apache Log4j"/>
</div>
</div>
<div id="topbar-nav" class="navbar-menu">
<div class="navbar-end">
<a class="navbar-item" href="https://logging.apache.org">a subproject of&nbsp;<strong>Apache Logging Services</strong></a>
</div>
</div>
</nav>
</header>
<div class="body">
<div class="nav-container" data-component="ROOT" data-version="">
<aside class="nav">
<div class="panels">
<div class="nav-panel-menu is-active" data-panel="menu">
<nav class="nav-menu">
<button class="nav-menu-toggle" aria-label="Toggle expand/collapse all" style="display: none"></button>
<h3 class="title"><a href="index.html">Home</a></h3>
<ul class="nav-list">
<li class="nav-item" data-depth="0">
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="download.html">Download</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="release-notes.html">Release notes</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="https://logging.apache.org/support.html">Support</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="https://logging.apache.org/security.html">Security</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="0">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/index.html">Manual</a>
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="manual/getting-started.html">Getting started</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="manual/installation.html">Installation</a>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/api.html">API</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/api.html#loggers">Loggers</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/eventlogging.html">Event Logger</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/simple-logger.html">Simple Logger</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/status-logger.html">Status Logger</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="manual/logbuilder.html">Fluent API</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/api.html#fish-tagging">Fish tagging</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/customloglevels.html">Levels</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/markers.html">Markers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/thread-context.html">Thread Context</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="manual/messages.html">Messages</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="manual/flowtracing.html">Flow Tracing</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/implementation.html">Implementation</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="manual/architecture.html">Architecture</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/config-intro.html">Configuration</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/configuration.html">Configuration file</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/systemproperties.html">Configuration properties</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/customconfig.html">Programmatic configuration</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/appenders.html">Appenders</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/appenders/file.html">File appenders</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/appenders/rolling-file.html">Rolling file appenders</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/appenders/database.html">Database appenders</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/appenders/network.html">Network Appenders</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/appenders/message-queue.html">Message queue appenders</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/appenders/delegating.html">Delegating Appenders</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/layouts.html">Layouts</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/json-template-layout.html">JSON Template Layout</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="manual/pattern-layout.html">Pattern Layout</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/lookups.html">Lookups</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/filters.html">Filters</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/scripts.html">Scripts</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/jmx.html">JMX</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/extending.html">Extending</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/plugins.html">Plugins</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="manual/performance.html">Performance</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/async.html">Asynchronous loggers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="manual/garbagefree.html">Garbage-free logging</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="0">
<button class="nav-item-toggle"></button>
<span class="nav-text">References</span>
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="plugin-reference.html">Plugin reference</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="javadoc.html">Java API reference</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="0">
<button class="nav-item-toggle"></button>
<span class="nav-text">Resources</span>
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="faq.html">F.A.Q.</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="migrate-from-log4j1.html">Migrating from Log4j 1</a>
</li>
<li class="nav-item is-current-page" data-depth="1">
<a class="nav-link" href="migrate-from-logback.html">Migrating from Logback</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="migrate-from-slf4j.html">Migrating from SLF4J</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="graalvm.html">Building GraalVM native images</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="hibernate.html">Integrating with Hibernate</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="jakarta.html">Integrating with Jakarta EE</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="soa.html">Integrating with service-oriented architectures</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="development.html">Development</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="0">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="components.html">Components</a>
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="log4j-iostreams.html">Log4j IOStreams</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="log4j-spring-boot.html">Log4j Spring Boot Support</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="log4j-spring-cloud-config-client.html">Log4j Spring Cloud Configuration</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="log4j-jul.html">JUL-to-Log4j bridge</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="log4j-to-jul.html">Log4j-to-JUL bridge</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="0">
<button class="nav-item-toggle"></button>
<span class="nav-text">Related projects</span>
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="https://logging.apache.org/log4j/jakarta/index.html">Log4j Jakarta EE</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="https://logging.apache.org/log4j/jmx-gui/index.html">Log4j JMX GUI</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="https://logging.apache.org/log4j/kotlin/index.html">Log4j Kotlin</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="https://logging.apache.org/log4j/scala/index.html">Log4j Scala</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="https://logging.apache.org/log4j/tools/index.html">Log4j Tools</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="https://logging.apache.org/log4j/transform/index.html">Log4j Transformation Tools</a>
</li>
</ul>
</li>
</ul>
</nav>
</div>
</div>
</aside>
</div>
<main class="article">
<div class="toolbar" role="navigation">
<button class="nav-toggle"></button>
<a href="index.html" class="home-link"></a>
<nav class="breadcrumbs" aria-label="breadcrumbs">
<ul>
<li><a href="index.html">Home</a></li>
<li>Resources</li>
<li><a href="migrate-from-logback.html">Migrating from Logback</a></li>
</ul>
</nav>
<div class="edit-this-page"><a href="https://github.com/apache/logging-log4j2/edit/2.x/src/site/antora/modules/ROOT/pages/migrate-from-logback.adoc">Edit this Page</a></div>
</div>
<div class="content">
<aside class="toc sidebar" data-title="Contents" data-levels="4">
<div class="toc-menu"></div>
</aside>
<article class="doc">
<h1 class="page">Migrating from Logback</h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><a href="https://logback.qos.ch">Logback</a> is a logging implementation for the <a href="https://www.slf4j.org">SLF4J</a> logging API, just like Log4j Core is a logging implementation for the <a href="manual/api.html" class="xref page">Log4j API</a>.
In this page we will guide you through migrating from Logback to Log4j Core as your logging implementation.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Instead of migrating your logging implementation, Logback, are you looking for migrating your logging API, SLF4J?
Please refer to <a href="migrate-from-slf4j.html" class="xref page">Migrating from SLF4J</a>.</p>
</div>
</td>
</tr>
</table>
</div>
<details>
<summary class="title">Struggling with the logging API, implementation, and bridge concepts? Click for an introduction.</summary>
<div class="content">
<div id="logging-api" class="dlist">
<dl>
<dt class="hdlist1">Logging API</dt>
<dd>
<p>A logging API is an interface your code or your dependencies directly logs against.
It is required at compile-time.
It is implementation agnostic to ensure that your application can write logs, but is not tied to a specific logging implementation.
Log4j API, <a href="https://www.slf4j.org">SLF4J</a>, <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html">JUL (Java Logging)</a>, <a href="https://commons.apache.org/proper/commons-logging/">JCL (Apache Commons Logging)</a>, <a href="https://openjdk.org/jeps/264">JPL (Java Platform Logging)</a> and <a href="https://github.com/jboss-logging/jboss-logging">JBoss Logging</a> are major logging APIs.</p>
</dd>
</dl>
</div>
<div id="logging-impl" class="dlist">
<dl>
<dt class="hdlist1">Logging implementation</dt>
<dd>
<p>A logging implementation is only required at runtime and can be changed without the need to recompile your software.
Log4j Core, <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html">JUL (Java Logging)</a>, <a href="https://logback.qos.ch">Logback</a> are the most well-known logging implementations.</p>
</dd>
</dl>
</div>
<div id="logging-bridge" class="dlist">
<dl>
<dt class="hdlist1">Logging bridge</dt>
<dd>
<p>Logging implementations accept input from a single logging API of their preference; Log4j Core from Log4j API, Logback from SLF4J, etc.
A logging bridge is a simple logging implementation of a logging API that forwards all messages to a foreign logging API.
Logging bridges allow a logging implementation to accept input from other logging APIs that are not their primary logging API.
For instance, <code>log4j-slf4j2-impl</code> <em>bridges</em> SLF4J calls to Log4 API and effectively enables Log4j Core to accept input from SLF4J.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>To make things a little bit more tangible, consider the following visualization of a typical Log4j Core installation with bridges for an application:</p>
</div>
<div class="imageblock kroki">
<div class="content">
<img src="_images/diag-a51b68065f249459078382aa4c61888857f01b2c.svg" alt="Visualization of a typical Log4j Core installation with SLF4J, JUL, and JPL bridges">
</div>
<div class="title">Figure 1. Visualization of a typical Log4j Core installation with SLF4J, JUL, and JPL bridges</div>
</div>
</div>
</details>
</div>
</div>
<div class="sect1">
<h2 id="migrating"><a class="anchor" href="#migrating"></a>Migrating</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You either have an application using Logback at runtime, or have a library using Logback for tests.
In either case, you can replace Logback with Log4j Core as follows:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Remove <code>ch.qos.logback:logback-classic</code> dependency</p>
</li>
<li>
<p>Remove <code>logback.xml</code> and <code>logback-test.xml</code> files</p>
</li>
<li>
<p>Follow the instructions shared in the <em>"Getting started"</em> page</p>
<div class="ulist">
<ul>
<li>
<p><a href="manual/getting-started.html#install-app" class="xref page">for applications</a></p>
</li>
<li>
<p><a href="manual/getting-started.html#install-lib" class="xref page">for libraries</a></p>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>Next you need to re-organize your logging API bridges such that all foreign APIs are bridged to Log4j API, the logging API implemented by Log4j Core.
This is explained in the next section.</p>
</div>
<div class="sect2">
<h3 id="bridges"><a class="anchor" href="#bridges"></a>Bridges</h3>
<div class="paragraph">
<p>It is highly likely that you were bridging all logging APIs (including Log4j API!) to SLF4J, the logging API implemented by Logback.
There are two particular approaches you can take here to ensure all logging APIs are instead bridged to Log4j API, the logging API implemented by Log4j Core:</p>
</div>
<div class="sect3">
<h4 id="bridge-to-log4j"><a class="anchor" href="#bridge-to-log4j"></a>Bridge all logging APIs to Log4j API</h4>
<div class="paragraph">
<p>We strongly advise you to bridge all foreign logging APIs <strong>directly</strong> to Log4j API.
You can use the cheat sheet shared below to implement that.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. Dependency migration cheat sheet</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">If dependency present</th>
<th class="tableblock halign-left valign-top">replace with</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.apache.logging.log4j:log4j-to-slf4j</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.apache.logging.log4j:log4j-slf4j2-impl</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.slf4j:jcl-over-slf4j</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>commons-logging:commons-logging</code> version <code>&gt;=1.3.0</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.slf4j:jul-to-slf4j</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.apache.logging.log4j:log4j-jul</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.slf4j:log4j-over-slf4j</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.apache.logging.log4j:log4j-1.2-api</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.springframework:spring-boot-starter-logging</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>org.springframework:spring-boot-starter-log4j2</code></p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="bridge-to-sfl4j"><a class="anchor" href="#bridge-to-sfl4j"></a>Bridge all logging APIs to SLF4J, and bridge SLF4J to Log4j API</h4>
<div class="paragraph">
<p>You can implement this by replacing <code>org.apache.logging.log4j:log4j-to-slf4j</code> dependency with <code>org.apache.logging.log4j:log4j-slf4j2-impl</code>.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p><strong>This approach is not recommended!</strong>
It incurs certain drawbacks since some logging API calls will need to cross multiple bridges.
For instance, a call to JUL will first be bridged to SLF4J, and then from there to Log4j API.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="config"><a class="anchor" href="#config"></a>Configuration</h3>
<div class="paragraph">
<p>It might not always be trivial to match the contents of the newly created <code>log4j2.xml</code> and <code>log4j2-test.xml</code> files with your old <code>logback.xml</code> and <code>logback-test.xml</code> files.
While all Logback components have corresponding equivalents in Log4j Core, they might not be sharing the same name or configuration.
To assist with migrating Logback configuration components to Log4j Core, see the following pages:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="manual/appenders.html" class="xref page">Appenders</a></p>
</li>
<li>
<p><a href="manual/layouts.html" class="xref page">Layouts</a></p>
</li>
<li>
<p><a href="manual/filters.html" class="xref page">Filters</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For the complete list of all Log4j configuration knobs, see <a href="manual/configuration.html" class="xref page">the Configuration page</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="parameterized-logging"><a class="anchor" href="#parameterized-logging"></a>Parameterized logging</h3>
<div class="paragraph">
<p>A common mistake in parameterized logging is to add a <code>{}</code> placeholder for the exception associated with a log event:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">} catch (Exception exception) {
logger.error("The foo process exited with an error: {}", exception);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Log4j Core and Logback differ in the way they treat this statement:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Logback</dt>
<dd>
<p>Logback interprets the <code>exception</code> argument as throwable and removes it from the list of parameters.
We end up with a parameterized statement with one placeholder, but zero parameters.
The placeholder therefore remains as is:</p>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-none hljs">The foo process exited with and error: {}
java.lang.RuntimeException: Message
at example.MigrateFromLogback.doLogWrong(MigrateFromLogback.java:10)
...</code></pre>
</div>
</div>
</dd>
<dt class="hdlist1">Log4j Core</dt>
<dd>
<p>Log4j Core first looks for the parameters of the message.
Since the format string has one placeholder, the <code>exception</code> argument is interpreted as a parameter of the log message.
The throwable associated to the log event is <code>null</code>, which results in a missing stack trace:</p>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-none hljs">The foo process exited with and error: java.lang.RuntimeException: Message</code></pre>
</div>
</div>
</dd>
</dl>
</div>
<div class="paragraph">
<p>To fix this problem and get the same output in both backends, you should remove the placeholder from the format string:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">} catch (Exception exception) {
logger.error("The foo process exited with an error.", exception);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>After the change, the output will look us:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-none hljs">The foo process exited with and error.
java.lang.RuntimeException: Message
at example.MigrateFromLogback.doLogWrong(MigrateFromLogback.java:10)
...</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>As a temporary solution, the SLF4J-to-Log4j API bridges contain a special
<a href="manual/api.html#logger-message-factories" class="xref page"><code>MessageFactory</code></a>
that classifies trailing <code>Throwable</code> arguments in the same way Logback does.
To use it, you need to set the <a href="manual/systemproperties.html#log4j2.messageFactory" class="xref page"><code>log4j2.messageFactory</code></a> configuration property to <code>org.apache.logging.slf4j.message.ThrowableConsumingMessageFactory</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</article>
</div>
</main>
</div>
<footer class="footer">
<p>
Copyright © 1999-2025 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
Licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache Software License, Version 2.0</a>.
Please read our <a href="https://privacy.apache.org/policies/privacy-policy-public.html">privacy policy</a>.
</p>
<p>
Apache, Log4j, and the Apache feather logo are trademarks or registered trademarks of The Apache Software Foundation.
Oracle and Java are registered trademarks of Oracle and/or its affiliates.
Other names may be trademarks of their respective owners.
</p>
</footer>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
_paq.push(["disableCookies"]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '42']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<noscript><p><img src="https://analytics.apache.org/matomo.php?idsite=42&amp;rec=1" style="border:0;" alt="" /></p></noscript>
<!-- End Matomo Code -->
<script id="site-script" src="./_/js/site.js" data-ui-root-path="./_"></script>
<script async src="./_/js/vendor/highlight.js"></script>
<!-- `@asciidoctor/tabs` extension scripts -->
<script async src="./_/js/vendor/tabs.js"></script>
</body>
</html>