Detailed explanation of common Java log frameworks

Posted by theelectricwiz on Tue, 08 Feb 2022 08:16:45 +0100

In Java development, common logging frameworks include JDKLog, Log4J, LogBack, SLF4J and SLF4J. These logging frameworks have their own characteristics and application scenarios. Understanding the characteristics and application scenarios of these frameworks is helpful for us to make correct judgment when making technology selection.

JDKLog: log knife

JDKLog is a log recording method officially provided by JDK, which can be used directly in JDK.

import java.util.logging.Logger;

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

The advantage of JDKLog is that it is very simple to use and can be used directly in JDK. However, the JDKLog function is too simple, does not support placeholder display, and has poor expansibility, so few people use it now.

Log4J: log cannon

Log4J is a log open source framework of Apache. It has multiple levels of logging (DEBUG/INFO/WARN/ERROR). It can record logs of different log levels separately, which greatly facilitates the viewing of logs.

Log4J has 1 Version x and 2 X version, now officially recommended to use 2 Version x, 2 Version x has made some upgrades in the architecture and some changes in the configuration file. But fortunately, the official configuration description document is very clear, and most problems can be solved by consulting the document.

Remarks: log4j1 Version x has stopped maintenance (August 2015)

Use log4j2 X step summary:

First: use log4j2 The X framework first needs to introduce dependent packages:

<!-- Log4J -->  
<dependency>  
    <groupId>org.apache.logging.log4j</groupId>  
    <artifactId>log4j-api</artifactId>  
    <version>2.6.2</version>  
</dependency>  
<dependency>  
    <groupId>org.apache.logging.log4j</groupId>  
    <artifactId>log4j-core</artifactId>  
    <version>2.6.2</version>  
</dependency>  

Second: add the configuration file log4j2 XML is placed in the resource directory:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Note: the level attribute of the node indicates the lowest level of output.

Third: write test classes

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/****
 ** Log4J Demo
 **/
public class Log4jLog {
	public static void main(String args[]) {
		Logger logger = LogManager.getLogger(Log4jLog.class);
		logger.debug("Debug Level");
		logger.info("Info Level");
		logger.warn("Warn Level");
		logger.error("Error Level");
	}
}

Run test class output results:

10:16:08.279 [main] INFO com.chanshuyi.Log4jLog - Info Level
10:16:08.280 [main] WARN com.chanshuyi.Log4jLog - Warn Level
10:16:08.280 [main] ERROR com.chanshuyi.Log4jLog - Error Level

Note: if LOG4J2 is not configured XML configuration file, then LOG4J will automatically enable a configuration file similar to the following

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="error">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Use the log4J2 default configuration file to output the test results

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
11:40:07.377 [main] ERROR com.chanshuyi.Log4jLog - Error Level

Log4J2.x # defect supplement

Log4J2.x itself has some disadvantages, such as not supporting the use of placeholders and not conducive to code reading. But compared with JDKLog, log4j 1 X can be said to be a very good logging framework

 

LogBack: log rocket

LogBack is actually an evolutionary version of log4j, because they are both open source log components designed by the same person (Ceki G ü lc ü). In addition to all the advantages of log4j, LogBack also solves the problem that log4j cannot use placeholders.

Summary of using back log:

First: to use the LogBack framework, you first need to introduce dependent packages:

<!-- LogBack -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.7</version>
</dependency>

Second: configure logback XML configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>
    <logger name="com.chanshuyi" level="TRACE"/>
    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

Note: the log level of LogBack can be subdivided into classes or packages, which can make logging more flexible. Introduce the Logger class into the following class file and log.

Third: write test classes

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

/****
 ** LogBack Demo
 **/
public class LogBack {
	static final Logger logger = LoggerFactory.getLogger(LogBack.class);

	public static void main(String[] args) {
		logger.trace("Trace Level.");
		logger.debug("Debug Level.");
		logger.info("Info Level.");
		logger.warn("Warn Level.");
		logger.error("Error Level.");
	}
}

Run test class output results:

