You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by pk...@apache.org on 2024/06/07 12:56:21 UTC
(logging-log4j2) branch doc/2.x/migration created (now 7c9c874cee)
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a change to branch doc/2.x/migration
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
at 7c9c874cee Improve "Migration from Log4j 1" page
This branch includes the following new commits:
new 7c9c874cee Improve "Migration from Log4j 1" page
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(logging-log4j2) 01/01: Improve "Migration from Log4j 1" page
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch doc/2.x/migration
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 7c9c874ceebbe4f9a4045b3e02ab5560ce2705b4
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Fri Jun 7 14:55:45 2024 +0200
Improve "Migration from Log4j 1" page
---
.../manual/migration/Migration1Example.java | 33 +++
.../manual/migration/Migration2Example.java | 32 +++
.../modules/ROOT/images/whichjar-log4j-1.2-api.png | Bin 24992 -> 0 bytes
.../modules/ROOT/images/whichjar-log4j-api.png | Bin 16515 -> 0 bytes
.../modules/ROOT/pages/manual/migration.adoc | 317 +++++++++++++++++----
5 files changed, 319 insertions(+), 63 deletions(-)
diff --git a/src/site/antora/modules/ROOT/examples/manual/migration/Migration1Example.java b/src/site/antora/modules/ROOT/examples/manual/migration/Migration1Example.java
new file mode 100644
index 0000000000..cc978a740d
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/migration/Migration1Example.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package example;
+
+import org.apache.log4j.Logger;
+
+public class Migration1Example {
+
+ private static final Logger logger = Logger.getLogger(Migration1Example.class);
+
+ public static void main(String[] args) {
+ String username = args.length > 0 ? args[0] : "unknown";
+ // tag::guards[]
+ if (logger.isInfoEnabled()) {
+ logger.info("Hello " + username + "!");
+ }
+ // end::guards[]
+ }
+}
diff --git a/src/site/antora/modules/ROOT/examples/manual/migration/Migration2Example.java b/src/site/antora/modules/ROOT/examples/manual/migration/Migration2Example.java
new file mode 100644
index 0000000000..37873bbebb
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/migration/Migration2Example.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package example;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+public class Migration2Example {
+
+ private static final Logger logger = LogManager.getLogger();
+
+ public static void main(String[] args) {
+ String username = args.length > 0 ? args[0] : "unknown";
+ // tag::guards[]
+ logger.info("Hello {}!", username);
+ // end::guards[]
+ }
+}
diff --git a/src/site/antora/modules/ROOT/images/whichjar-log4j-1.2-api.png b/src/site/antora/modules/ROOT/images/whichjar-log4j-1.2-api.png
deleted file mode 100644
index 8b54810904..0000000000
Binary files a/src/site/antora/modules/ROOT/images/whichjar-log4j-1.2-api.png and /dev/null differ
diff --git a/src/site/antora/modules/ROOT/images/whichjar-log4j-api.png b/src/site/antora/modules/ROOT/images/whichjar-log4j-api.png
deleted file mode 100644
index 194196aad3..0000000000
Binary files a/src/site/antora/modules/ROOT/images/whichjar-log4j-api.png and /dev/null differ
diff --git a/src/site/antora/modules/ROOT/pages/manual/migration.adoc b/src/site/antora/modules/ROOT/pages/manual/migration.adoc
index 82ebbad046..ab00996b70 100644
--- a/src/site/antora/modules/ROOT/pages/manual/migration.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/migration.adoc
@@ -16,25 +16,241 @@ Licensed to the Apache Software Foundation (ASF) under one or more
////
= Migrating from Log4j 1
+:log4j1-url: https://logging.apache.org/log4j/1.x
+
+{log4j1-url}/index.html[Log4j 1]
+has reached **End of Life** in 2015 (see
+https://blogs.apache.org/foundation/entry/apache_logging_services_project_announces[announcement])
+and is no longer supported.
+
+Since Log4j 2 has been rewritten from scratch, it introduces many breaking changes to its predecessor.
+Most notably:
+
+* It uses a new package namespace (`org.apache.logging.log4j`), whereas Log4j 1 used the `org.apache.log4j` namespace,
+
+* It features a
+xref:manual/api.adoc[logging API]
+which is independent of its reference implementation,
+
+* It uses a new more flexible
+xref:manual/configuration.adoc[configuration file format],
+which is **incompatible** with the format used by Log4j 1.
+
+[#prepare-to-migrate]
+== Prepare to migrate
+
+.Are you a library developer?
+[TIP]
+====
+If you are developing a library, which functionality is not related to logging, you only need to rewrite the library to use Log4j 2 API.
+Skip directly to <<api-migration>>.
+====
+
+In order to migrate your application to Log4j 2 you need to assess first how your application **and** its dependencies use Log4j 1.
+While Log4j 1 didn't have a formal split between a logging API and a logging backend, for the purpose of this guide, we'll introduce the following split:
+
+[#log4j-1-api-methods]
+Log4j 1 API::
++
+It is the part of the Log4j 1 library that produces log events, and it is the most commonly used.
+The methods that are considered part of the Log4j 1 API are listed below:
++
+.Log4j 1 API methods
+[cols="1m,2"]
+|===
+| Class name | Methods
-http://logging.apache.org/log4j/1.2/[Log4j 1.x] has https://blogs.apache.org/foundation/entry/apache_logging_services_project_announces[reached End of Life] in 2015 and is no longer supported.
+| {log4j1-url}/apidocs/org/apache/log4j/MDC.html[org.apache.log4j.MDC]
+| All methods
-This page explains how to migrate applications or libraries currently using the Log4j 1.x API to use Log4j v2 as their main logging framework.
+| {log4j1-url}/apidocs/org/apache/log4j/NDC.html[org.apache.log4j.NDC]
+| All methods
-[#Log4j12Bridge]
-== Option 1: use the Log4j 1.x bridge (log4j-1.2-api)
+| {log4j1-url}/apidocs/org/apache/log4j/Priority.html[org.apache.log4j.Priority]
+| All methods
+
+| {log4j1-url}/apidocs/org/apache/log4j/Level.html[org.apache.log4j.Level]
+| All methods
+
+| {log4j1-url}/apidocs/org/apache/log4j/Category.html[org.apache.log4j.Category]
+| All methods, except: methods for the
+{log4j1-url}/apidocs/org/apache/log4j/spi/AppenderAttachable.html[AppenderAttachable] interface,`callsAppenders` and `setLevel`.
+
+| {log4j1-url}/apidocs/org/apache/log4j/Logger.html[org.apache.log4j.Logger]
+| Same as `Category`
+
+| {log4j1-url}/apidocs/org/apache/log4j/LogManager.html[org.apache.log4j.LogManager]
+| All methods
+|===
+
+Log4j 1 Backend::
++
+This is the part of the logging library that consumes log events, formats them and writes to their destination.
+It also allows to configure Log4j 1 programmatically.
+It is usually **not used** in code, since the recommended way to configure Log4j 1 is through a configuration file.
+
+[TIP]
+====
+While it is fairly simple to check which classes and methods in the `org.apache.log4j` package are used by your own application, the task is much more complex, when it comes to your application dependencies.
+
+All the libraries that use **Log4j 1 API** must have a compile dependency on either
+https://central.sonatype.com/artifact/log4j/log4j[log4j:log4j]
+or its clone
+https://central.sonatype.com/artifact/ch.qos.reload4j/reload4j[ch.qos.reload4j:reload4j].
+There are however misconfigured libraries that declare those dependencies, even if they don't directly use Log4j 1 **at all**.
+
+To distinguish between libraries that use Log4j 1 and those that don't, you can look for the presence of other logging APIs. If a library **directly** depends on:
+
+* https://central.sonatype.com/artifact/commons-logging/commons-logging[`commons-logging:commons-logging`],
+* https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-api[`org.apache.logging.log4j:log4j-api`],
+* https://central.sonatype.com/artifact/org.slf4j/slf4j-api[`org.slf4j:slf4j-api`],
+* https://central.sonatype.com/artifact/org.jboss.logging/jboss-logging[`jboss-logging`],
+* other logging APIs,
+
+it is fair to assume that it does not use **Log4j 1 API**, even if it has a direct dependency on `log4j:log4j` or `ch.qos.reload4j:reload4j`.
+====
+
+The following sections explain how to migrate from Log4j 1 to Log4j 2, depending on the way Log4j 1 is used in your application:
+
+* if your application or one of its dependencies is coded against Log4j 1 API, see <<api-migration>>,
+* if your application uses Log4j 1 only as logging backend, see <<backend-migration>>.
+
+[#api-migration]
+== Log4j 1 API migration
+
+To migrate an application that uses Log4j 1 API as logging API, the recommended approach is to modify your code.
+See <<api-code-migration>> for details.
+
+In the case one of your libraries uses Log4j 1 API or you can not modify your logging code at the moment, a Log4j 1 to Log4j 2 bridge is available.
+See <<Log4j12Bridge>> for details.
+
+[#api-code-migration]
+=== Migrate code from Log4j 1 API to Log4j 2 API
+
+[TIP]
+====
+You can migrate your code from Log4j 1 to Log4j 2 automatically, by using the
+https://docs.openrewrite.org/recipes/java/logging/log4j/log4j1tolog4j2[Log4j1ToLog4j2] OpenRewrite recipe.
+See
+https://docs.openrewrite.org/recipes/java/logging/log4j/log4j1tolog4j2[OpenRewrite site] for more details.
+====
+
+Except the change in the package name from `org.apache.log4j` to `org.apache.logging.log4j`, most of the class and method names in Log4j 2 API are inherited from Log4j 1 API.
+
+In order to migrate you code, you need to:
+
+* modify the imports and types used by your application, according to the following table:
++
+.Migration of types from Log4j 1 to Log4j 2
+[cols="1m,1m"]
+|===
+| Migrate Log4j 1 type | to Log4j type
+
+| {log4j1-url}/apidocs/org/apache/log4j/MDC.html[org.apache.log4j.MDC]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/ThreadContext.html[org.apache.logging.log4j.ThreadContext]
+
+| {log4j1-url}/apidocs/org/apache/log4j/NDC.html[org.apache.log4j.NDC]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/ThreadContext.html[org.apache.logging.log4j.ThreadContext]
+
+| {log4j1-url}/apidocs/org/apache/log4j/Priority.html[org.apache.log4j.Priority]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/Level.html[org.apache.logging.log4j.Level]
+
+| {log4j1-url}/apidocs/org/apache/log4j/Level.html[org.apache.log4j.Level]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/Level.html[org.apache.logging.log4j.Level]
+
+| {log4j1-url}/apidocs/org/apache/log4j/Category.html[org.apache.log4j.Category]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[org.apache.logging.log4j.Logger]
+
+| {log4j1-url}/apidocs/org/apache/log4j/Logger.html[org.apache.log4j.Logger]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[org.apache.logging.log4j.Logger]
+
+| {log4j1-url}/apidocs/org/apache/log4j/LogManager.html[org.apache.log4j.LogManager]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html[org.apache.logging.log4j.LogManager]
+|===
+
+* Some Log4j 1 methods were renamed or moved to a different class.
+Therefore you need to replace the following methods with their Log4j 2 API equivalents:
++
+.Migration of methods from Log4j 1 to Log4j 2
+[cols="1m,1m"]
+|===
+| Migrate Log4j 1 method | to Log4j method
+
+| {log4j1-url}/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.String)[Logger.getLogger()]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getLogger()[LogManager.getLogger()]
+
+| {log4j1-url}/apidocs/org/apache/log4j/Logger.html#getRootLogger()[Logger.getRootLogger()]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getRootLogger()[LogManager.getRootLogger()]
+
+| {log4j1-url}/apidocs/org/apache/log4j/Category.html#getEffectiveLevel()[Category.getEffectiveLevel()]
+| link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#getLevel()[Logger.getLevel()]
+|===
+
+* Finally, some methods need specific conversion rules to be applied:
++
+.Special Log4j 1 method migration rules
+[cols="1,3"]
+|===
+| Method | Description
+
+| {log4j1-url}/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.String,%20org.apache.log4j.spi.LoggerFactory)[`Logger.getLogger(String, LoggerFactory)`]
+| Remove the `LoggerFactory` parameter and use one of Log4j 2's other extension mechanisms.
-You may be able to convert an application to Log4j 2 _without any code changes_ by replacing the Log4j 1.x jar file with Log4j 2's `log4j-1.2-api.jar`.
+| {log4j1-url}/apidocs/org/apache/log4j/LogManager.html#shutdown()[`LogManager.shutdown()`]
+| Since Log4j 2.6, an equivalent
+link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#shutdown()[`LogManager.shutdown()`]
+can be used.
-The Log4j 1.x bridge is useful when:
+The utility of this method call depends upon the logging backend used with Log4j API.
-* the application itself is (maybe partly) still using the Log4j 1.x API, or if
-* the application depends on a library which depends on the Log 1.x API, or
-* the application needs to support logging configurations in the old Log4j 1.x format.
+The Log4j Core backend automatically adds a JVM shutdown hook on start up to perform any Core cleanups.
+Starting in Log4j 2.1, you can also specify a custom
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/util/ShutdownCallbackRegistry.html[ShutdownCallbackRegistry].
+See
+xref:manual/systemproperties.adoc#log4j2.shutdownCallbackRegistry[log4j2.shutdownCallbackRegistry]
+for more details.
-To use this option, applications need to use the following three jar files: the Log4j 2 API jar (`log4j-api.jar`), the Log4j 2 implementation jar (`log4j-core.jar`) and the Log4j 1.x bridge jar (`log4j-1.2-api.jar`).
+| Non Log4j 1 API methods
+| Methods outside of those listed in <<log4j-1-api-methods>>, such as `Logger.setLevel()` require a different implementation, depending on the logging backend that will be used.
+|===
+
+[NOTE]
+====
+To prevent a performance penalty from string concatenation in disabled log statements, Log4j 1 required the use of `is*Enabled()` guards:
+
+[source,java,indent=0]
+----
+include::example$manual/migration/Migration1Example.java[tag=guards]
+----
+
+Since Log4j 2 API introduces
+xref:manual/api.adoc#best-practice-concat[parameterized logging]
+these guards are no longer necessary and the same statement can be rewritten as:
+
+[source,java,indent=0]
+----
+include::example$manual/migration/Migration2Example.java[tag=guards]
+----
+====
+
+[#api-use-bridge]
+=== Use Log4j 1 to Log4j 2 API bridge
+
+If you can not modify your application's code or one of your dependencies is using
+<<log4j-1-api-methods,Log4j 1 API>>
+as logging API, you can delay the migration process by
+<<log4j-1-2-api-installation,installing the Log4j 1 to Log4j 2 bridge>>.
-image:whichjar-log4j-1.2-api.png[Using log4j 2 via the log4j 1.x API]
+Since forwarding Log4j 1 API calls to Log4j 2 API calls is the basic functionality of the bridge, no further configuration is required from your part.
+
+[#backend-migration]
+== Log4j 1 Backend migration
+
+[#configuration-file-migration]
+== Log4j 1 Configuration file migration
+
+[#log4j-1.2-api]
+== Option 1: use the Log4j 1.x bridge (log4j-1.2-api)
For most applications this is sufficient.
This is a low-effort way to migrate, and may also allow for migration to proceed gradually over time.
@@ -49,13 +265,6 @@ Log4j 2 will then add log4j.properties, log4j-test.properties, log4j.xml and log
. Set the Log4j 1 system property "log4j.configuration" to the location of the log4j 1 configuration file.
The files must have a file extension of either ".properties" or ".xml".
-[#APICompatibility]
-=== API Compatibility
-
-Log4j 2 provides support for the Log4j 1 logging methods by providing alternate implementations of the classes containing those methods.
-These classes may be found in the log4j-1.2-api jar distributed with the project.
-All calls to perform logging will result in the data passed to the logging methods to be forwarded to the Log4j2 API where they can be processed by implementations of the Log4j 2 API.
-
[#ConfigurationCompatibility]
=== Configuration Compatibility
@@ -121,52 +330,8 @@ While the Log4j 1.x bridge supports logging configurations that use the Log4j 1.
The Log4j 2 website contains extensive documentation on the 2.x configuration format.
Examples for migrating logging configurations from the v1 format to the v2 format are below.
-[#Log4j2API]
-== Option 2: convert your application to the Log4j 2 API (log4j-api)
-
-The other migration option involves changing your application code to use the Log4j 2 API.
-For the most part, converting from the Log4j 1.x API to Log4j 2 should be fairly simple.
-Many of the log statements will require no modification.
-However, where necessary the following changes must be made.
-
-image:whichjar-log4j-api.png[Using log4j 2 via the log4j 2.x API]
-
-|===
-| Log4j 1.x | Log4j 2.x
-
-| Package name: `org.apache.log4j`
-| `org.apache.logging.log4j`
-
-| Calls to `org.apache.log4j.Logger.getLogger()`
-| `org.apache.logging.log4j.LogManager.getLogger()`
-
-| Calls to `org.apache.log4j.Logger.getRootLogger()` or `org.apache.log4j.LogManager.getRootLogger()`
-| `org.apache.logging.log4j.LogManager.getRootLogger()`
-
-| Calls to `org.apache.log4j.Logger.getLogger` that accept a `LoggerFactory`
-| Remove the `org.apache.log4j.spi.LoggerFactory` and use one of Log4j 2's other extension mechanisms
-
-| Calls to `org.apache.log4j.Logger.getEffectiveLevel()`
-| `org.apache.logging.log4j.Logger.getLevel()`
-
-| Calls to `org.apache.log4j.LogManager.shutdown()`
-| Not needed in version 2 because the Log4j Core now automatically adds a JVM shutdown hook on start up to perform any Core clean ups.
-Starting in Log4j 2.1, you can specify a custom link:../javadoc/log4j-core/org/apache/logging/log4j/core/util/ShutdownCallbackRegistry.html[ShutdownCallbackRegistry] to override the default JVM shutdown hook strategy.
-Starting in Log4j 2.6, you can use `org.apache.logging.log4j.LogManager.shutdown()` to initiate shutdown manually.
-
-| Calls to `org.apache.log4j.Logger.setLevel()` or similar methods
-| Not supported at API level.
-Equivalent functionality is provided in the Log4j 2 implementation classes, see `org.apache.logging.log4j.core.config.Configurator.setLevel()`, but this may leave the application susceptible to changes in Log4j 2 internals.
-
-| String concatenation like `logger.info("hi " + userName)`
-| Parameterized messages like `logger.info("hi {}", userName)`
-
-| http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html[`org.apache.log4j.MDC`] and http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/NDC.html[`org.apache.log4j.NDC`]
-| xref:manual/thread-context.adoc[Thread Context]
-|===
-
[#Log4j2ConfigurationFormat]
-== Migrating logging configurations to the Log4j 2 format
+== Migrate configurations files from Log4j 1 to Log4j 2
Although the Log4j 2 configuration syntax is different from that of Log4j 1.x, most, if not all, of the same functionality is available.
@@ -446,3 +611,29 @@ This will allow it to shut down properly.
</Loggers>
</Configuration>
----
+
+[#Log4j12Bridge]
+== Log4j 1 to Log4j 2 bridge
+
+In order to help users with the migration process, a Log4j 1 to Log4j 2 bridge is available.
+The bridge can fulfill three separate functions:
+
+* it forwards all <<log4j-1-api-methods,Log4j 1 API>> method calls to the corresponding Log4j 2 API calls,
+* since version 2.17.2 is supports the usage of some components written for Log4j 1 inside Log4j 2 Core,
+* it provides a limited support for programmatic configuration of Log4j 2 Core, using Log4j 1 method calls,
+* it provides a limited support for Log4j 1 configuration file formats.
+
+[#log4j-1-2-api-installation]
+=== Installation
+
+Since the Log4j 1 to Log4j 2 Bridge **replaces** Log4j 1 classes, it is incompatible with the following artifacts:
+
+* https://central.sonatype.com/artifact/log4j/log4j[`log4j:log4j`]
+* https://central.sonatype.com/artifact/ch.qos.reload4j/reload4j[`ch.qos.reload4j:reload4j`],
+* https://central.sonatype.com/artifact/org.slf4j/log4j-over-slf4j[`org.slf4j:log4j-over-slf4j`]
+
+Before installing the bridge, you need to make sure that none of the artifacts above are present in your runtime classpath.
+
+To install the bridge, add the following dependency to your application:
+
+include::partial$manual/dependencies-log4j-1.2-api.adoc[]