slf4j, jcl, jul, log4j1, log4j2, logback summary

#1 Series Catalog

#2 Summary of various jar packages

  • log4j1:

    • log4j: the entire contents of log4j1
  • log4j2:

    • log4j-api: API defined by log4j2
    • log4j-core: The implementation of the above API of log4j2
  • logback:

    • logback-core: the core package of logback
    • logback-classic: logback implements the API of slf4j
  • commons-logging:

    • commons-logging: The native fullness of commons-logging
    • log4j-jcl: a bridge from commons-logging to log4j2
    • jcl-over-slf4j: bridge from commons-logging to slf4j
  • slf4j turns to some actual logging framework:

    Scenario introduction: If you use the slf4j API for programming, the bottom layer wants to use log4j1 for actual log output, which is what slf4j-log4j12 does.

    • slf4j-jdk14: Bridge from slf4j to jdk-logging
    • slf4j-log4j12: Bridge from slf4j to log4j1
    • log4j-slf4j-impl: Bridge from slf4j to log4j2
    • logback-classic: the bridge from slf4j to logback
    • slf4j-jcl: Bridge from slf4j to commons-logging
  • Some actual logging framework turns to slf4j:

    Scenario introduction: If you use the log4j1 API for programming, but you want to output through logback, you need to first transfer the log output of log4j1 to slf4j for output, and then slf4j to logback for output. Forward the output of log4j1 to slf4j, which is what log4j-over-slf4j does

    This part is mainly used to switch between the actual log frameworks (will be explained in detail below)

    • jul-to-slf4j: bridge from jdk-logging to slf4j
    • log4j-over-slf4j: bridge from log4j1 to slf4j
    • jcl-over-slf4j: bridge from commons-logging to slf4j

#3 Integration Summary

##3.1 commons-logging integrates with other logging frameworks

  • 1 commons-logging and jdk-logging integration:

    Required jar package:

    • commons-logging
  • 2 commons-logging integrated with log4j1:

    Required jar package:

    • commons-logging
    • log4j
  • 3 commons-logging integrated with log4j2:

    Required jar package:

    • commons-logging
    • log4j-api
    • log4j-core
    • log4j-jcl (integrated package)
  • 4 commons-logging integration with logback:

    Required jar package:

    • logback-core
    • logback-classic
    • slf4j-api, jcl-over-slf4j (2 integrated packages, commons-logging is no longer required)
  • 5 commons-logging integration with slf4j:

    Required jar package:

    • jcl-over-slf4j (integrated package, no more commons-logging needed)
    • slf4j-api

##3.2 slf4j integration with other logging frameworks

  • slf4j integration with jdk-logging:

    Required jar package:

    • slf4j-api
    • slf4j-jdk14 (integrated package)
  • slf4j integration with log4j1:

    Required jar package:

    • slf4j-api
    • log4j
    • slf4j-log4j12 (integrated package)
  • slf4j integration with log4j2:

    Required jar package:

    • slf4j-api
    • log4j-api
    • log4j-core
    • log4j-slf4j-impl (integrated package)
  • slf4j integration with logback:

    Required jar package:

    • slf4j-api
    • logback-core
    • logback-classic (integrated package)
  • slf4j integration with commons-logging:

    Required jar package:

    • slf4j-api
    • commons-logging
    • slf4j-jcl (integrated package)

#4 Switching between logging systems

##4.1 log4j seamlessly switches to logback

###4.1.1 Case

We have used the log4j1 API in the code to output the log, and now we want to use the logback for the actual log output without changing the existing code.

Used jar package:

  • log4j

Use Cases:

private static final Logger logger=Logger.getLogger(Log4jTest.class);

public static void main(String[] args){
	if(logger.isInfoEnabled()){
		logger.info("log4j info message");
	}
}

The above Logger is log4j1's own org.apache.log4j.Logger. In the above code, we are using the log4j1 API for programming

Now how to make the above log output output through logback?