14:34:45.747 [main] TRACE com.chanshuyi.LogBack - Trace Level.
14:34:45.749 [main] DEBUG com.chanshuyi.LogBack - Debug Level.
14:34:45.749 [main] INFO com.chanshuyi.LogBack - Info Level.
14:34:45.749 [main] WARN com.chanshuyi.LogBack - Warn Level.
14:34:45.749 [main] ERROR com.chanshuyi.LogBack - Error Level.

LogBack advantages and disadvantages supplement

LogBack solves the problem that Log4J cannot use placeholders, which makes it very convenient to read log code. In addition, LogBack has faster running speed and better internal implementation than Log4J. In addition, SLF4J is integrated in LogBack, which can realize some log recording more natively.

SLF4J: adapter

JDKLog, Log4J and LogBack, which are commonly used logging frameworks, have their own advantages and disadvantages and are suitable for use in different scenarios. But the actual situation of the project is: simple projects can directly use JDKLog, while complex projects need Log4J. Many times, our projects are from simple to complex, that is, we are likely to use JDKLog at the beginning. Later, when the business is complex, we need to use Log4J. At this time, how can we output the originally written logs with the new log framework?

Solution 1:

One of the most rigid methods is to modify the code line by line. All the log codes previously used in JDKLog are modified into the log interface of Log4J. But this way is not only inefficient, but also does repetitive work. How can we bear it.

Solution 2:

Because in the actual project application, sometimes there may be the need to switch from one logging framework to another. At this time, it is often necessary to make great changes in the code. In order to avoid changing the code when switching logging components, a thing called SLF4J (Simple Logging Facade for Java, that is, java simple logging interface set) appears.

SLF4J (Simple Logging Facade for Java, i.e. java simple logging interface set) is a logging interface specification. It provides users with a unified logging interface and shields the differences of different logging components. In this way, we only need to look at the interface document SLF4J when writing code, and we don't need to pay attention to the differences between different frameworks. When we need to replace the log component, we only need to replace a specific log component Jar package.

SLF4J and log framework (JDKLog, LOG4J, LogBack) integration summary

SLF4J+JDKLog

First: import the following dependent packages into Maven

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.7.21</version>
</dependency>

Second: write test classes

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

/****
 ** SLF4J + JDKLog
 **/
public class Slf4jJDKLog {
	final static Logger logger = LoggerFactory.getLogger(Slf4jJDKLog.class);

	public static void main(String[] args) {
		logger.trace("Trace Level.");
		logger.info("Info Level.");
		logger.warn("Warn Level.");
		logger.error("Error Level.");
	}
}

Third: output of test results

July 15, 2021 3:30:02 afternoon com.chanshuyi.slf4j.Slf4jJDKLog main
 information: Info Level.
July 15, 2021 3:30:02 afternoon com.chanshuyi.slf4j.Slf4jJDKLog main
 warning: Warn Level.
July 15, 2021 3:30:02 afternoon com.chanshuyi.slf4j.Slf4jJDKLog main
 serious: Error Level.

SLF4J+LOG4J

First: add the following dependent jar packages (slf4j-api.jar, slf4j-412.jar, log4j.jar) to Maven

<!-- 2.SLF4J + Log4J -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

Second: configure log4j configuration file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' >
    <appender name="myConsole" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                value="[%d{dd HH:mm:ss,SSS} %-5p] [%t] %c{2} - %m%n" />
        </layout>
        <!--Filter sets the level of output-->
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="levelMin" value="debug" />
            <param name="levelMax" value="error" />
            <param name="AcceptOnMatch" value="true" />
        </filter>
    </appender>
    <!-- root logger Settings for-->
    <root>
        <priority value ="debug"/>
        <appender-ref ref="myConsole"/>
    </root>
</log4j:configuration>

Still use the above test class without modification. Output console test results

[15 16:04:06,371 DEBUG] [main] slf4j.SLF4JLog - Debug Level.
[15 16:04:06,371 INFO ] [main] slf4j.SLF4JLog - Info Level.
[15 16:04:06,371 WARN ] [main] slf4j.SLF4JLog - Warn Level.
[15 16:04:06,371 ERROR] [main] slf4j.SLF4JLog - Error Level.

SLF4J+LogBack

