| //// |
| 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. |
| //// |
| |
| = Migrating from Logback |
| |
| {logback-url}[Logback] is a logging implementation for the {slf4j-url}[SLF4J] logging API, just like Log4j Core is a logging implementation for the xref:manual/api.adoc[Log4j API]. |
| In this page we will guide you through migrating from Logback to Log4j Core as your logging implementation. |
| |
| [TIP] |
| ==== |
| Instead of migrating your logging implementation, Logback, are you looking for migrating your logging API, SLF4J? |
| Please refer to xref:migrate-from-slf4j.adoc[]. |
| ==== |
| |
| .Struggling with the logging API, implementation, and bridge concepts? Click for an introduction. |
| [%collapsible] |
| ==== |
| include::partial$concepts.adoc[tag=!software-type] |
| ==== |
| |
| [#migrating] |
| == Migrating |
| |
| 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: |
| |
| . Remove `ch.qos.logback:logback-classic` dependency |
| |
| . Remove `logback.xml` and `logback-test.xml` files |
| |
| . Follow the instructions shared in the _"Getting started"_ page |
| ** xref:manual/getting-started.adoc#install-app[for applications] |
| ** xref:manual/getting-started.adoc#install-lib[for libraries] |
| |
| 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. |
| |
| [#bridges] |
| === Bridges |
| |
| 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: |
| |
| [#bridge-to-log4j] |
| ==== Bridge all logging APIs to Log4j API |
| |
| We strongly advise you to bridge all foreign logging APIs *directly* to Log4j API. |
| You can use the cheat sheet shared below to implement that. |
| |
| .Dependency migration cheat sheet |
| [cols="1,1"] |
| |=== |
| | If dependency present | replace with |
| |
| | `org.apache.logging.log4j:log4j-to-slf4j` |
| | `org.apache.logging.log4j:log4j-slf4j2-impl` |
| |
| | `org.slf4j:jcl-over-slf4j` |
| | `commons-logging:commons-logging` version `>=1.3.0` |
| |
| | `org.slf4j:jul-to-slf4j` |
| | `org.apache.logging.log4j:log4j-jul` |
| |
| | `org.slf4j:log4j-over-slf4j` |
| | `org.apache.logging.log4j:log4j-1.2-api` |
| |
| | `org.springframework:spring-boot-starter-logging` |
| | `org.springframework:spring-boot-starter-log4j2` |
| |=== |
| |
| [#bridge-to-sfl4j] |
| ==== Bridge all logging APIs to SLF4J, and bridge SLF4J to Log4j API |
| |
| You can implement this by replacing `org.apache.logging.log4j:log4j-to-slf4j` dependency with `org.apache.logging.log4j:log4j-slf4j2-impl`. |
| |
| [WARNING] |
| ==== |
| *This approach is not recommended!* |
| 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. |
| ==== |
| |
| [#config] |
| === Configuration |
| |
| It might not always be trivial to match the contents of the newly created `log4j2.xml` and `log4j2-test.xml` files with your old `logback.xml` and `logback-test.xml` 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: |
| |
| * xref:manual/appenders.adoc[] |
| * xref:manual/layouts.adoc[] |
| * xref:manual/filters.adoc[] |
| |
| For the complete list of all Log4j configuration knobs, see xref:manual/configuration.adoc[the Configuration page]. |
| |
| [#parameterized-logging] |
| === Parameterized logging |
| |
| A common mistake in parameterized logging is to add a `{}` placeholder for the exception associated with a log event: |
| |
| [source,java,indent=0] |
| ---- |
| include::example$migrate-from-logback/MigrateFromLogback.java[tag=wrong] |
| ---- |
| |
| Log4j Core and Logback differ in the way they treat this statement: |
| |
| Logback:: |
| Logback interprets the `exception` 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: |
| + |
| [source] |
| ---- |
| The foo process exited with and error: {} |
| java.lang.RuntimeException: Message |
| at example.MigrateFromLogback.doLogWrong(MigrateFromLogback.java:10) |
| ... |
| ---- |
| |
| Log4j Core:: |
| Log4j Core first looks for the parameters of the message. |
| Since the format string has one placeholder, the `exception` argument is interpreted as a parameter of the log message. |
| The throwable associated to the log event is `null`, which results in a missing stack trace: |
| + |
| [source] |
| ---- |
| The foo process exited with and error: java.lang.RuntimeException: Message |
| ---- |
| |
| To fix this problem and get the same output in both backends, you should remove the placeholder from the format string: |
| |
| [source,java,indent=0] |
| ---- |
| include::example$migrate-from-logback/MigrateFromLogback.java[tag=right] |
| ---- |
| |
| After the change, the output will look us: |
| |
| [source] |
| ---- |
| The foo process exited with and error. |
| java.lang.RuntimeException: Message |
| at example.MigrateFromLogback.doLogWrong(MigrateFromLogback.java:10) |
| ... |
| ---- |
| |
| [TIP] |
| ==== |
| As a temporary solution, the SLF4J-to-Log4j API bridges contain a special |
| xref:manual/api.adoc#logger-message-factories[`MessageFactory`] |
| that classifies trailing `Throwable` arguments in the same way Logback does. |
| 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`. |
| ==== |