Use logback to set the log level

Time:2021-12-5

Logback sets the log level

There are many articles describing how to set logs using logback. This article focuses on the differences and uses of different settings. First, list the three common methods, and then explain the differences.

Levelfilter in appender:

Level filter: filter according to the log level. If the log level is equal to the configuration level, the filter receives or rejects logs based on onmath and onmismatch


 <appender name="CONSOLE">   
   <filter>   
     <level>INFO</level>   
     <onMatch>ACCEPT</onMatch>   
     <onMismatch>DENY</onMismatch>   
   </filter>   
   ...
 </appender>   

Thresholdfilter in appender:

Threshold filter, which filters out logs below the specified threshold. When the log level is equal to or higher than the threshold, the filter returns neutral. It is different from levelfilter in that one is an interval and the other is a single point.

<appender name="CONSOLE"  >   
   <!--  Filter out trace and debug level logs -- >   
   <filter>   
     <level>INFO</level>   
   </filter>   
   ...
 </appender>

Level in logger:

It is used to set the log level of the specified name. If it is not set, the level of the parent class is used. The top-level parent class is root. It is generally used to adjust the log level of the specified class. The rule is that only logs equal to or higher than the set level can be output (note that it is possible, because it depends on the setting of the appender)


<logger level="TRACE" name="com.test.pk1"/>

How should the above be used and effective?

How to take effect: you can understand the log processing pipeline as follows:

Judge the level of the logger first. If it does not meet the requirements, it will be directly discarded and will not be printed. If it meets the requirements, go to the next step

1. Find the associated appender and filter the log according to the appender’s filter

2. How to apply: setting the log level through logger is common and easy to understand. Since you can control the log output by level through the level of logger, when will the appender filter be used?

The main application scenario is to save different files according to the log level. For example, if it is equal to or higher than the error level, save it to log_ The error.log file, equal to or higher than the warn level, is saved to log_ Warn.log file (deep research: why save different files according to levels? It is convenient to find problems, because the amount of debug level logs is often large in practical applications. By saving logs by levels, you can directly look at the error level logs and quickly find problems).

Example:


<appender name="WarnLogFile">
        ...
        <file>${LOGS_DIR}/log-warn.log</file>
        <filter>
            <level>WARN</level>
        </filter>
        ...
    </appender>
    
    <appender name="InfoLogFile">
        ...
        <file>${LOGS_DIR}/log-info.log</file>
        <filter>
            <level>INFO</level>
        </filter>
        ...
    </appender>
    
    <appender name="DebugLogFile">
        ...
        <file>${LOGS_DIR}/log-debug.log</file>
        <filter>
            <level>DEBUG</level>
        </filter>
        ...
    </appender>

Logback log – output by log level

I. Introduction to logback

Logback is another open source log component designed by the founder of log4j. The official website is: http://logback.qos.ch 。 It is currently divided into the following modules:

  • logback-core: the basic module of the other two modules
  • logback-classic: it is an improved version of log4j. At the same time, it fully implements the slf4j API, so that you can easily replace it with other logging systems, such as log4j or jdk14 logging
  • logback-access: the access module is integrated with the servlet container and provides the function of accessing logs through HTTP

II. Introduction to logback configuration

Logger, appender and layout

As a log recorder, logger is mainly used to store log objects after it is associated with the corresponding context of the application. It can also define log type and level.

Appender is mainly used to specify the destination of log output, which can be console, file, remote socket server, mysql, postresql, Oracle and other databases, JMS and remote UNIX syslog daemon.

Layout is responsible for converting events into strings and outputting formatted log information.

logger context

Each logger is associated to a loggercontext. Loggercontext is responsible for manufacturing loggers and arranging loggers in a tree structure. All other loggers are also obtained through the static method getlogger of the org.slf4j.loggerfactory class. The getlogger method takes the logger name as a parameter. Calling the loggerfactory.getlogger method with the same name will always get a reference to the same logger object.

Valid level and level inheritance

The logger can be assigned a level. Levels include trace, debug, info, warn and error, which are defined in the ch.qos.logback.classic.level class. If the logger is not assigned a level, it inherits the level from the nearest ancestor with the assigned level. The default level of root logger is debug.