First: import the following dependent packages into Maven

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.7</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.1.7</version>
</dependency>

Second: configure logback XML file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>
    <logger name="com.chanshuyi" level="TRACE"/>
    <root level="warn">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

Still use the above test class without modification. Output console test results

16:08:01.040 [main] TRACE com.chanshuyi.slf4j.SLF4JLog - Trace Level.
16:08:01.042 [main] DEBUG com.chanshuyi.slf4j.SLF4JLog - Debug Level.
16:08:01.043 [main] INFO com.chanshuyi.slf4j.SLF4JLog - Info Level.
16:08:01.043 [main] WARN com.chanshuyi.slf4j.SLF4JLog - Warn Level.
16:08:01.043 [main] ERROR com.chanshuyi.slf4j.SLF4JLog - Error Level.

LogBack log framework

At present, the most streaming log framework solution is SLF4J + LogBack. The reasons are as follows:

LogBack itself implements the log interface of SLF4J, and SLF4J is not required to make further adaptation.

LogBack itself is optimized on the basis of log4j, and its running speed and efficiency are higher than log4j.

SLF4J + LogBack supports placeholders to facilitate the reading of log codes, while LOG4J does not.

LogBack log framework component description

LogBack is divided into three components: LogBack core, LogBack classic and LogBack access.

LogBack core provides the core functions of LogBack and is the basis of the other two components.

Logback classic implements the API of SLF4J, so when you want to use it with SLF4J, you need to introduce logback classic into the dependency.

Logback access is prepared to integrate the Servlet environment. It can provide the log interface of HTTP access.

The logging data flow of LogBack is from Class (Package) to Logger, then from Logger to Appender, and finally from Appender to specific output terminal.

LogBack log framework configuration file description

The LogBack Configuration file can be divided into several nodes, in which Configuration is the Root node and Appender, Logger and Root are the child nodes of Configuration.

Appender node: it is the child node of the. It is the component responsible for writing logs. Appender has two necessary attributes: name and class. Name specifies the name of the appender, class specifies the fully qualified name of the appender, class, mainly including:
ch.qos.logback.core.ConsoleAppender console output
ch.qos.logback.core.FileAppender file output
ch.qos.logback.core.RollingFileAppender file scrolling output

Example:

<?xml version="1.0" encoding="utf-8"?>
<configuration debug="true" scan="true" scanPeriod="2">
    <!-- conf consoel out -->
    <appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
    </appender>
    <!-- conf file out -->
    <appender name="file_out" class="ch.qos.logback.core.FileAppender">
    </appender>
    <!-- conf file out -->
    <appender name="file_out" class="ch.qos.logback.core.RollingFileAppender">
    </appender>
    <root></root>
    <logger></logger>
</configuration>

ConsoleAppender: add logs to the console. There are the following nodes:

< encoder >: format the log.

< target >: string system Out or system Err, default system out;

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!-- conf consoel out -->
    <appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date [%thread] %-5level %logger - %message%newline</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="console_out" />
    </root>
</configuration>

FileAppender: add the log to the file. There are the following nodes:

< File >: the file name to be written can be a relative directory or an absolute directory. If the directory does not exist, it will be created automatically.

< append >: if true, the log will be appended to the end of the file. If false, the existing file will be cleared. The default is true.

< encoder >: format the log [please refer to the official website for specific description of conversion characters.]

Example:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <appender name="file_out" class="ch.qos.logback.core.FileAppender">
        <file>logs/debug.log</file>
        <encoder>
            <pattern>%date [%thread] %-5level %logger - %message%newline</pattern>
        </encoder>
    </appender>
</configuration>

rollingFileAppender