Just replace the jar package:

  • Step 1: Remove the log4j jar package

  • Step 2: Add the following jar package

    • log4j-over-slf4j (to switch from log4j1 to slf4j)
    • slf4j-api
    • logback-core
    • logback-classic
  • Step 3: Add the logback configuration file to the classpath

What is the principle?

###4.1.2 Switching principle

Take a look at log4j-over-slf4j to see at a glance:

log4j to slf4j

We can see that this is actually a simplified and modified version of log4j. Remove the native jar package of log4j1 and replace it with the simplified and modified version of the jar package (which can achieve seamless migration).

However, the implementation of Logger in the simplified version is different from that in the native version. The implementation of Logger in the simplified version is as follows (inheriting Category):

public class Category {
    private String name;
    protected org.slf4j.Logger slf4jLogger;
    private org.slf4j.spi.LocationAwareLogger locationAwareLogger;

    Category(String name) {
        this.name = name;
        slf4jLogger = LoggerFactory.getLogger(name);
        if (slf4jLogger instanceof LocationAwareLogger) {
            locationAwareLogger = (LocationAwareLogger) slf4jLogger;
        }
    }
}

As can be seen from the above, the Logger in the simplified version is generated by the API of slf4j, so the simplified version of the Logger we use will be delegated to slf4j for output. Since there is logback-classic in the current classpath, slf4j will choose logback for output. Thus, the log switching from log4j to logback is realized.

The following content only explains the switch from the log system to slf4j, and no longer explains which log slf4j chooses to output

##4.2 jdk-logging seamlessly switches to logback

###4.2.1 Case

private static final Logger logger=Logger.getLogger(JulSlf4jLog4jTest.class.getName());

public static void main(String[] args){
	logger.log(Level.INFO,"jul info a msg");
	logger.log(Level.WARNING,"jul waring a msg");
}

It can be seen that the above is programmed using the API that comes with jdk-logging, and now we want to hand over these logs to logback for output

The solution is as follows:

  • Step 1: Add the following jar package:

    • jul-to-slf4j (implement jdk-logging switch to slf4j)
    • slf4j-api
    • logback-core
    • logback-classic
  • Step 2: Add the logback configuration file to the classpath

  • Step 3: Add the following code to the code:

    static{
    	SLF4JBridgeHandler.install();
    }
    

###4.2.2 Switching principle

Let's take a look at the contents of the jul-to-slf4j jar package:

jul switch to slf4j

We see only one class: SLF4JBridgeHandler

It inherits the java.util.logging.Handler defined in jdk-logging. Handler is a processor in jdk-logging's log processing process (I haven't studied it carefully). Before using it, it must be registered in advance. Handler, that is, the above SLF4JBridgeHandler.install() operation, after install, we can implement log switching through this handler, as follows:

protected Logger getSLF4JLogger(LogRecord record) {
    String name = record.getLoggerName();
    if (name == null) {
        name = UNKNOWN_LOGGER_NAME;
    }
    return LoggerFactory.getLogger(name);
}

In the process of processing logs, the native LoggerFactory of slf4j is used to obtain a Logger defined by slf4j for log output.

And slf4j will choose logback for the actual log output

##4.3 commons-logging switch to logback

###4.3.1 Use Cases

jar package used

  • commons-logging

The case is as follows:

private static Log logger=LogFactory.getLog(JulJclTest.class);

public static void main(String[] args){
	if(logger.isTraceEnabled()){
		logger.trace("commons-logging-jcl trace message");
	}
}	

It can be seen that we use the commons-logging API to perform log programming operations, and now we want to switch to logback for log output (this is actually the integration of commons-logging and logback)

