The Java Logging Battleground Gets Two New Updates
Written by Nikos Vaggalis   
Thursday, 13 October 2022

New releases of two popular APIs update Java's logging battleground. Battleground because there are two front runners. The two APIs in question are SLF4J 2.0.0 and Log4j 2.19.0.

First of all, let's meet them both. SLF4J stands for Simple Logging Facade for Java and is an interface for various logging backend frameworks like java.util.logging, logback, log4j and log4j2 so that applications can use any of them interchangeably without changing code.

 
 
However, despite SLF4J's portability and in order to work with it, each backend framework requires a specific config file, something that has raised question of whether SLF4J is actually that useful; if that is the case why not just go straight for an implementation like log4j directly, forgoing SLF4J completely? It's a valid argument, but the real value of SLF4J is for people producing libraries and you don't want to force a specific logging framework onto your clients. The SLF4J abstraction allows the consumer to choose an implementation.

SLF4J's 2. 0. x series major improvement is the addition of a backward-compatible fluent logging api. The idea is to build a logging event piece by piece with a LoggingEventBuilder  and to log once the event is fully built. The methods atTrace(), atDebug(), atInfo(), atWarn() atError(), all new in the org.slf4j.Logger interface, return an instance of LoggingEventBuilder.

Here are few usage examples:

The statement

logger.atInfo().log("Hello world.");

is equivalent to:

logger.info("Hello world.");

The following log statements are equivalent in their output (for the default implementation):

int newT = 15;
int oldT = 16;

// using traditional API
logger.debug("Temperature set to {}. Old value was {}.", newT, oldT);

// using fluent API, log message with arguments
logger.atDebug().log("Temperature set to {}. Old value was {}.", newT, oldT);

// using fluent API, add arguments one by one and then log message
logger.atDebug().setMessage("Temperature set to {}. Old value was {}.").addArgument(newT).addArgument(oldT).log();

// using fluent API, add one argument with a Supplier //and then log message with one more argument.
// Assume the method t16() returns 16.
logger.atDebug().setMessage("Temperature set to {}. Old value was {}.").addArgument(() -> t16()).addArgument(oldT).log()

For most users, upgrading to version 2. 0. x should be a drop-in replacement, as long as the logging provider is updated as well. Existing frameworks must migrate to the ServiceLoader mechanism since slf4j-api now relies on this to find its logging backend.

What are those existing frameworks if SLF4J is an abstraction over them? 

  • java. util. logging for basic functionality
  • Log4j —Apache Log4j, was very popular but it was deprecated on August 5, 2015
  • Logback — a successor to the popular log4j project, picking up where log4j 1. x leaves off
  • Log4j 2 — Apache Log4j 2 is another successor and upgrade to Log4j and is considered more improved than Logback.
    It provides many other modern features such as support for Markers, lambda expressions for lazy logging, property substitution using Lookups, multiple patterns on a PatternLayout and asynchronous Loggers.

 

That said, Log4j2 has a new version 2.19.0 as of this September, primarily containing bug fixes and minor enhancements. As discussed, it also needed to change to support the new SLF4J 2.0.x ServiceLoader mechanism:

Due to breaks in compatibility in the SLF4J binding, Log4j now ships with two versions of the SLF4J to Log4j adapters. log4j-slf4j-impl should be used with SLF4J 1. 7. x and earlier and log4j-slf4j2-impl should be used with SLF4J 2. x and later. SLF4J-1. 8. x is no longer supported as a GA release never occurred.

Apache Log4j 2.19.0, as well as SLF4J 2. 0. x, requires a minimum of Java 8 to build and run.

Finally, note that Log4j2 also provides an API for various logging implementations like SLF4J does. In that sense it competes with SLF4J since it acts both as a facade and an implementation.

As such, the Log4j API is a logging facade that may, of course, be used with the Log4j implementation, but may also be used in front of other logging implementations such as Logback. The Log4j API has several advantages over SLF4J: 

  • The Log4j API supports logging Messages instead of just Strings.

  • The Log4j API supports lambda expressions.

  • The Log4j API provides many more logging methods than SLF4J.

  • In addition to the “parameterized logging” format supported by SLF4J, the Log4j API also supports events using the java. text. MessageFormat syntax as well printf-style messages.

  • The Log4j API provides a LogManager. shutdown() method. The underlying logging implementation must implement the Terminable interface for the method to have effect.

  • Other constructs such as Markers, log Levels, and ThreadContext (aka MDC) are fully supported. 

Log4j 2 does a lot, but that's both a blessing and a curse as the latest Log4JShell vulnerability demonstrated. Trying to go overboard by allowing any inputs to be parsed and interpreted by the application, no matter where it originates, just for providing more functionality to its users, opened it wide to exploits.

iconslf4j

More Information

SLF4J user manual

SLF4J GitHub

Log4j2 2.19.0

Related Articles

Apache Tika Improves Security

Open Source Insights Into The Software Supply Chain

Kafka Replaces Zookeeper With Quorum

Last Updated ( Thursday, 13 October 2022 )