Rolling record file: first record the log to the specified file. When certain conditions are met, record the log to other files. There are the following nodes:
< File >: the file name to be written can be a relative directory or a directory. If the directory does not exist, it will be created automatically.
< append >: if true, the log will be appended to the end of the file. If false, the existing file will be cleared. The default is true.
< encoder >: format the log.
< rollingpolicy >: determines the behavior of RollingFileAppender when scrolling occurs, involving file movement and renaming.
rollingPolicy
TimeBaseRollingPolicy: the most commonly used rollingpolicy. The rollingpolicy is formulated according to the time, that is, it is responsible for scrolling and triggering scrolling. There are the following nodes:;
< filenamepattern >: necessary nodes, including files and "% d" converter, ""% d "can contain a Java text. The time format specified by simpledateformat, such as:% d {yyyy MM}. If% d is used directly, the default format is yyyy - MM - dd.
< maxhistory >: optional node, which controls the maximum number of archived files to be retained. If the number exceeds, the old files will be deleted. Assuming that it is set to scroll every month and is 6, only the files in the last 6 months will be saved and the old files before will be deleted. Note: the directories created for filing will also be deleted.
< filenamepattern >: must contain "% I". For example, set the minimum value and maximum value to 1 and 2 respectively, and the naming mode is log%i.log, which will generate the archive file Log1 Log and log2 Log, you can also specify file compression options, for example: log%i.log GZ or log%i.log zip
Triggingpolicy: tell RollingFileAppender to activate RollingFileAppender scrolling.

Example:

<!-- 03:conf errorAppender out -->
<appender name="errorAppender" class="ch.qos.logback.core.RollingFileAppender">
    <file>logs/error.log</file>
    <!-- Set scrolling policy -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--Set log naming mode-->
        <fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!--Up to 30 days log-->
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <!-- Over 150 MB Trigger scrolling strategy when -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>
    
    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>

logger node
logger is a child node of to set the log printing level of a package or a specific class, and specify. logger has only one name attribute and two optional attributes level / addtivity.
name: used to specify a package or a specific class constrained by this logger.
Level: used to set the printing level, regardless of case. The optional values are TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF. There is also a special value of INHERITED or the synonym NULL, which represents the level at which the superior is enforced. If this property is not set, the current logger will inherit the level of the parent.
addtivity: whether to pass print information to the superior logger. The default value is true;
It can contain zero or more elements, indicating that this appender will be added to the logger.

Example:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <!-- Filter out non INFO level -->
        <level>INFO</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
        </filter>
</appender>

<!-- conf infoAppender out -->
<appender name="infoAppender" class="ch.qos.logback.core.RollingFileAppender">
    <file>logs/info.log</file>
    <!-- Set scrolling policy -->
    <rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--Set log naming mode-->
        <fileNamePattern>infoFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!--Up to 30 days log-->
        <maxHistory>30</maxHistory>
    </rollingPoliy>
    <!-- Over 150 MB Trigger scrolling strategy when -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>

    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>

<!-- Add two appender node -->
<logger name="logback.olf.log" level="info">
    <appender-ref ref = "console_out"/>
    <appender-ref ref = "infoAppender"/>
</logger>
</configuration>

root node
Element to configure the root logger. This element has a level attribute and no name attribute because it has been named root. The value of the level property is case independent. Its value is one of the following strings: TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF. If the root element does not reference any Appenders, ALL Appenders will be lost.

Example:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- conf consoel out -->
<appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <!-- Filter out non INFO level -->
        <level>INFO</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>

<!-- 01:conf infoAppender out -->
<appender name="infoAppender" class="ch.qos.logback.core.RollingFileAppender">
    <file>logs/info.log</file>
    <!-- Set scrolling policy -->
    <rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--Set log naming mode-->
        <fileNamePattern>infoFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!--Up to 30 days log-->
        <maxHistory>30</maxHistory>
    </rollingPoliy>

    <!-- Over 150 MB Trigger scrolling strategy when -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>

    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>

<!-- 02:conf debugAppender out -->
<appender name="debugAppender" class="ch.qos.logback.core.RollingFileAppender">
    <file>logs/debug.log</file>
    <!-- Set scrolling policy -->
    <rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--Set log naming mode-->
        <fileNamePattern>debugFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!--Up to 30 days log-->
        <maxHistory>30</maxHistory>
    </rollingPoliy>

    <!-- Over 150 MB Trigger scrolling strategy when -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>

    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>