The solution is as follows:

  • The first step: remove the commons-logging jar package (in fact, it doesn't matter if you go or not)

  • Step 2: Add the following jar package:

    • jcl-over-slf4j (implement commons-logging switch to slf4j)
    • slf4j-api
    • logback-core
    • logback-classic
  • Step 3: Add the logback configuration file to the classpath

###4.3.2 Switching principle

This principle has been said before, you can see the integration of commons-logging and logback

That is, commons-logging selects slf4j as the underlying log output object through jcl-over-slf4j, and slf4j selects logback as the underlying log output object.

##4.4 Commonly used log scene switching explanation

The principle of log switching is explained above, and the following will be applied for specific examples.

Let's take a look at the official picture of slf4j:

Switch between log systems

The three cases are described in detail below.

###4.4.1 Top left picture

  • status quo:

    The current application has used the following promiscuous APIs to program logs:

    • commons-logging
    • log4j1
    • jdk-logging

    Now I want to unify the output of the log to logback

  • Solution:

    • Step 1: Switch all the above log systems seamlessly to slf4j first

      • Remove commons-logging (in fact, you can go or not), use jcl-over-slf4j to switch the underlying log output of commons-logging to slf4j
      • Remove log4j1 (must be removed), use log4j-over-slf4j, switch the log output of log4j1 to slf4j
      • Use jul-to-slf4j to switch jul's log output to slf4j
    • Step 2: Make slf4j select logback as the underlying log output

    Add the following jar packages:

    • slf4j-api
    • logback-core
    • logback-classic

The 2 images below are similar to the above

###4.4.2 Top right picture

  • status quo:

    The current application has used the following promiscuous APIs to program logs:

    • commons-logging
    • jdk-logging

    Now I want to unify the output of the log to log4j1

  • Solution:

    • Step 1: Switch all the above log systems seamlessly to slf4j first

      • Remove commons-logging (in fact, you can go or not), use jcl-over-slf4j to switch the underlying log output of commons-logging to slf4j
      • Use jul-to-slf4j to switch jul's log output to slf4j
    • Step 2: Make slf4j select log4j1 as the underlying log output

    Add the following jar packages:

    • slf4j-api
    • log4j
    • slf4j-log4j12 (integrated package)

###4.4.3 Bottom left

  • status quo:

    The current application has used the following promiscuous APIs to program logs:

    • commons-logging
    • log4j

    Now I want to unify the output of the log to jdk-logging

  • Solution:

    • Step 1: Switch all the above log systems seamlessly to slf4j first

      • Remove commons-logging (in fact, you can go or not), use jcl-over-slf4j to switch the underlying log output of commons-logging to slf4j
      • Remove log4j1 (must be removed), use log4j-over-slf4j, switch the log output of log4j1 to slf4j
    • Step 2: Make slf4j select jdk-logging as the underlying log output

    Add the following jar packages:

    • slf4j-api
    • slf4j-jdk14 (integrated package)

#5 Conflict Description

Still the content here is the conflict description of the slf4j official website

In fact, it is easy to understand the function of each jar package introduced above.

##5.1 jcl-over-slf4j conflicts with slf4j-jcl

  • jcl-over-slf4j: commons-logging switched to slf4j

  • slf4j-jcl : slf4j switches to commons-logging

If the two coexist, it will inevitably lead to mutual delegation, resulting in memory overflow

##5.2 log4j-over-slf4j conflicts with slf4j-log4j12

  • log4j-over-slf4j: log4j1 switches to slf4j
  • slf4j-log4j12 : slf4j switches to log4j1

If the two coexist, it will inevitably lead to mutual delegation, resulting in memory overflow. But log4j-over-slf4 makes a judgment internally to prevent memory overflow:

That is to judge whether the org.slf4j.impl.Log4jLoggerFactory in the slf4j-log4j12 jar package exists. If it exists, it means that there is a conflict, and an exception is thrown to prompt the user to remove the corresponding jar package. The code is as follows, in the org. In apache.log4j.Log4jLoggerFactory:

slf4j-log4j12 conflict prevention strategy

##5.3 jul-to-slf4j conflicts with slf4j-jdk14

  • jul-to-slf4j: jdk-logging switches to slf4j
  • slf4j-jdk14 : slf4j switches to jdk-logging

If the two coexist, it will inevitably lead to mutual delegation, resulting in memory overflow

#6 Conclusion

At this point, this log series is finally complete. It focuses on the interaction and integration between log systems, so if you want to study the architecture of a single log system in depth, you need to do in-depth research on your own.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325771958&siteId=291194637