vy commented on code in PR #2649: URL: https://github.com/apache/logging-log4j2/pull/2649#discussion_r1633793065
########## src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-log4j-12-api.adoc: ########## @@ -0,0 +1,55 @@ +//// + 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. +//// +[id=log4j1.compatibility] +== `log4j1.compatibility` + +[cols="1h,5"] +|=== +| Env. variable | LOG4J_COMPATIBILITY +| Type | `boolean` +| Default value | `false` +|=== + +If set to `true`, Log4j 2 will scan the classpath to find Log4j 1 configuration files in the following standard locations: + +* `log4j-test.properties`, +* `log4j-test.xml`, +* `log4j.properties`, +* `log4j.xml`. + +[id=log4j.configuration] +== `log4j.configuration` + +[cols="1h,5"] +|=== +| Env. variable +| LOG4J_CONFIGURATION_FILE + +| Type +| +https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/Path.html[Path] +or +https://docs.oracle.com/javase/{java-target-version}/docs/api/java/net/URI.html[URI] + +| Default value +| `null` +|=== + +If not `null`, Log4j will try to retrieve a **Log4j 1** configuration file from the given location. Review Comment: Increasing the emphasis around 1-vs-2 as was done above. ```suggestion If not `null`, Log4j 2 will try to retrieve a **Log4j 1** configuration file from the given location. ``` ########## src/site/antora/modules/ROOT/pages/manual/migration.adoc: ########## @@ -16,433 +16,573 @@ Licensed to the Apache Software Foundation (ASF) under one or more //// = Migrating from Log4j 1 +:log4j1-url: https://logging.apache.org/log4j/1.x +:sonatype-url: https://central.sonatype.com/artifact + +{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 -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/Level.html[org.apache.log4j.Level] +| All methods -The Log4j 1.x bridge is useful when: +| {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`. -* 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. +| {log4j1-url}/apidocs/org/apache/log4j/Logger.html[org.apache.log4j.Logger] +| Same as `Category` -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`). +| {log4j1-url}/apidocs/org/apache/log4j/LogManager.html[org.apache.log4j.LogManager] +| All methods +|=== -image:whichjar-log4j-1.2-api.png[Using log4j 2 via the log4j 1.x API] +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. -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. +[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. -[id=enabling-the-log4j-1-x-bridge] -=== Enabling the Log4j 1.x bridge +All the libraries that use **Log4j 1 API** in their code must have a compile dependency on either +{sonatype-url}/log4j/log4j[log4j:log4j] +or its clone +{sonatype-url}/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**. -Enable the Log4j 1.x bridge via one of the following steps: +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: -. Set the system property "log4j1.compatibility" to a value of "true". -Log4j 2 will then add log4j.properties, log4j-test.properties, log4j.xml and log4j-test.xml to the xref:manual/configuration.adoc#AutomaticConfiguration[configuration files] it searches for on the class path. -. 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". +* {sonatype-url}/commons-logging/commons-logging[`commons-logging:commons-logging`], +* {sonatype-url}/org.apache.logging.log4j/log4j-api[`org.apache.logging.log4j:log4j-api`], +* {sonatype-url}/org.slf4j/slf4j-api[`org.slf4j:slf4j-api`], +* {sonatype-url}/org.jboss.logging/jboss-logging[`jboss-logging`], +* other logging APIs, -[#APICompatibility] -=== API Compatibility +it is fair to assume that it uses those libraries **instead** of **Log4j 1 API**, even if it has a direct dependency on `log4j:log4j` or `ch.qos.reload4j:reload4j`. +==== -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. +The following sections explain how to migrate from Log4j 1 to Log4j 2, depending on the way Log4j 1 is used in your application: -[#ConfigurationCompatibility] -=== Configuration Compatibility +* 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>>. -Log4j 2 provides support for Log4j 1 configuration files. -Configuration of the Appenders, Layouts and Filters that were provided in the Log4j 1 distribution will be redirected to their Log4j 2 counterparts - with the exception of the implemented Rewrite Policies. -This means that although the behavior of these components will be similar, they may not be exactly the same. -For example, the XML generated by the XMLLayout may not exactly match the XML generated by the Log4j1XMLLayout. +[#api-migration] +== Log4j 1 API migration -In addition, Log4j 2 supports custom Log4j 1 Appenders, Filters, and Layouts with some constraints. -Since the original Log4j 1 components may not be present in Log4j 2, custom components that extend them will fail. +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. -==== Supported Components +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 <<api-use-bridge>> for details. -Supported Appenders include: AsyncAppender, ConsoleAppender, DailyRollingFileAppender, FileAppender, NullAppender, RewriteAppender (limited), RollingFileAppender, SyslogAppender. +[#api-code-migration] +=== Migrate code from Log4j 1 API to Log4j 2 API -Supported Filters include: DenyAllFilter, LevelMatchFilter, LevelRangeFilter, StringMatchFilter. +[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. +==== -Supported Layouts include: HtmlLayout, PatternLayout, SimpleLayout, TTCCLayout , XmlLayout. +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. -Supported Rewrite Policies include: MapRewritePolicy, PropertyRewritePolicy. +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 -==== Unsupported or Unimplemented Components +| {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] -If your configuration contains any of the below components, consider xref:#Log4j2ConfigurationFormat[migrating your configuration] to the Log4j 2 format. +| {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] -===== Appenders +| {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] -* JDBCAppender (cannot be mapped to Log4j 2's JdbcAppender) -* JMSAppender -* SMTPAppender -* SocketAppender (Requires the use of the SerializedLayout which is a security risk) -* SocketHubAppender (Requires the use of the SerializedLayout which is a security risk) -* TelnetAppender (Security risk) +| {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] -===== Rewrite Policies +| {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] -* ReflectionRewritePolicy -* Custom rewrite policies since LoggingEvent is currently a no-op. +| {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] -===== Renderers +| {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] +|=== -Log4j 2 currently ignores renderers. +* 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 -[#Log4j12BridgeLimitations] -=== Limitations of the Log4j 1.x bridge +| {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()] -Applications can migrate by just using the bridge without further code changes, if they meet the following requirements: +| {log4j1-url}/apidocs/org/apache/log4j/Logger.html#getRootLogger()[Logger.getRootLogger()] +| link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getRootLogger()[LogManager.getRootLogger()] -. They must not access methods and classes internal to the Log4j 1.x implementation such as ``Appender``s, `LoggerRepository` or ``Category``'s `callAppenders` method. -. They must not programmatically configure Log4j. -. They must not configure by calling the Log4j 1.x classes `DOMConfigurator` or `PropertyConfigurator`. +| {log4j1-url}/apidocs/org/apache/log4j/Category.html#getEffectiveLevel()[Category.getEffectiveLevel()] +| link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#getLevel()[Logger.getLevel()] +|=== -=== When to stop using the Log4j 1.x bridge +* Finally, some methods need specific conversion rules to be applied: ++ +.Special Log4j 1 method migration rules +[cols="1,3"] +|=== +| Method | Description -Once you have migrated all of your own application and library code under your control, you may not need the bridge anymore. -Note that when you use a library/framework that can be configured to use several logging frameworks, then you typically don't need the log4j-1.2-api bridge either, as you may be able to directly configure it to use Log4j v2 instead v1. -Some libraries/frameworks even auto-detect the presence of certain logging framework implementations on their classpath, and automagically switch their internal logging delegation accordingly; -try simple removing the Log4j v1 dependency instead of replacing it with this bridge, and test if logging from all of your dependencies still work. +| {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. -If you own or can contribute open source to the library you depend on, consider replacing its use of the Log4j v1 API with the v2 API. +| {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()[`o.a.l.l.LogManager.shutdown()`] +method can be used. -While the Log4j 1.x bridge supports logging configurations that use the Log4j 1.x properties or XML format, migrating to the new 2.x format is not difficult. -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. +The utility of this method call depends upon the logging backend used with Log4j API. -[#Log4j2API] -== Option 2: convert your application to the Log4j 2 API (log4j-api) +The Log4j Core backend automatically adds a JVM shutdown hook on start up to perform any cleanups, so the `LogManager.shutdown()` call can be safely removed. +Starting in Log4j 2.1, you can also specify a custom +link:../javadoc/log4j-core/org/apache/logging/log4j/core/util/ShutdownCallbackRegistry.html[ShutdownCallbackRegistry]. -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. +See +xref:manual/systemproperties.adoc#log4j2.shutdownCallbackRegistry[log4j2.shutdownCallbackRegistry] +for more details. -image:whichjar-log4j-api.png[Using log4j 2 via the log4j 2.x API] +| Non Log4j 1 API methods +| Methods outside of those listed in <<log4j-1-api-methods>>, such as `Logger.setLevel()` need to be replaced with a method +call specific to the logging backend used by the application. +Some third-party integrators, such as Spring Boot, provide utility methods that let you abstract the logging backend, e.g. the +https://docs.spring.io/spring-boot/api/java/org/springframework/boot/logging/LoggingSystem.html#setLogLevel(java.lang.String,org.springframework.boot.logging.LogLevel)[`LoggingSystem.setLogLevel()`] +Spring Boot method. |=== -| Log4j 1.x | Log4j 2.x -| Package name: `org.apache.log4j` -| `org.apache.logging.log4j` +[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] +=== [[APICompatibility]]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>>. + +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 -| Calls to `org.apache.log4j.Logger.getLogger()` -| `org.apache.logging.log4j.LogManager.getLogger()` +If your application uses Log4j 1 **only** as logging backend bound to another logging API, such as Apache Commons Logging (JCL) or SLF4J, you only need to: -| Calls to `org.apache.log4j.Logger.getRootLogger()` or `org.apache.log4j.LogManager.getRootLogger()` -| `org.apache.logging.log4j.LogManager.getRootLogger()` +. Configure all logging bridges to log to Log4j 2 API instead. +This can be done by replacing the following dependencies on your application's runtime classpath: ++ +.Dependency migration from Log4j 1 to Log4j 2 +[cols="1,1"] +|=== +|Replace Log4j 1 dependency | with Log4j 2 dependency -| 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 +| {sonatype-url}/log4j/log4j[`log4j:log4j`] +| {sonatype-url}/org.apache.logging.log4j/log4j-core[`org.apache.logging.log4j:log4j-core`] -| Calls to `org.apache.log4j.Logger.getEffectiveLevel()` -| `org.apache.logging.log4j.Logger.getLevel()` +| {sonatype-url}/ch.qos.reload4j/reload4j[`ch.qos.reload4j:reload4j`] +| {sonatype-url}/org.apache.logging.log4j/log4j-core[`org.apache.logging.log4j:log4j-core`] -| 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. +| {sonatype-url}/commons-logging/commons-logging[`commons-logging:commons-logging`] +| either upgrade to version 1.3.0 (or later) -| 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. +or replace with +{sonatype-url}/org.apache.logging.log4j/log4j-slf4j2-impl[`org.apache.logging.log4j:log4j-jcl`] -| String concatenation like `logger.info("hi " + userName)` -| Parameterized messages like `logger.info("hi {}", userName)` +| {sonatype-url}/org.slf4j/slf4j-log4j12[`org.slf4j:slf4j-log4j12`] +| {sonatype-url}/org.apache.logging.log4j/log4j-slf4j2-impl[`org.apache.logging.log4j:log4j-slf4j2-impl`] -| 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] +| {sonatype-url}/org.slf4j/slf4j-reload4j[`org.slf4j:slf4j-reload4j`] +| {sonatype-url}/org.apache.logging.log4j/log4j-slf4j2-impl[`org.apache.logging.log4j:log4j-slf4j2-impl`] |=== ++ +See xref:manual/installation.adoc[] for more details. + +. Convert your configuration files from the Log4j 1 to the Log4j 2 configuration format. +See <<configuration-file-migration>> below for more details. + +[#migrate-custom-components] +=== Migrate Log4j 1 custom components + +Since Log4j 1 offered a limited amount of appenders and layouts, over the years users implemented many **custom** components that offered additional features. +If you are currently using a custom Log4j 1 component you should proceed as follows: + +. Log4j 2 provides many improvements to Log4j 1 components and many new components. +Check if the feature offered by your custom component is not already available in Log4j 2. +If you can not find the feature, ask on our link:/support.html[support channels]. +. Since Log4j 2.17.2, the Log4j 1 to Log4j 2 bridge has a limited support for using native Log4j 1 appenders and layouts. +Native Log4j 1 components can only be configured using Log4j 1 configuration files (see <<ConfigurationCompatibility>>) +and require the <<log4j-1-2-api-installation,installation of the Log4j 1 to Log4j 2 bridge>>. ++ +[WARNING] +==== +Mixing Log4j 1 and Log4j 2 components will most certainly reduce the performance of the logging system. +==== +. If your Log4j 1 native component is not supported by the Log4j 1 to Log4j 2 bridge, we suggest to rewrite it directly as Log4j 2 component. +See xref:manual/extending.adoc[] for more details. + +[#configuration-file-migration] +== Log4j 1 Configuration file migration [#Log4j2ConfigurationFormat] -== Migrating logging configurations to the Log4j 2 format +=== Convert configuration file 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. +Although the Log4j 2 configuration syntax is different from that of Log4j 1, most, if not all, of the same functionality is available. -=== Interpolation +[TIP] +==== +The `log4j-1.2-api` bridge contains a small utility that converts `log4j.properties` files into `log4j2.xml` file. +In order to use it you need to: -Note that system property interpolation via the `+${foo}+` syntax has been extended to allow property lookups from many different sources. -See the xref:manual/lookups.adoc[Lookups] documentation for more details. -For example, using a lookup for the system property named `catalina.base`, in Log4j 1.x, the syntax would be `${catalina.base}`. -In Log4j 2, the syntax would be `${sys:catalina.base}`. +. Download the `log4j-api`, `log4j-core` and `log4j-1.2-api` artifacts. +To retrieve them all at once, see the xref:download.adoc[] page. +. Set the `CLASSPATH` environment variable to contain the artifacts mentioned above. +. Run -=== Layouts +[source,shell] +---- +java org.apache.log4j.config.Log4j1ConfigurationConverter \ + --in log4j.properties --out log4j2.xml +---- +==== -Log4j 1.x has a XMLLayout which is different from the XmlLayout in Log4j 2. -The log4j-1.2-api module contains a `Log4j1XmlLayout` that produces output in the Log4j 1.x format. +[#configuration-interpolation] +==== Interpolation -The Log4j 1.x `SimpleLayout` can be emulated with PatternLayout "%level - %m%n". +Log4j 1 only supports interpolation using system properties and properties from the `log4j.properties` file using the `$\{foo}` syntax. +Log4j 2 extended this mechanism, by introducing pluggable xref:manual/lookups.adoc[]. -The Log4j 1.x `TTCCLayout` can be emulated with PatternLayout "%r [%t] %p %c %notEmpty{%ndc }- %m%n". +In order to convert a Log4j 1 configuration file that uses interpolation to a Log4j 2 configuration file, replace all occurrences of `$\{foo}` with `${sys:foo}`. -Both `PatternLayout` and `EnhancedPatternLayout` in Log4j 1.x can be replaced with `PatternLayout` in Log4j 2. -The log4j-1.2-api module contains two pattern conversions "%ndc" and "%properties" which can be used to emulate "%x" and "%X" in Log4j 1.x PatternLayout ("%x" and %X" in Log4j 2 have a slightly different format). +[#configuration-appenders] +==== Appenders -Below are some example configurations for Log4j 1.x and their counterparts in Log4j 2. +Log4j 2 contains an equivalent for most Log4j 1 appenders: -=== Sample 1 - Migrating a simple Console Appender configuration +.Log4j 2 equivalents of Log4j 1 appenders +[cols="1m,1m,2"] +|=== +| Log4j 1 appender | Log4j 2 equivalent | Notes -Log4j 1.x XML configuration +| {log4j1-url}/apidocs/org/apache/log4j/AsyncAppender.html[org.apache.log4j.AsyncAppender] +| xref:manual/appenders.adoc#AsyncAppender[Async] +| -[,xml] ----- -<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> -<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'> - <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> - <layout class="org.apache.log4j.PatternLayout"> - <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> - </layout> - </appender> - <category name="org.apache.log4j.xml"> - <priority value="info" /> - </category> - <Root> - <priority value ="debug" /> - <appender-ref ref="STDOUT" /> - </Root> -</log4j:configuration> ----- +| {log4j1-url}/apidocs/org/apache/log4j/ConsoleAppender.html[org.apache.log4j.ConsoleAppender] +| xref:manual/appenders.adoc#ConsoleAppender[Console] +| -Log4j 2 XML configuration +| {log4j1-url}/apidocs/org/apache/log4j/DailyRollingFileAppender.html[org.apache.log4j.DailyRollingFileAppender] +| xref:manual/appenders.adoc#RollingFileAppender[RollingFile] +| See <<rolling-file-conversion>> Review Comment: Link is missing a label:  ########## src/site/antora/modules/ROOT/pages/manual/migration.adoc: ########## @@ -16,433 +16,573 @@ Licensed to the Apache Software Foundation (ASF) under one or more //// = Migrating from Log4j 1 +:log4j1-url: https://logging.apache.org/log4j/1.x +:sonatype-url: https://central.sonatype.com/artifact + +{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 -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/Level.html[org.apache.log4j.Level] +| All methods -The Log4j 1.x bridge is useful when: +| {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`. -* 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. +| {log4j1-url}/apidocs/org/apache/log4j/Logger.html[org.apache.log4j.Logger] +| Same as `Category` -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`). +| {log4j1-url}/apidocs/org/apache/log4j/LogManager.html[org.apache.log4j.LogManager] +| All methods +|=== -image:whichjar-log4j-1.2-api.png[Using log4j 2 via the log4j 1.x API] +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. -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. +[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. -[id=enabling-the-log4j-1-x-bridge] -=== Enabling the Log4j 1.x bridge +All the libraries that use **Log4j 1 API** in their code must have a compile dependency on either +{sonatype-url}/log4j/log4j[log4j:log4j] +or its clone +{sonatype-url}/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**. -Enable the Log4j 1.x bridge via one of the following steps: +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: -. Set the system property "log4j1.compatibility" to a value of "true". -Log4j 2 will then add log4j.properties, log4j-test.properties, log4j.xml and log4j-test.xml to the xref:manual/configuration.adoc#AutomaticConfiguration[configuration files] it searches for on the class path. -. 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". +* {sonatype-url}/commons-logging/commons-logging[`commons-logging:commons-logging`], +* {sonatype-url}/org.apache.logging.log4j/log4j-api[`org.apache.logging.log4j:log4j-api`], +* {sonatype-url}/org.slf4j/slf4j-api[`org.slf4j:slf4j-api`], +* {sonatype-url}/org.jboss.logging/jboss-logging[`jboss-logging`], +* other logging APIs, -[#APICompatibility] -=== API Compatibility +it is fair to assume that it uses those libraries **instead** of **Log4j 1 API**, even if it has a direct dependency on `log4j:log4j` or `ch.qos.reload4j:reload4j`. +==== -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. +The following sections explain how to migrate from Log4j 1 to Log4j 2, depending on the way Log4j 1 is used in your application: -[#ConfigurationCompatibility] -=== Configuration Compatibility +* 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>>. -Log4j 2 provides support for Log4j 1 configuration files. -Configuration of the Appenders, Layouts and Filters that were provided in the Log4j 1 distribution will be redirected to their Log4j 2 counterparts - with the exception of the implemented Rewrite Policies. -This means that although the behavior of these components will be similar, they may not be exactly the same. -For example, the XML generated by the XMLLayout may not exactly match the XML generated by the Log4j1XMLLayout. +[#api-migration] +== Log4j 1 API migration -In addition, Log4j 2 supports custom Log4j 1 Appenders, Filters, and Layouts with some constraints. -Since the original Log4j 1 components may not be present in Log4j 2, custom components that extend them will fail. +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. -==== Supported Components +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 <<api-use-bridge>> for details. -Supported Appenders include: AsyncAppender, ConsoleAppender, DailyRollingFileAppender, FileAppender, NullAppender, RewriteAppender (limited), RollingFileAppender, SyslogAppender. +[#api-code-migration] +=== Migrate code from Log4j 1 API to Log4j 2 API -Supported Filters include: DenyAllFilter, LevelMatchFilter, LevelRangeFilter, StringMatchFilter. +[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. +==== -Supported Layouts include: HtmlLayout, PatternLayout, SimpleLayout, TTCCLayout , XmlLayout. +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. -Supported Rewrite Policies include: MapRewritePolicy, PropertyRewritePolicy. +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 -==== Unsupported or Unimplemented Components +| {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] -If your configuration contains any of the below components, consider xref:#Log4j2ConfigurationFormat[migrating your configuration] to the Log4j 2 format. +| {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] -===== Appenders +| {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] -* JDBCAppender (cannot be mapped to Log4j 2's JdbcAppender) -* JMSAppender -* SMTPAppender -* SocketAppender (Requires the use of the SerializedLayout which is a security risk) -* SocketHubAppender (Requires the use of the SerializedLayout which is a security risk) -* TelnetAppender (Security risk) +| {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] -===== Rewrite Policies +| {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] -* ReflectionRewritePolicy -* Custom rewrite policies since LoggingEvent is currently a no-op. +| {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] -===== Renderers +| {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] +|=== -Log4j 2 currently ignores renderers. +* 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 -[#Log4j12BridgeLimitations] -=== Limitations of the Log4j 1.x bridge +| {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()] -Applications can migrate by just using the bridge without further code changes, if they meet the following requirements: +| {log4j1-url}/apidocs/org/apache/log4j/Logger.html#getRootLogger()[Logger.getRootLogger()] +| link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getRootLogger()[LogManager.getRootLogger()] -. They must not access methods and classes internal to the Log4j 1.x implementation such as ``Appender``s, `LoggerRepository` or ``Category``'s `callAppenders` method. -. They must not programmatically configure Log4j. -. They must not configure by calling the Log4j 1.x classes `DOMConfigurator` or `PropertyConfigurator`. +| {log4j1-url}/apidocs/org/apache/log4j/Category.html#getEffectiveLevel()[Category.getEffectiveLevel()] +| link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#getLevel()[Logger.getLevel()] +|=== -=== When to stop using the Log4j 1.x bridge +* Finally, some methods need specific conversion rules to be applied: ++ +.Special Log4j 1 method migration rules +[cols="1,3"] +|=== +| Method | Description -Once you have migrated all of your own application and library code under your control, you may not need the bridge anymore. -Note that when you use a library/framework that can be configured to use several logging frameworks, then you typically don't need the log4j-1.2-api bridge either, as you may be able to directly configure it to use Log4j v2 instead v1. -Some libraries/frameworks even auto-detect the presence of certain logging framework implementations on their classpath, and automagically switch their internal logging delegation accordingly; -try simple removing the Log4j v1 dependency instead of replacing it with this bridge, and test if logging from all of your dependencies still work. +| {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. -If you own or can contribute open source to the library you depend on, consider replacing its use of the Log4j v1 API with the v2 API. +| {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()[`o.a.l.l.LogManager.shutdown()`] +method can be used. -While the Log4j 1.x bridge supports logging configurations that use the Log4j 1.x properties or XML format, migrating to the new 2.x format is not difficult. -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. +The utility of this method call depends upon the logging backend used with Log4j API. -[#Log4j2API] -== Option 2: convert your application to the Log4j 2 API (log4j-api) +The Log4j Core backend automatically adds a JVM shutdown hook on start up to perform any cleanups, so the `LogManager.shutdown()` call can be safely removed. +Starting in Log4j 2.1, you can also specify a custom +link:../javadoc/log4j-core/org/apache/logging/log4j/core/util/ShutdownCallbackRegistry.html[ShutdownCallbackRegistry]. -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. +See +xref:manual/systemproperties.adoc#log4j2.shutdownCallbackRegistry[log4j2.shutdownCallbackRegistry] +for more details. -image:whichjar-log4j-api.png[Using log4j 2 via the log4j 2.x API] +| Non Log4j 1 API methods +| Methods outside of those listed in <<log4j-1-api-methods>>, such as `Logger.setLevel()` need to be replaced with a method +call specific to the logging backend used by the application. +Some third-party integrators, such as Spring Boot, provide utility methods that let you abstract the logging backend, e.g. the +https://docs.spring.io/spring-boot/api/java/org/springframework/boot/logging/LoggingSystem.html#setLogLevel(java.lang.String,org.springframework.boot.logging.LogLevel)[`LoggingSystem.setLogLevel()`] +Spring Boot method. |=== -| Log4j 1.x | Log4j 2.x -| Package name: `org.apache.log4j` -| `org.apache.logging.log4j` +[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] +=== [[APICompatibility]]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>>. + +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 -| Calls to `org.apache.log4j.Logger.getLogger()` -| `org.apache.logging.log4j.LogManager.getLogger()` +If your application uses Log4j 1 **only** as logging backend bound to another logging API, such as Apache Commons Logging (JCL) or SLF4J, you only need to: -| Calls to `org.apache.log4j.Logger.getRootLogger()` or `org.apache.log4j.LogManager.getRootLogger()` -| `org.apache.logging.log4j.LogManager.getRootLogger()` +. Configure all logging bridges to log to Log4j 2 API instead. +This can be done by replacing the following dependencies on your application's runtime classpath: ++ +.Dependency migration from Log4j 1 to Log4j 2 +[cols="1,1"] +|=== +|Replace Log4j 1 dependency | with Log4j 2 dependency -| 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 +| {sonatype-url}/log4j/log4j[`log4j:log4j`] +| {sonatype-url}/org.apache.logging.log4j/log4j-core[`org.apache.logging.log4j:log4j-core`] -| Calls to `org.apache.log4j.Logger.getEffectiveLevel()` -| `org.apache.logging.log4j.Logger.getLevel()` +| {sonatype-url}/ch.qos.reload4j/reload4j[`ch.qos.reload4j:reload4j`] +| {sonatype-url}/org.apache.logging.log4j/log4j-core[`org.apache.logging.log4j:log4j-core`] -| 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. +| {sonatype-url}/commons-logging/commons-logging[`commons-logging:commons-logging`] +| either upgrade to version 1.3.0 (or later) -| 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. +or replace with +{sonatype-url}/org.apache.logging.log4j/log4j-slf4j2-impl[`org.apache.logging.log4j:log4j-jcl`] -| String concatenation like `logger.info("hi " + userName)` -| Parameterized messages like `logger.info("hi {}", userName)` +| {sonatype-url}/org.slf4j/slf4j-log4j12[`org.slf4j:slf4j-log4j12`] +| {sonatype-url}/org.apache.logging.log4j/log4j-slf4j2-impl[`org.apache.logging.log4j:log4j-slf4j2-impl`] -| 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] +| {sonatype-url}/org.slf4j/slf4j-reload4j[`org.slf4j:slf4j-reload4j`] +| {sonatype-url}/org.apache.logging.log4j/log4j-slf4j2-impl[`org.apache.logging.log4j:log4j-slf4j2-impl`] |=== ++ +See xref:manual/installation.adoc[] for more details. + +. Convert your configuration files from the Log4j 1 to the Log4j 2 configuration format. +See <<configuration-file-migration>> below for more details. + +[#migrate-custom-components] +=== Migrate Log4j 1 custom components + +Since Log4j 1 offered a limited amount of appenders and layouts, over the years users implemented many **custom** components that offered additional features. +If you are currently using a custom Log4j 1 component you should proceed as follows: + +. Log4j 2 provides many improvements to Log4j 1 components and many new components. +Check if the feature offered by your custom component is not already available in Log4j 2. +If you can not find the feature, ask on our link:/support.html[support channels]. +. Since Log4j 2.17.2, the Log4j 1 to Log4j 2 bridge has a limited support for using native Log4j 1 appenders and layouts. +Native Log4j 1 components can only be configured using Log4j 1 configuration files (see <<ConfigurationCompatibility>>) +and require the <<log4j-1-2-api-installation,installation of the Log4j 1 to Log4j 2 bridge>>. ++ +[WARNING] +==== +Mixing Log4j 1 and Log4j 2 components will most certainly reduce the performance of the logging system. +==== +. If your Log4j 1 native component is not supported by the Log4j 1 to Log4j 2 bridge, we suggest to rewrite it directly as Log4j 2 component. +See xref:manual/extending.adoc[] for more details. + +[#configuration-file-migration] +== Log4j 1 Configuration file migration [#Log4j2ConfigurationFormat] -== Migrating logging configurations to the Log4j 2 format +=== Convert configuration file 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. +Although the Log4j 2 configuration syntax is different from that of Log4j 1, most, if not all, of the same functionality is available. -=== Interpolation +[TIP] +==== +The `log4j-1.2-api` bridge contains a small utility that converts `log4j.properties` files into `log4j2.xml` file. +In order to use it you need to: -Note that system property interpolation via the `+${foo}+` syntax has been extended to allow property lookups from many different sources. -See the xref:manual/lookups.adoc[Lookups] documentation for more details. -For example, using a lookup for the system property named `catalina.base`, in Log4j 1.x, the syntax would be `${catalina.base}`. -In Log4j 2, the syntax would be `${sys:catalina.base}`. +. Download the `log4j-api`, `log4j-core` and `log4j-1.2-api` artifacts. +To retrieve them all at once, see the xref:download.adoc[] page. +. Set the `CLASSPATH` environment variable to contain the artifacts mentioned above. +. Run -=== Layouts +[source,shell] +---- +java org.apache.log4j.config.Log4j1ConfigurationConverter \ + --in log4j.properties --out log4j2.xml +---- +==== -Log4j 1.x has a XMLLayout which is different from the XmlLayout in Log4j 2. -The log4j-1.2-api module contains a `Log4j1XmlLayout` that produces output in the Log4j 1.x format. +[#configuration-interpolation] +==== Interpolation -The Log4j 1.x `SimpleLayout` can be emulated with PatternLayout "%level - %m%n". +Log4j 1 only supports interpolation using system properties and properties from the `log4j.properties` file using the `$\{foo}` syntax. +Log4j 2 extended this mechanism, by introducing pluggable xref:manual/lookups.adoc[]. -The Log4j 1.x `TTCCLayout` can be emulated with PatternLayout "%r [%t] %p %c %notEmpty{%ndc }- %m%n". +In order to convert a Log4j 1 configuration file that uses interpolation to a Log4j 2 configuration file, replace all occurrences of `$\{foo}` with `${sys:foo}`. -Both `PatternLayout` and `EnhancedPatternLayout` in Log4j 1.x can be replaced with `PatternLayout` in Log4j 2. -The log4j-1.2-api module contains two pattern conversions "%ndc" and "%properties" which can be used to emulate "%x" and "%X" in Log4j 1.x PatternLayout ("%x" and %X" in Log4j 2 have a slightly different format). +[#configuration-appenders] +==== Appenders -Below are some example configurations for Log4j 1.x and their counterparts in Log4j 2. +Log4j 2 contains an equivalent for most Log4j 1 appenders: -=== Sample 1 - Migrating a simple Console Appender configuration +.Log4j 2 equivalents of Log4j 1 appenders +[cols="1m,1m,2"] +|=== +| Log4j 1 appender | Log4j 2 equivalent | Notes -Log4j 1.x XML configuration +| {log4j1-url}/apidocs/org/apache/log4j/AsyncAppender.html[org.apache.log4j.AsyncAppender] +| xref:manual/appenders.adoc#AsyncAppender[Async] +| -[,xml] ----- -<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> -<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'> - <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> - <layout class="org.apache.log4j.PatternLayout"> - <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> - </layout> - </appender> - <category name="org.apache.log4j.xml"> - <priority value="info" /> - </category> - <Root> - <priority value ="debug" /> - <appender-ref ref="STDOUT" /> - </Root> -</log4j:configuration> ----- +| {log4j1-url}/apidocs/org/apache/log4j/ConsoleAppender.html[org.apache.log4j.ConsoleAppender] +| xref:manual/appenders.adoc#ConsoleAppender[Console] +| -Log4j 2 XML configuration +| {log4j1-url}/apidocs/org/apache/log4j/DailyRollingFileAppender.html[org.apache.log4j.DailyRollingFileAppender] +| xref:manual/appenders.adoc#RollingFileAppender[RollingFile] +| See <<rolling-file-conversion>> -[,xml] ----- -<Configuration> - <Appenders> - <Console name="STDOUT" target="SYSTEM_OUT"> - <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> - </Console> - </Appenders> - <Loggers> - <Logger name="org.apache.log4j.xml" level="info"/> - <Root level="debug"> - <AppenderRef ref="STDOUT"/> - </Root> - </Loggers> -</Configuration> ----- +| {log4j1-url}/apidocs/org/apache/log4j/FileAppender.html[org.apache.log4j.FileAppender] +| xref:manual/appenders.adoc#FileAppender[File] +| -=== Sample 2 - Migrating a simple File Appender, XMLLayout and SimpleLayout configuration +| {log4j1-url}/apidocs/org/apache/log4j/RollingFileAppender.html[org.apache.log4j.RollingFileAppender] +| xref:manual/appenders.adoc#RollingFileAppender[RollingFile] +| See <<rolling-file-conversion>> Review Comment: Link is missing a label:  ########## 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); Review Comment: Could you rename all `static final`s to upper-case, please? That is, `s/logger/LOGGER/`. Note that this is the recommended practice in `getting-started.adoc` too. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