<!-- 03:conf errorAppender out -->
<appender name="errorAppender" class="ch.qos.logback.core.RollingFileAppender">
    <file>logs/error.log</file>
    <!-- Set scrolling policy -->
    <rollingPoliy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--Set log naming mode-->
        <fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!--Up to 30 days log-->
        <maxHistory>30</maxHistory>
    </rollingPoliy>

    <!-- Over 150 MB Trigger scrolling strategy when -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>

    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>

<root level="ALL">
    <appender-ref ref="infoAppender"/>
    <appender-ref ref="debugAppender"/>
    <appender-ref ref="errorAppender"/>
</root>
</configuration>

Filter filter node
Level filter
LevelFilter filters recorded events according to the record level. If the level of the event is equal to the configured level, the filter accepts or rejects the event according to the onMatch and onMismatch properties.

Example:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!-- conf consoel out -->
    <appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- Filter out non INFO level -->
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="console_out" />
    </root>
</configuration>

Threshold filter
ThresholdFilter filters out events below the specified threshold.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!-- conf consoel out -->
    <appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- Filter out TRACE and DEBUG Level log -->
            <level>INFO</level>
        </filter>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
         </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="console_out" />
    </root>
</configuration>

Evaluator filter
Evaluate whether the specified conditions are met

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!-- conf consoel out -->
    <appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.EvaluatorFilter">
            <evaluator>
                <!--Filter out all logs that do not contain hello Character log-->
                <expression>
                    message.contains("hello")
                </expression>
                <onMatch>NEUTRAL</onMatch>
                <onMismatch>DENY</onMismatch>
            </evaluator>
        </filter>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="console_out" />
    </root>
</configuration>

Matchers

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <!-- conf consoel out -->
    <appender name ="console_out" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.EvaluatorFilter">
            <evaluator>
                <matcher>
                    <Name>odd</Name>
                    <!-- Filter out statements with odd sequence numbers-->
                    <regex>statement [13579]</regex>
                </matcher>
                <expression>odd.matches(formattedMessage)</expression>
                <onMatch>NEUTRAL</onMatch>
                <onMismatch>DENY</onMismatch>
            </evaluator>
        </filter>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="console_out" />
    </root>
</configuration>

The following is my common log XML configuration file for your reference:

<?xml version="1.0" encoding="UTF-8"?> 
  
<!-- From high to low OFF , FATAL , ERROR , WARN , INFO , DEBUG , TRACE , ALL -->  
<!-- The log output rule is based on the current ROOT Level. When the log is output, the level is higher than root The default level is output -->  
<!-- For each of the following configurations filter If you filter out the output file, high-level files will appear, and low-level log information will still appear filter Filtering only records logs at this level-->  
  
  
<!-- Attribute description scan: Security is set to true If the configuration file changes, it will be reloaded. The default value is true scanPeriod:Set the time interval for monitoring whether the configuration file is modified. If the time unit is not given,
The default unit is milliseconds. When scan by true This property takes effect when. The default interval is 1 minute.   
    debug:When this property is set to true When, it will be printed out logback Internal log information, real-time viewing logback Operation status. The default value is false.  -->  
