@@ -106,3 +106,62 @@ To assist with migrating Logback configuration components to Log4j Core, see the
106106* xref:manual/filters.adoc[]
107107
108108For 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