= Migrating from Log4j 1.x
Ralph Goers <rgoers@apache.org>

[#Log4j1.2Bridge]
== Using the Log4j 1.x bridge

Perhaps the simplest way to convert to using Log4j 2 is to replace the
log4j 1.x jar file with Log4j 2's `log4j-1.2-api.jar`. However, to use
this successfully applications must meet the following requirements:

1.  They must not access methods and classes internal to the Log4j 1.x
implementation such as `Appender`s, `LoggerRepository` or `Category`'s
`callAppenders` method.
2.  They must not programmatically configure Log4j.
3.  They must not configure by calling the classes `DOMConfigurator` or
`PropertyConfigurator`.

== Converting to 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.

.  The main package in version 1 is `org.apache.log4j`, in version 2 it
is `org.apache.logging.log4j`
.  Calls to `org.apache.log4j.Logger.getLogger()` must be modified to
`org.apache.logging.log4j.LogManager.getLogger()`.
.  Calls to `org.apache.log4j.Logger.getRootLogger()` or
`org.apache.log4j.LogManager.getRootLogger()` must be replaced with
`org.apache.logging.log4j.LogManager.getRootLogger()`.
.  Calls to `org.apache.log4j.Logger.getLogger` that accept a
`LoggerFactory` must remove the `org.apache.log4j.spi.LoggerFactory` and
use one of Log4j 2's other extension mechanisms.
.  Replace calls to `org.apache.log4j.Logger.getEffectiveLevel()` with
`org.apache.logging.log4j.Logger.getLevel()`.
.  Remove calls to `org.apache.log4j.LogManager.shutdown()`, they are
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:../log4j-core/apidocs/org/apache/logging/log4j/core/util/ShutdownCallbackRegistry.html[`ShutdownCallbackRegistry`]
to override the default JVM shutdown hook strategy.
..  Starting in Log4j 2.6, you can now use
`org.apache.logging.log4j.LogManager.shutdown()` to initiate shutdown
manually.
.  Calls to `org.apache.log4j.Logger.setLevel()` or similar methods are
not supported in the API. Applications should remove these. Equivalent
functionality is provided in the Log4j 2 implementation classes, see
`org.apache.logging.log4j.core.config.Configurator.setLevel()`, but may
leave the application susceptible to changes in Log4j 2 internals.
.  Where appropriate, applications should convert to use parameterized
messages instead of String concatenation.
.  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`]
have been replaced by the link:thread-context.html[Thread Context].

== Configuring Log4j 2

Although the Log4j 2 configuration syntax is different than that of
Log4j 1.x, most, if not all, of the same functionality is available.

Note that system property interpolation via the `${foo}` syntax has been
extended to allow property lookups from many different sources. See the
link:lookups.html[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}`.

Log4j 1.x has a XMLLayout which is different from the XmlLayout in Log4j
2, the log4j-1.2-api module contains a `Log4j1XmlLayout` which produce
output in the format as in Log4j 1.x. The Log4j 1.x `SimpleLayout` can
be emulated with PatternLayout "%level - %m%n". The Log4j 1.x
`TTCCLayout` can be emulated with PatternLayout "%r [%t] %p %c
%notEmpty\{%ndc }- %m%n".

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).

Below are the example configurations for Log4j 1.x and their
counterparts in Log4j 2.

=== Sample 1 - Simple configuration using a Console Appender

Log4j 1.x XML configuration

.log4j.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<!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>
----

Log4j 2 XML configuration

.log4j2.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<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>
----

=== Sample 2 - Simple configuration using a File Appender, XMLLayout and SimpleLayout

Log4j 1.x XML configuration

.log4j.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="A1" class="org.apache.log4j.FileAppender">
    <param name="File"   value="A1.log" />
    <param name="Append" value="false" />
    <layout class="org.apache.log4j.xml.XMLLayout" />
  </appender>
  <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.SimpleLayout" />
  </appender>
  <category name="org.apache.log4j.xml">
    <priority value="debug" />
    <appender-ref ref="A1" />
  </category>
  <root>
    <priority value ="debug" />
    <appender-ref ref="STDOUT" />
  </Root>
