Hi all,

I have finished the PRs for all X-to-Log4j API and Log4j API-to-X
bridges in `2.x` and `3.x`, but the PRs are still waiting for a
review, before I merge them and release `3.0.0-beta3`.
Sorry for the long e-mail.

Summarizing the situation would be:

== JUL

The Log4j API-to-JUL bridge (`log4j-to-jul`) will stay in `2.x` and it
will be referenced in `log4j-bom` version 3.x. Everything we need is
in JUL from JDK 8. I don't see any improvements we could make using
JDK 17.

The JUL-to-Log4j API (`log4j-jul`) will be refactored in `3.x` to take
advantage of some new JUL methods in JDK 17:

* The `o.a.l.l.jul.LogManager` will be moved to a new `jul-to-log4j`
artifact (and renamed). This is the premiere choice for JUL-to-Log4j
API forwarding, since it replaces the JUL logging backend entirely. On
the other hand its usage requires a lot of manual setup on the part of
the application developer (e.g. he must set the
`java.util.logging.manager` system property before anything in the JVM
uses it, i.e. on the command line). Users will tolerate the class name
change.

* The `Log4jBridgeHandler`, which is used by Spring Boot, will stay in
`log4j-jul`. This is a fallback JUL-to-Log4j API forwarding, since it
uses the original `j.u.l.LogManager` and `j.u.l.Logger` (including
filtering). For this reason `log4j-core` is added as a required
dependency, so that it can propagate configured log levels to
`j.u.l.Logger`s (this enhances performance for disabled loggers, since
it drops the log events as fast as possible). Since there is also an
`Slf4jBridgeHandler`, I don't expect anyone using `log4j-jul` with
anything else than Log4j Core.

[1] https://github.com/apache/logging-log4j2/pull/2935

== JPL (System.Logger)

The JPL-to-Log4j API bridge requires JDK 11 or higher. So I keep it in
version 3.x.

== SLF4J

The Log4j API-to-SLF4J bridge (`log4j-to-slf4j`) will stay in `2.x`
and it will be referenced in `log4j-bom` version 3.x. Everything we
need is in SLF4J 1.7.x. I don't see any improvements we could make
using SLF4J 2.x.

The SLF4J-to-Log4j API bridges (`log4j-slf4j-impl` and
`log4j-slf4j2-impl`) are the problem and have caused a lot of
discussion (see [1], [2], [3] and the last PMC meeting).

There is a difference between what they are and how people use them:

1. Technically they are bridges between APIs and depend only on
`log4j-api` and `slf4j-api`,
2. Many users (not Spring Boot and major actors, but smaller projects)
use them as a single dependency they need to add to use Log4j Core.
This usage is justified by the description of the artifacts that was
"The Apache Log4j SLF4J API binding to Log4j 2 Core" and many sites
like MvnRepository still use that description. This is why currently
the bridges have a runtime `log4j-core` dependency.
3. Some users even use these artifacts directly in their code. For
example they cast SLF4J Markers to our concrete implementation to add
structured data that SLF4J is not able to provide.

Now, I am categorically against allowing usage (3) in Log4j 3.x. If
the bridges are to remain in `3.x`, they will be totally encapsulated
in a single non-exported package (which is the recommended JPMS way
for service providers).

If we remove the bridges from 3.x (and add them to `log4j-bom` version
3.x), there will be a hiccup in the (2) usage: the runtime
dependencies of `log4j-slf4j2-impl` 2.x contain `log4j-core` 2.x. If a
user want to use Log4j Core 3.x, he needs to do it explicitly (either
adding `log4j-core` explicitly to their POM, adding `log4j-bom` to
dependency management or better both).
There are two solutions to this problem:

=== Solution 1

We can:

* drop the bridges in 3.x and add them to `log4j-bom` version 3.x
(implemented in PR #2924[2]),
* drop the runtime dependency on `log4j-core` in 2.x (implemented in
PR #3038[3]),
* document everything.

The advantage of this solution is that users will be forced to add
`log4j-core` explicitly to their POM starting with version `2.25.x`.

=== Solution 2

We can:

* create a brand new and correctly named `slf4j-to-log4j` file and
advertise it as SLF4J-to-Log4j API bridge.
* in 2.x the bridge will be just an empty JAR with a dependency on
`log4j-slf4j2-impl` and an exclusion on `log4j-core`.
* in 3.x the bridge will be a rebranded and encapsulated `log4j-slf4j2-impl`.
* the `log4j-slf4j-impl` and `log4j-slf4j2-impl` artifacts disappear
from the 3.x branch and even from `log4j-bom`.

The advantage of this solution is branding. This will break the setup
of all users, even `spring-boot-starter-log4j2` that correctly declare
both the SLF4J-to-Log4j API bridge and Log4j Core. On the other hand
users can not complain about backward compatibility, since there will
be no previous history with the `slf4j-to-log4j` artifact.

Which solution would you prefer? We can also have hybrid solutions
(solution 1 + new `slf4j-to-log4j` artifact in 3.x).

Piotr

[1] https://issues.apache.org/jira/browse/LOG4J2-3601
[2] https://github.com/apache/logging-log4j2/pull/2924
[3] https://github.com/apache/logging-log4j2/pull/3038

Reply via email to