Printing method and basic selection rules

The printing method determines the level of recording requests. For example, if l is a logger instance, the statement l.info (“…”) is a record statement with level info. When the level of the record request is higher than or equal to the valid level of its logger, it is called enabled; otherwise, it is called disabled. The record request level is p and the valid level of its logger is Q. only when p > = q, the request will be executed.

This rule is the core of logback. The level order is: trace < debug < info < warn < error

Log level output

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- Define the storage address of log files. Do not use relative paths in logback configuration -- >
    <property name="LOG_HOME" value="log"/>
    <property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{TRACE_ID}] %-5level %logger{20}[%L] - %msg%n"/>
    <!--  Console output -- >
    <appender name="STDOUT">
        <encoder>
            <!-- Formatted output:% d represents the date,% thread represents the thread name,% - 5level: the level displays 5 characters from the left, width% MSG: log message,% n is the newline character -- >
            <pattern>${PATTERN}</pattern>
            <!--  Set output character set encoding -- >
            <charset>UTF-8</charset>  
        </encoder>
    </appender>
    <!--  Generate log files per day -- >
    <appender name="FILE">
        <append>true</append>
        <rollingPolicy>
            <!-- File name of log file output -- >
            <FileNamePattern>${LOG_HOME}/log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!-- Log file retention days -- >
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder>
            <!-- Formatted output:% d represents the date,% thread represents the thread name,% - 5level: the level displays 5 characters from the left, width% MSG: log message,% n is the newline character -- >
            <pattern>${PATTERN}</pattern>
            <!--  Set output character set encoding -- >
            <charset>UTF-8</charset>  
        </encoder>
        <!-- Maximum log file size -- >
        <triggeringPolicy>
            <MaxFileSize>50MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!--  Error file output log -- >
    <appender name="ERROR_FILE">
        <File>${LOG_HOME}/log_error.log</File>
        <append>true</append>
        <prudent>false</prudent>
        <!--  Log file rolling policy -- >
        <rollingPolicy>
            <FileNamePattern>${LOG_HOME}/log_error_%d{yyyy-MM-dd}.log.gz</FileNamePattern>
            <!--  Number of days logs remain on disk -- >
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!--  Filter, only accept the logs of error level, and deny rejects other log levels -- >
        <filter>
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!--  Log output format -- >
        <encoder>
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>
    <!--  Info file output log -- >
    <appender name="INFO_FILE">
        <File>${LOG_HOME}/log_info.log</File>
        <append>true</append>
        <prudent>false</prudent>
        <!--  Log file rolling policy -- >
        <rollingPolicy>
            <FileNamePattern>${LOG_HOME}/log_info_%d{yyyy-MM-dd}.log.gz</FileNamePattern>
            <!--  Number of days logs remain on disk -- >
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!--  Filter, only accept the logs of error level, and deny rejects other log levels -- >
        <filter>
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!--  Log output format -- >
        <encoder>
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>
    <!--  Debug file output log -- >
    <appender name="DEBUG_FILE">
        <File>${LOG_HOME}/log_debug.log</File>
        <append>true</append>
        <prudent>false</prudent>
        <!--  Log file rolling policy -- >
        <rollingPolicy>
            <FileNamePattern>${LOG_HOME}/log_debug_%d{yyyy-MM-dd}.log.gz</FileNamePattern>
            <!--  Number of days logs remain on disk -- >
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!--  Filter, only accept the logs of error level, and deny rejects other log levels -- >
        <filter>
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!--  Log output format -- >
        <encoder>
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>
    <!--  Asynchronously output logs to disk files to avoid disk IO operations every time -- >
    <appender name="ASYNC">
        <discardingThreshold>0</discardingThreshold>
        <queueSize>10000</queueSize>
        <appender-ref ref="FILE" />
    </appender>
    <!--  Log output level -- >
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
<!--        <appender-ref ref="ASYNC"/>-->
<!--        <appender-ref ref="ERROR_FILE"/>-->
<!--        <appender-ref ref="INFO_FILE"/>-->
<!--        <appender-ref ref="DEBUG_FILE"/>-->
    </root>
</configuration>

The above is my personal experience. I hope I can give you a reference, and I hope you can support developpaer.