<configuration>  
    <!-- Define log file input location -->  
    <property name="log_dir" value="/logs/ucas" />  
    <!-- The maximum history of the log is 30 days -->  
    <property name="maxHistory" value="30"/>  
  
  
    <!-- ConsoleAppender Console output log -->  
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">  
        <!-- Format the log -->  
        <encoder>  
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n</pattern>  
        </encoder>  
    </appender>  
      
      
    <!-- ERROR Level log -->  
    <!-- Rolling record file: first record the log to the specified file. When a certain condition is met, record the log to other files RollingFileAppender-->  
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">  
        <!-- Filter, record only WARN Level log -->  
        <filter class="ch.qos.logback.classic.filter.LevelFilter">  
            <level>ERROR</level>  
            <onMatch>ACCEPT</onMatch>  
            <onMismatch>DENY</onMismatch>  
        </filter>  
        <!-- The most commonly used rolling strategy, which formulates the rolling strategy according to time.Responsible for both rolling and departure rolling -->  
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <!--Log output locations can be relative, and absolute paths -->  
            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/biz-error-log.log</fileNamePattern>  
            <!-- Optional node, which controls the maximum number of archived files to be retained. If the number exceeds, the old files will be deleted. It is assumed that the setting is rolling every month, and<maxHistory>It's 6,  
            Only the files of the last 6 months are saved, and the old files before are deleted. Note that deleting old files means that directories created for archiving will also be deleted-->  
            <maxHistory>${maxHistory}</maxHistory>  
        </rollingPolicy>  
                  
        <encoder>  
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  
        </encoder>  
    </appender>  
      
      
    <!-- WARN Level log appender -->  
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">  
        <!-- Filter, record only WARN Level log -->  
        <filter class="ch.qos.logback.classic.filter.LevelFilter">  
            <level>WARN</level>  
            <onMatch>ACCEPT</onMatch>  
            <onMismatch>DENY</onMismatch>  
        </filter>  
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/biz-warn-log.log  
            </fileNamePattern>  
            <maxHistory>${maxHistory}</maxHistory>  
        </rollingPolicy>  
        <encoder>  
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  
        </encoder>  
    </appender>  
      
      
    <!-- INFO Level log appender -->  
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">  
        <!-- Filter, record only INFO Level log -->  
        <filter class="ch.qos.logback.classic.filter.LevelFilter">  
            <level>INFO</level>  
            <onMatch>ACCEPT</onMatch>  
            <onMismatch>DENY</onMismatch>  
        </filter>  
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/biz-info-log.log  
            </fileNamePattern>  
            <maxHistory>${maxHistory}</maxHistory>  
        </rollingPolicy>  
        <encoder>  
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  
        </encoder>  
    </appender>  
      
      
    <!-- DEBUG Level log appender -->  
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">  
        <filter class="ch.qos.logback.classic.filter.LevelFilter">  
            <level>DEBUG</level>  
            <onMatch>ACCEPT</onMatch>  
            <onMismatch>DENY</onMismatch>  
        </filter>  
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/biz-debug-log.log  
            </fileNamePattern>  
            <maxHistory>${maxHistory}</maxHistory>  
        </rollingPolicy>  
        <encoder>  
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  
        </encoder>  
    </appender>  
    
    <logger name="org.springframework.web" value="DEBUG"/>
    <logger name="com.digipower" value="DEBUG"/>
    <logger name="org.apache.commons.digester" value="DEBUG" />
		
      
    <!-- root Level potential error log level -->  
    <root level="WARN">  
        <!-- console output  -->  
        <appender-ref ref="STDOUT" />  
        <!-- File output -->  
        <appender-ref ref="ERROR" />  
        <appender-ref ref="INFO" />  
        <appender-ref ref="WARN" />  
        <appender-ref ref="DEBUG" />  
    </root>  
</configuration>

How to perform log system conversion?

In the actual log conversion process, SLF4J actually acts as an intermediary. For example, when we use LOG4J to log a project, we need to change LogBack to log.
At this time, we need to convert LOG4J into SLF4J log system, and then from SLF4J log system to LogBack log system.

Shift from log frame to SLF4J
jul-to-slf4j: bridge from JDK logging to slf4j
Log4j over slf4j: bridge from log4j1 to slf4j
JCL over slf4j: the bridge from commons logging to slf4j
Shift from SLF4J to specific log framework
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: slf4j the bridge to logback
Slf4j JCL: the bridge from slf4j to commons logging

Project example: at the beginning, we used Log4J logging framework. Now we want to switch to LogBack framework, so we first need to add Log4J-over-SLF4J Jar converts Log4J to SLF4J, and then adds LogBack classic Jar converts SLF4J to LogBack.

List of log technology framework
JUL: the logging tool in JDK, also known as JDKLog and JDK logging.
LOG4J1: a specific log implementation framework.
LOG4J2: a specific log implementation framework, which is the next version of LOG4J1.
Logpack: a specific log implementation framework, but its performance is better.
JCL: a log facade that provides a unified logging interface, also commonly known as common logging.
SLF4J: a log facade. Like JCL, it provides a unified log recording interface, which can be easily switched to see the specific implementation framework.
JUL, LOG4J1, LOG4J2 and logpack are the log implementation framework, while JCL and SLF4J are the log implementation facade