Skip to content

Commit f7a6320

Browse files
committed
Add documentation for ThrowableConsumingMessageFactory
1 parent f2fa3cc commit f7a6320

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package example;
2+
3+
import org.apache.logging.log4j.LogManager;
4+
import org.apache.logging.log4j.Logger;
5+
6+
class MigrateFromLogback {
7+
private static Logger logger = LogManager.getLogger();
8+
9+
doLogWrong() {
10+
try {
11+
// do something
12+
// tag::wrong[]
13+
} catch (Exception e) {
14+
logger.error("The foo process exited with an error: {}", e);
15+
}
16+
// end::wrong[]
17+
}
18+
19+
doLogRight() {
20+
try {
21+
// do something
22+
// tag::right[]
23+
} catch (Exception e) {
24+
logger.error("The foo process exited with an error.", e);
25+
}
26+
// end::right[]
27+
}
28+
}

src/site/antora/modules/ROOT/pages/migrate-from-logback.adoc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,62 @@ To assist with migrating Logback configuration components to Log4j Core, see the
106106
* xref:manual/filters.adoc[]
107107
108108
For the complete list of all Log4j configuration knobs, see xref:manual/configuration.adoc[the Configuration page].
109+
110+
[#parameterized-logging]
111+
=== Parameterized logging
112+
113+
A common mistake in parameterized logging is to add a `{}` placeholder for the exception associated with a log event:
114+
115+
[source,java,indent=0]
116+
----
117+
include::example$migrate-from-logback/MigrateFromLogback.java[tag=wrong]
118+
----
119+
120+
Log4j Core and Logback differ in the way they treat this statement:
121+
122+
Logback::
123+
Logback interprets the `e` argument as throwable and removes it from the list of parameters.
124+
We end up with a parameterized statement with one placeholder, but zero parameters.
125+
The placeholder therefore remains as is:
126+
+
127+
[source]
128+
----
129+
The foo process exited with and error: {}
130+
java.lang.RuntimeException: Message
131+
at example.MigrateFromLogback.doLogWrong(MigrateFromLogback.java:10)
132+
...
133+
----
134+
135+
Log4j Core::
136+
Log4j Core first looks for the parameters of the message.
137+
Since the format string has one placeholder, the `e` argument is interpreted as a parameter of the log message.
138+
The throwable associated to the log event is `null`, which results in a missing stack trace:
139+
+
140+
[source]
141+
----
142+
The foo process exited with and error: java.lang.RuntimeException: Message
143+
----
144+
145+
To fix this problem and obtain the same output in both backends, you should remove the placeholder from the format string:
146+
147+
[source,java,indent=0]
148+
----
149+
include::example$migrate-from-logback/MigrateFromLogback.java[tag=right]
150+
----
151+
152+
After the change, the output will look us:
153+
154+
[source]
155+
----
156+
The foo process exited with and error.
157+
java.lang.RuntimeException: Message
158+
at example.MigrateFromLogback.doLogWrong(MigrateFromLogback.java:10)
159+
...
160+
----
161+
162+
[TIP]
163+
====
164+
As a temporary solution, the SLF4J-to-Log4j API bridges contain a special
165+
xref:manual/api.adoc#logger-message-factories[`MessageFactory`]
166+
that classifies trailing `Throwable` arguments in the same way Logback does.
167+
To use it, you need to set the xref:manual/systemproperties.adoc#log4j2.messageFactory[`log4j2.messageFactory`] configuration property to `org.apache.logging.slf4j.message.ThrowableConsumingMessageFactory`.

0 commit comments

Comments
 (0)