Java log --slf4j-- usage / tutorial / example

Original website:

brief introduction

explain

         This article introduces the usage of slf4j this logging framework in Java with examples. It will also introduce relevant knowledge.

Official website

Official website: SLF4J
Official website documents: SLF4J Documentation

slf4j introduction

summary

explain

term

explain

Noun interpretation

Slf4j: simple log facade for Java.

effect

Similar to the adapter, you can print directly using the slf4j method, and eventually call the specific log, such as java.util.logging, logback and log4j.

advantage

After the system changes a log source, there is no need to change the code; Save memory (you can use placeholder {}).

Configuration method

The log format, recording level and output mode are realized through the configuration of the specific log system.

Supported logging systems

NOP, Simple,log4j, log4j2, java.util.logging, JCL and logback.

Timing of binding log implementation library

Bind the real Log library statically at compile time

Method of switching log system

Just switch the jar package. For example, switch from java.util.logging to log4j, and just replace slf4j-jdk14-xxx.jar with slf4j-log4j12-xxx.jar.

Differences between slf4j and Commons logging

term

slf4j

commons-logging

Timing of binding log implementation library

Bind the real Log library statically at compile time.

Available in OSGI

Dynamic search mechanism to automatically find out the real log library when the program is running.

It uses ClassLoader to find and load log libraries, which makes frameworks like OSGI unable to work normally, because different OSGI plug-ins use their own ClassLoader (this mechanism of OSGI ensures that plug-ins are independent of each other).

placeholder

You can use placeholder '{}'

Placeholders are not available

Placeholder for slf4j

Other web sites

Advantages and application principle of slf4j_ Java_winwill2012 blog - CSDN blog

General log usage (take log4j as an example)

java file

import org.apache.log4j.Logger;

public class TestLog4j {
    private static final Logger LOGGER = Logger.getLogger(TestLog4j.class);

    public static void main(String[] args) {
        String message = "Hello World.";
        LOGGER.info("This is a test message: " + message);
    }
}

Disadvantages of this method

1. String addition is a performance consuming operation
2. If the output level of log4j configuration is ERROR, it will not output at all and occupy memory.

The solution to the second disadvantage: add judgment, but it will make the code cumbersome. For example:

	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("This is a test message: " + message);
	}

The {} placeholder method for slf4j

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestLog4j {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestLog4j.class);

    public static void main(String[] args) {
        String message = "Hello World.";
        LOGGER.info("This is a test message: {}", message);
    }
}

        The {} placeholder is used, and there will be no string splicing operation.
         Before producing the string of the final log information, this method will check whether a specific log level is turned on, which not only reduces the memory consumption, but also reduces the CPU time to process the string connection command in advance.

Related source code: slf4j-log4j12-1.6.1. Jar = > log4jloggeradapter