</log4j:configuration>
----

Log4j 2 XML configuration

.log4j2.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <File name="A1" fileName="A1.log" append="false">
      <Log4j1XmlLayout />
    </File>
    <Console name="STDOUT" target="SYSTEM_OUT">
      <PatternLayout pattern="%level - %m%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="org.apache.log4j.xml" level="debug">
      <AppenderRef ref="A1"/>
    </Logger>
    <Root level="debug">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
</Configuration>
----

=== Sample 3 - SocketAppender

Log4j 1.x XML configuration. This example from Log4j 1.x is misleading.
The SocketAppender does not actually use a Layout. Configuring one will
have no effect.

.log4j.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="A1" class="org.apache.log4j.net.SocketAppender">
    <param name="RemoteHost" value="localhost"/>
    <param name="Port" value="5000"/>
    <param name="LocationInfo" value="true"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/>
    </layout>
  </appender>
  <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="debug"/>
    <appender-ref ref="A1"/>
  </category>
  <root>
    <priority value="debug"/>
    <appender-ref ref="STDOUT"/>
  </Root>
</log4j:configuration>
----

Log4j 2 XML configuration

.log4j2.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <Socket name="A1" host="localHost" port="5000">
      <PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
    </Socket>
    <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="debug">
      <AppenderRef ref="A1"/>
    </Logger>
    <Root level="debug">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
</Configuration>
----

=== Sample 4 - AsyncAppender and TTCCLayout

Log4j 1.x XML configuration using the AsyncAppender.

.log4j.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" configDebug="true">
  <appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
    <appender-ref ref="TEMP"/>
  </appender>
  <appender name="TEMP" class="org.apache.log4j.FileAppender">
    <param name="File" value="temp"/>
    <layout class="org.apache.log4j.TTCCLayout">
      <param name="ThreadPrinting" value="true"/>
      <param name="CategoryPrefixing" value="true"/>
      <param name="ContextPrinting" value="true"/>
    </layout>
  </appender>
  <root>
    <priority value="debug"/>
    <appender-ref ref="ASYNC"/>
  </Root>
</log4j:configuration>
----

Log4j 2 XML configuration.

.log4j2.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
  <Appenders>
    <File name="TEMP" fileName="temp">
      <PatternLayout pattern="%r [%t] %p %c %notEmpty{%ndc }- %m%n"/>
    </File>
    <Async name="ASYNC">
      <AppenderRef ref="TEMP"/>
    </Async>
  </Appenders>
  <Loggers>
    <Root level="debug">
      <AppenderRef ref="ASYNC"/>
    </Root>
  </Loggers>
</Configuration>
----

=== Sample 5 - AsyncAppender with Console and File

Log4j 1.x XML configuration using the AsyncAppender.

.log4j.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" configDebug="true">
  <appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
    <appender-ref ref="TEMP"/>
    <appender-ref ref="CONSOLE"/>
  </appender>
  <appender name="CONSOLE" 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>
  <appender name="TEMP" class="org.apache.log4j.FileAppender">
    <param name="File" value="temp"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
    </layout>
  </appender>
  <root>
    <priority value="debug"/>
    <appender-ref ref="ASYNC"/>
  </Root>
</log4j:configuration>
----

Log4j 2 XML configuration. Note that the Async Appender should be
configured after the appenders it references. This will allow it to
shutdown properly.

.log4j2.xml
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
  <Appenders>
    <Console name="CONSOLE" target="SYSTEM_OUT">
      <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
    </Console>
    <File name="TEMP" fileName="temp">
      <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
    </File>
    <Async name="ASYNC">
      <AppenderRef ref="TEMP"/>
      <AppenderRef ref="CONSOLE"/>
    </Async>
  </Appenders>
  <Loggers>
    <Root level="debug">
      <AppenderRef ref="ASYNC"/>
    </Root>
  </Loggers>
</Configuration>
----