public void debug(String format, Object arg1, Object arg2) {
    if (logger.isDebugEnabled()) {
        FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
        logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
}

slf4j's package

In the following table, you only need to specify bold dependencies, which will automatically pull other dependencies. You can also force other dependencies to a certain version. Just put other dependencies behind bold dependencies.

package

meaning

Required dependencies

slf4j-api-xxx.jar

slf4j core interface package

slf4j-simple-xxx.jar

slf4jSimpleLogger log implementation package

slf4j-api-xxx.jar=>  slf4j-simple-xxx.jar

slf4j-log4j12-xxx.jar

slf4j calls the 1.2 implementation package of log4j

slf4j-api-xxx.jar=>   Slf4j-log4j12-xxx. Jar = > log4j-xxx.jar (version 1.2)

slf4j-log4j13-xxx.jar

slf4j calls the 1.3 implementation package of log4j

slf4j-jdk14-xxx.jar

slf4j calls the implementation package of java.util.logging of JDK (only available after jdk1.4)

slf4j-api-xxx.jar=>  slf4j-jdk14-xxx.jar =>  java.util.logging

slf4j-nop-xxx.jar

slf4j calls nop (no printing)

slf4j-api-xxx.jar=>  slf4j-nop-xxx.jar =>  /dev/null

slf4j-migrator-xxx.jar

Help migrate your code to use SLF4J.

slf4j-ext-xxx.jar

jul-to-slf4j-xxx.jar

The original jul print code is delegated to slf4j

slf4j-api-xxx.jar=>   Jul-to-slf4j-xxx. Jar = > slf4j YYY (example: slf4j-simple-xxx.jar)

log4j-over-slf4j-xxx.jar

The original log4j code remains unchanged and is output using the slf4j interface

slf4j-api-xxx.jar=>   Log4j over slf4j XXX. Jar = > slf4j YYY (example: slf4j simple XXX. Jar)

jcl-over-slf4j-xxx.jar

The original jcl code remains unchanged and is output using the slf4j interface

slf4j-api-xxx.jar=>   Log4j over slf4j XXX. Jar = > slf4j YYY (example: slf4j simple XXX. Jar)

slf4j-jcl-xxx.jar

The original slf4j code remains unchanged, using jcl output

logback-classic-xxx.jar

Upgrade of log4j. Not provided by slf4j.

slf4j-api-xxx.jar=>  logback-classic-xxx.jar, logback-core-xxx.jar

logback naturally supports slf4j, so no connection layer is required

Call structure

Slf4j API (interface layer)  
         | 
The connection layer of each log implementation package (slf4j-jdk14, slf4j log4j, etc.)  
         | 
Each log implementation package (implementation layer)

Compatibility issues

1. The connection layer binds a specific implementation layer
         For example:   slf4j-jdk14.jar or   slf4j-log4j12.jar.

2. The version of interface layer and connection layer shall be the same
        Mixing different versions of slf4j API (interface layer) and connection layer bindings may cause problems. For example, slf4j api-1.7.19.jar corresponds to slf4j-simple-1.7.19.jar. Using slf4j-simple-1.5.5.jar will not work normally.

3. The client is compatible with any interface layer
         From the client's point of view, all versions of slf4j API are compatible. You can use any version of slf4j api.jar. As long as the second item is met, there will be no problem.

bridging

Other web sites

Official website: Bridging legacy APIs

brief introduction  

        If you are developing the components called by the application and have used JCL, some components may directly call java.util.logging. At this time, you need a bridge (named xxx-over/to-slf4j.jar) to redirect their log output to SLF4J.

        The bridge is a fake log implementation tool. For example, when jcl-over-slf4j.jar is put into CLASS_PATH, even if a component originally outputs logs through JCL, it will be "cheated" into SLF4J by jcl-over-slf4j, and then SLF4J will hand over the logs to the specific log implementation tool according to the binder. There are relevant routines below: Example 2 and example 3 below.

        What happens when log4j-over-slf4j.jar and slf4j-log4j12-version.jar are placed in the CLASS_PATH at the same time: the log will be kicked around and eventually enter an endless loop, resulting in memory overflow. This is also the case when other packets are forwarded to each other. (log4j-over-slf4j and slf4j-log4j12 are exceptions. log4j-over-slf4 makes an internal judgment to prevent memory overflow: judge whether org.slf4j.impl.Log4jLoggerFactory in slf4j-log4j12 jar package exists. If so, it indicates a conflict. Throw an exception and prompt the user to remove the corresponding jar package. The code is slf4j-log4j12-xxx. Jar = > org.apache.log4j.log4jloggerfac Store = > static field).

slf4j official map

Example

@Slf4j

        Each time you write a new class, you need to write: private static final Logger logger = = LoggerFactory.getLogger(Demo.class); concise method: use lombok's @ Slf4j.

step

1. Introduce lombok dependency

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

2. Write @ Slf4j on the class

3. Directly use the log variable

slf4j-simple

java file

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo {
    private static final Logger logger = = LoggerFactory.getLogger(Demo.class);
    public static void main(String[] args) {
        logger.info("Hello World");
    }
}

pom.xml

pom.xml(slf4j-simple)

       <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>

test

Compile and run the HelloWorld program. Now there will be the following output on the console:

[main] INFO org.example.a.Demo - Hello World

Note: if slf4j XXX is not configured (for example, dependency is not added), the following error will be reported.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Failure reason: the bound slf4j is not found under the class path

slf4j-log4j12

To provide the log4j.properties configuration file.

rely on

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.30</version>
    <scope>test</scope>
</dependency>

  The usage is the same as slf4j simple

jul to slf4j simple

Other web sites

Columns of SLF4j and common logging_java_xiaoxinxiao - CSDN blog

Before conversion: java.util.logging(jul) provided with jdk

java file

Use the java.util.logging(jul) that comes with the jdk.

package com.example;
 
import java.util.logging.Logger;
 
public class HelloWorld {
    private static final Logger logger = Logger.getLogger(HelloWorld.class.getName());
 
    public static void main(String[] args) {
        logger.severe("jul severe test");
        logger.warning("jul warning test");
        logger.info("jul info test");
    }
}

test

March 06, 2020 9:10:07 am com.example.HelloWorld main
Severe: jul severe test
March 06, 2020 9:10:07 am com.example.HelloWorld main
Warning: jul warning test
March 06, 2020 9:10:07 am com.example.HelloWorld main
Info: jul info test

After conversion: jul goes to slf4j simple

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>mytest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jul-to-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>
       <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>
    </dependencies>
</project>

java file

Add the following statements to the main function:

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();

java file after adding

package com.example;

import org.slf4j.bridge.SLF4JBridgeHandler;
import java.util.logging.Logger;

public class Demo {
    private static final Logger logger = Logger.getLogger(Demo.class.getName());

    public static void main(String[] args) {
        SLF4JBridgeHandler.removeHandlersForRootLogger();
        SLF4JBridgeHandler.install();

        logger.severe("jul severe test");
        logger.warning("jul warning test");
        logger.info("jul info test");
    }
}

test

[main] ERROR com.example.Demo - jul severe test
[main] WARN com.example.Demo - jul warning test
[main] INFO com.example.Demo - jul info test

jcl to slf4j

Before conversion: jcl

java program

package com.example;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
 
public class Demo {
	private final static Log logger = LogFactory.getLog(Demo .class);
 
	public static void main(String[] args) {
		logger.debug("DEBUG ...");
		logger.info("INFO ...");
		logger.error("ERROR ...");
	}
}

maven dependency

<dependency>
	<groupId>commons-logging</groupId>
	<artifactId>commons-logging</artifactId>
	<version>1.2</version>
</dependency>

configuration file

commons-logging.properties

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

test

[INFO] Demo - INFO ...
[ERROR] Demo - ERROR ...

After conversion: jcl to slf4j

Modify maven dependencies only

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>

test

[main] INFO com.example.Demo - INFO ...
[main] ERROR com.example.Demo - ERROR ...

Other web sites

slf4j package instructions -- ITeye blog
SLF4J user manual_ Java_ Goodidea CSDN blog
Relationship between log4j and Commons logging, slf4j - sxfans - ITeye blog

Keywords: Java slf4j

Added by B of W on Mon, 01 Nov 2021 12:58:32 +0200