Previous article: Logging framework in the Java ecosystem

This chapter provides an example of configuring Logback

Introduction to the

Ceki Gulcu, an early author of Log4j, developed SLF4J(The Simple Logging Facade for Java) Facade framework in 2006 as JCL(Jakarta Commons Logging) More reliable alternatives to.

Then Ceki Gulcu developed a new generation of logging implementation framework Logback as the implementation of Slf4j.

And log base 4j2

Apache Log4j2 is an upgrade of Apache Log4j and is incompatible with Log4j. Log4j2 is mainly referenced from Logback

Three modules

  • Logback-core: The base module of the other two modules
  • Logback-classic: It is an improved version of Log4J and fully implements the SLF4J API so that you can easily switch to other Logging systems such as Log4J or JDK14 Logging
  • Logback-access: The access module integrates with the Servlet container to provide log access over Http

Log request level versus logger level

The logging level we often say is not accurate, sometimes you may be talking about the logging request level, sometimes you are talking about the logger level

Log Request level

Above is our most common usage, where.info() and.error() refer to what level of logs are written to the logger.

The level in the log request level refers to the level of log information

level

Logs are divided into two types in descending order of importance

  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE

Logger level

According to the richness of the printed logs, the logs are classified from most to least

  • ALL
  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • OFF

In the command, “ALL” prints ALL log information. “OFF” prints nothing

Log recorder

Slf4j. logger is an interface. The actual type of logger depends on what logging framework you are using. If you are using logback, The actual type of the logger ch. Qos. Logback. Classic. The logger

Logger default level

You can also change the default level of the root logger in the configuration file if you wish

LoggerContext

Each logger is associated with a LoggerContext, which is responsible for creating loggers and arranging them 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 an argument. Calling the LoggerFactory.getLogger method with the same name always yields a reference to the same Logger object.

The log information that different levels of loggers can record

The first line is the level of the logger, where the LOG_LEVEL column is the level of the log request, with YES indicating that it can print and NO indicating that it cannot

LOG_LEVEL TRACE DEBUG INFO WARN ERROR OFF
TRACE YES NO NO NO NO NO
DEBUG YES YES NO NO NO NO
INFO YES YES YES NO NO NO
WARN YES YES YES YES NO NO
ERROR YES YES YES YES YES NO

reference

Using Logback

The official documentation

Configuration mode

Logback supports two configuration modes

  1. Java programming
  2. The configuration file
    1. XML configuration file
    2. Groovy configuration files

Configuration file loading sequence

Logback looks for configuration files in the following order

  1. First look for logback-test.xml in the classpath, if not found
  2. Logback will look for logback.groovy in the classpath if it is not found
  3. Logback will look for logback.xml in the classpath and if it cannot be found
  4. The Logback is automatically configured

The default configuration

Even if you don’t configure anything, Logback will be configured by default, so what does the default configuration configure?

If the default configuration were expressed in XML, the result would be the following

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <! -- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
Copy the code

State Manager – StatusManager

The "status" here is the official term, and the specific thing is the log messageCopy the code

Logback collects its internal state data into a StatusManager object and accesses it through LoggerContext, where you can access all state data associated with the Logback context.

Of course, not all log messages can be retained, and to keep memory usage at a reasonable level, the default StatusManager implementation stores the status messages in two separate parts: the header and the tail.

The header section stores the first H status messages, while the tail section stores the last T messages. H = T = 150 at present. Note that these values may change in future releases.

The classic Logback comes with a servlet called ViewStatusMessagesServlet. This Servlet prints LoggerContext as an HTML table for the content associated with the current content by StatusManager. This is sample output.

Logback – classic also comes with a servlet called ViewStatusMessagesServlet. This servlet outputs as HTML the content associated with StatusManager and the current LoggerContext.

Sample output

To add this servlet to your Web application, add the following line to its WEB-INF/web.xml file.

  <servlet>
    <servlet-name>ViewStatusMessages</servlet-name>
    <servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ViewStatusMessages</servlet-name>
    <url-pattern>/lbClassicStatus</url-pattern>
  </servlet-mapping>
Copy the code

The above is the official method, and the following is the method configured in Spring. All you need to do is add @bean to any Spring component

@Component
public class ServletRegister {

    @Bean
    public ServletRegistrationBean registerServlet(a) {
        return new ServletRegistrationBean(new ViewStatusMessagesServlet(), "/lbClassicStatus"); }}Copy the code

Through http://host/yourWebapp/lbClassicStatus can access to the interface

StatusListener — StatusListener

You can register StatusListener with StatusManager so that you can immediately take response actions on status messages, especially messages that occur after the LogBack configuration. Registering status listeners is a convenient way to monitor logBack internal state without human intervention.

Logback comes with an implementation of StatusListener called OnConsoleStatusListener. As the name suggests, it prints all incoming status messages on the console.

You can also register one or more status listeners in a configuration file.

<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />  
  ... 
</configuration>
Copy the code

Note that registered state listeners will only receive state events after registration, so it is best to place the state listener registration directive at the top of the configuration file before placing other directives.

Logback Configuration file structure

The syntax of the Logback profile is very flexible. Therefore, it is not possible to specify the allowed syntax using A DTD file or XML Schema. However, the basic structure of a configuration file still exists

As shown above, the root node is a < Configuration > element and contains zero or more <appender> elements, then zero or more <logger> elements, thenAt most one <root> element.

  • Logger and root serve as log recorders. After they are associated with an application context, they are used to store log objects and define log types and levels.
  • Appenders are primarily used to specify log output destinations, which can be consoles, files, remote socket servers, MySQL, PostreSQL, Oracle, and other databases, JMS, and remote UNIX Syslog daemons.

<configuration>

<configuration debug="true" scan="true" scanPeriod="120 seconds">.</configuration>
Copy the code

Diagnosis of Logback

If you feel that Logback is abnormal, you can enable the Logback diagnostic function

The following uses XML configuration as an example

<configuration debug="true">.</configuration>
Copy the code

or

<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />.</configuration>
Copy the code

These two configurations are equivalent

Automatic reloading of configuration files after modification (” hot loading “)

Logback supports “hot loading,” which means that the configuration is automatically reloaded when the project is running

The following uses XML configuration as an example

<configuration scan="true">.</configuration>
Copy the code

By default, the configuration file is scanned every minute for changes. You can also manually set the frequency

<configuration scan="true" scanPeriod="120 seconds">.</configuration>
Copy the code

Note that the value scanPeriod is a unit of space time. If the time unit is not specified, the default time unit is milliseconds

Because it is easy to make mistakes when editing a configuration file, if the latest version of the configuration file has XML syntax errors, it will fall back to the previous configuration file without XML syntax errors.Copy the code

When hot loading is enabled, Logback starts a ReconfigureOnChangeTask task in the background, which runs in a separate thread and checks to see if your configuration file has changed at the set frequency

Variable – < property >

Custom variable

<configuration>
  <property name="APP_Name" value="myAppName" />.</configuration>
Copy the code

Under < Configuration >, you can use to define a variable. The property name is the name of the variable and the property value is the value of the variable

Use custom variables

A variable is referred to by ${variable name}

<configuration>
    <property name="LOG_PATTERN" value="%date %level [%thread] %logger{10} [%file : %line] %msg%n" />
    
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>.</configuration>
Copy the code

Log output — <appender>

A logger needs to use an appender to export logs to a console, file, database, etc.

Appender has two mandatory properties

  • Name: Name of the appender (optional)
  • calss: The full class name of a specific appender, which is a concrete implementation of an appender. Logback has several commonly used appenders.
    • Ch. Qos. Logback. Core. ConsoleAppender: the log output to the console appender
    • Ch. Qos. Logback. Core. Rolling. RollingFileAppender: the log output to a file, and in accordance with the conditions of the output switch to the new file (scroll output, automatic cutting)

Encoder — <encoder>


is responsible for converting events (logs) into a byte array and writing that byte array out as an OutputStream.


is a child of

. In the

node, the most important configuration is , which is used to format log output.


<appender name="" class="">
    <encoder>
        <pattern></pattern>
        <charset></charset> 
    </encoder>
</appender>
Copy the code

<pattern>

is used to define the log output format. The Conversion Specifier in Logback (which is a set of predefined variables) makes it easy to combine the desired log format

Here I only list the commonly used Conversion specifier. Please refer to the official documentation for more details

Date, time

Suppose the system time is 2006-10-20 14:06:49.812

Conversion Pattern Result
%d The 14:06:49 2006-10-20, 812
%date The 14:06:49 2006-10-20, 812
%date{ISO8601} The 14:06:49 2006-10-20, 812
%date{HH:mm:ss.SSS} 14:06:49. 812
%date{yyyy-MM-dd HH:mm:ss.SSS, Asia/Shanghai} The 14:06:49 2006-10-20, 812

Log recorder

Conversion Pattern Result
%logger The full class name of the logger

Class name, method name, line number

Conversion Pattern Result
% % C, class The complete class name of the output log class. The efficiency of obtaining the class name is average, and it is recommended to use it only when necessary
% % M and method Output log method
% L, % line Print the line number of log. Obtaining line numbers is not efficient and is recommended only when needed

Log information

Conversion Pattern Result
%m, % MSG, %message Log information

A newline

Conversion Pattern Result
%n A newline

Message request level

Conversion Pattern Result
%p, %le, %level Message request level

thread

Conversion Pattern Result
% % t, thread The thread that outputs logs
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS, Asia/Shanghai} %red(%-5level) --- [%thread] %cyan(%class.%method/%line) : %msg%n</pattern>
    </encoder>
</appender>
Copy the code

color

For console output, Logback supports fill colors, which are as follows

  • %black()
  • %red()
  • %green()
  • %yellow()
  • %blue()
  • %magenta()
  • %cyan()
  • %white()
  • %gray()
  • %boldRed()
  • %boldGreen()
  • %boldYellow()
  • %boldBlue()
  • %boldMagenta()
  • %boldCyan()
  • %boldWhite()
  • %highlight()

This is done by wrapping messages in colored codes, such as setting the log level to red % RED (%-5level)

Set character set — <charset>

<charset> is a child of <encoder> and is used to set the output character set

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS, Asia/Shanghai} %red(%-5level) --- [%thread] %cyan(%class.%method/%line) : %msg%n</pattern>
        <charset>UTF-8</charset> 
    </encoder>
</appender>
Copy the code

ConsoleAppender

Ch. Qos. Logback. Core. ConsoleAppender is the appender, logback for the log output to the console.

For the console, only the

node needs to be configured

<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date %red(%-5level) --- [%thread] %cyan(%class.%method/%line) : %msg%n</pattern>
            <charset>UTF-8</charset> 
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
Copy the code

RollingFileAppender

Ch. Qos. Logback. Core. Rolling. RollingFileAppender is the Appender, logback for the log output to a file, and in accordance with the conditions of the output switch to the new file (scroll output, automatic cutting)

attribute type instructions
file String File name, if the file does not exist. Note the file path
append boolean True appends to the end of the file, false overwrites, and defaults to true
encoder Encoder Encoder to set the log output format and code
rollingPolicy RollingPolicy Scroll strategy, describe how to scroll
triggeringPolicy TriggeringPolicy Trigger policy. Under what conditions does scrolling happen

It is essential to use RollingFileAppender RollingPolicy and TriggeringPolicy. However, if the RollingPolicy implements the TriggeringPolicy interface, you only need to specify the RollingPolicy.

RollingPolicy has an attribute called fileNamePattern, which, like the file attribute, represents the log file name, as described below

RollingPolicy — RollingPolicy

RollingPolicy is responsible for the process of moving and renaming log files. Logback provides multiple implementations of rollingPolicies

  • TimeBasedRollingPolicy: Scroll by time, such as day or month
  • SizeAndTimeBasedRollingPolicy: according to the time and size rolling, rolling, for example in the day set on the basis of size, to prevent one day log file is too large! Such as double 11

TimeBasedRollingPolicy

Ch. Qos. Logback. Core. Rolling. TimeBasedRollingPolicy rolling strategy and implement the TriggeringPolicy (trigger strategy)

Therefore, once timeBase RollingPolicy is configured, TriggeringPolicy does not need to be configured

The TimeBasedRollingPolicy has several important properties

  • MaxHistory: deleteN roll cycles agoIs a log file (the history records of the first N rolling cycles can be kept at most). Assuming that scrolls are sent per minute and maxHistory is set to 3, thenEach time you send a scroll, delete the archive 3 minutes ago. For example:
    • 12:00: Archive file 0
    • 12:01: Archive file 1
    • 12:02: No archive (e.g., no log generated in a minute)
    • 12:03: No archive (e.g., no log generated in a minute)
    • 12:04: Scroll is triggered to delete log files from 3 scroll cycles (that is, 3 minutes ago), so archive 0 is deleted, leaving only archive 1

Note that since the old archive log files were deleted, all folders created for the archive log files will be appropriately deleted

  • TotalSizeCap: Further limits the total size of all archive files on top of the maxHistory limit. When the total size limit is exceeded, the oldest archive is asynchronously deleted. TotalSizeCap depends on maxHistory. If maxHistory is not available, setting totalSizeCap alone will not take effect

  • CleanHistoryOnStart: The default delete operation is sent during the transition that triggers the scroll. However, the life cycle of some applications may not be sufficient to trigger scrolling, and for such short-lived applications, archive deletion may never be performed. Archive deletion can be performed when Appender starts by setting cleanHistoryOnStart to true. CleanHistoryOnStart defaults to false.

  • FileNamePattern is one of the most complex and important attributes, and it’s also a mandatory one, so take that as a separate one

FileNamePattern properties

The File property in RollingFileAppender (the parent of TimeBasedRollingPolicy) may or may not be set. This is recommended because the location of the log file in the current activity can be decoupled from the location of the archive log file by setting the File property that contains FileAppender.

The value of fileNamePattern is the path name of the log file, supporting absolute and relative paths and date converters — %d.

For example

  • An absolute path: / Users/WQLM/work/project/test/logs/logback/application. The log
  • Relative paths: logs/logback/application. The log
  • Note: Windows environments are aware of directory separators

Date converter — %d %d indicates the current time of the system. The default format is %d{YYYY-MM-DD}, defined by %d{date format}.

Time zone %d Default host time zone %d{YYYY-MM-DD,UTC+8}

For example

  • Case 1: logs/logback / % d/application. The log
  • Example 2: logs/logback/application_ % d {- dd yyyy – MM, UTC + 8}. The log

In addition to the above, date converters are also used to infer when scrolling is triggered!! Example 1, for example, triggers a scroll every morning to create a folder and file with a new date. Example 2 will trigger a scroll to create a file with a new date every morning.

Multiple %d’s use multiple %d’s, only one of which is used to infer when the scroll is triggered. The rest must be marked as non-inferred conditions with aux arguments, such as logs/logback/%d{YYYY-mm,aux}/application_%d.log

File compression TimeBase RollingPolicy supports automatic file compression. If the fileNamePattern property ends in. Gz or. Zip, this function is enabled.

Case 1:

compression started but appender is not set

<appender name="RFA" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <! --<file>logs/logback/application.log</file>-->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    	<fileNamePattern>logs/logback/application_%d.zip</fileNamePattern>.</rollingPolicy>.</appender>
Copy the code


is not set, so logback generates an unnamed log file called logs/logback/application_2019-12-31 based on the contents of

and writes the current day logs to this file. Logs /logback/application_2019-12-31.zip will be compressed into logs/logback/application_2019-12-31.zip Logs /logback/application_2020-01-01 New log file

Case 2:

compression started and appender set

<appender name="RFA" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/logback/application.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    	<fileNamePattern>logs/logback/application_%d.zip</fileNamePattern>.</rollingPolicy>.</appender>
Copy the code

Due to set the < file >, so the logback will log output to logs/logback/application log, The next day logback according to < fileNamePattern > the Settings in the logs/logback/application. Log into logs/logback/application_2019-12-31. Zip and generate New log logs/logback/application. The log file

For various technical reasons, rolling is not clock-driven but depends on the arrival of logging events.

For example, on March 8, 2002, assuming fileNamePattern was set to YYYY-MM-DD (daily scroll), the first event coming after 2002-3-9 00:00:00 would trigger the scroll.

If you wait until 2002-3-9 00:23:47 and do not receive the log event, you will not continue to wait, immediately trigger the scroll

Therefore, depending on the arrival rate of the event, there may be some delay, but it will not exceed 00:23:47

Summary The fileNamePattern property combines multiple functions, including

  • Setting dynamic File Names
  • Used to infer when a roll is triggered
  • Enable compression policy
  • Units affecting maxHistory (scroll period)
  • It also describes how to scroll, right

Personally, I feel that the fileNamePattern attribute is designed to be too “heavy”

example

<configuration>
    <appender name="TimeFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/app1/app1.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
          <fileNamePattern>logs/app1/app1_%d.zip</fileNamePattern>
           <! Keep log files with up to 60 scrolling cycles
           <maxHistory>60</maxHistory>
           <! -- Under maxHistory, total log file size cannot exceed 1GB-->
           <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%date %-5level --- [%thread] %class.%method/%line : %msg%n</pattern>
        </encoder>
    </appender>
    
    <root level="DEBUG">
        <appender-ref ref="TimeFile" />
    </root>
</configuration>
Copy the code

SizeAndTimeBasedRollingPolicy

Sometimes, want to on the basis of the archive in accordance with the time limit the size of the log file, then you need to use SizeAndTimeBasedRollingPolicy.

For example, each archived log file cannot exceed 50M on a daily basis to prevent large archived log files on special days such as Double 11

SizeAndTimeBasedRollingPolicy inherited TimeBasedRollingPolicy, therefore TimeBasedRollingPolicy all have the function of it, SizeAndTimeBasedRollingPolicy than TimeBasedRollingPolicy many a maxFileSize properties

The maxFileSize property indicates the size of a single archive log file, in KB, MB, or GB

example

<configuration>
    <appender name="SizeAndTimeFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/app1/app1.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
          <fileNamePattern>logs/app1/backup/app1_%d_%i.zip</fileNamePattern>
           <! -- Maximum 10MB for a single log file -->
           <maxFileSize>10MB</maxFileSize>
           <! Delete log files before n rolling cycles (at most keep the history of the first n rolling cycles) -->
           <maxHistory>60</maxHistory>
           <! Limit the total size of all archive files on top of maxHistory limit
           <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%date %-5level --- [%thread] %class.%method/%line : %msg%n</pattern>
        </encoder>
    </appender>
    
    <root level="DEBUG">
        <appender-ref ref="SizeAndTimeFile" />
    </root>
</configuration>
Copy the code

% I is the archive sequence number for a rolling period, starting at 0

Note: maxHistory is a log file with n scroll cycles, not n log files. With maxFileSize set, there may be multiple log files in a scroll cycle

Logger — <logger>

<logger name="" level="" additivity="" >
    <appender-ref ref="" />
</logger>
Copy the code


has three attributes

  • Name: package name or class name. That is, under which class or package the logger will be applied. mandatory
  • Level: Indicates the logger level. Logs below this level are not recorded. The value ranges from TRACE, DEBUG, INFO, WARN, ERROR, ALL, and OFF(case insensitive). If this parameter is not specified, level is inherited from the parent logger
  • Additivity: Whether to append the output source (appender) of the parent Logger. Default: true. If you want to export only to your own source (appender), set this parameter to false (see example 2)

A logger can also contain zero or more

elements that output logs using an appender

Level of inheritance


      
<configuration scan="true" scanPeriod="30 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.wqlm.boot.user.controller.UserController" ></logger>
    <logger name="com.wqlm.boot.user.controller" ></logger>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
Copy the code

As above, name = “com. WQLM. Boot. User. Controller. UserController” the logger is not defined level, so it will inherit the parent logger level.

So who is the parent logger? Is actually the name = “com. WQLM. Boot. User. The controller” logger.

Logback determines the parent-child relationship of loggers based on the package or class hierarchy

Continue to go ahead, name = “com. WQLM. Boot. User. The controller” no logger defined level, so it will inherit its parent logger level. However, there is no more “shallow” logger in this XML, so its parent logger is root. That is, it inherits the level of the root Logger, which is info.

Just go from top to bottom until you find the Logger that shows the level label. You now work your way up from the lower level to the upper level, uploading the inherited level layer by layer until you encounter a Logger that displays the labeled level

Therefore, name = “com. WQLM. Boot. User. Controller. UserController” logger level is info

What is the level of the following loggers


      
<configuration scan="true" scanPeriod="30 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.wqlm.boot.user.controller.UserController" ></logger>
    <logger name="com.wqlm.boot.user.controller" level="warn"></logger>
    <logger name="com.wqlm.boot.user" ></logger>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
Copy the code

Follow the inheritance rules described above

Name = “com. WQLM. Boot. User. Controller. UserController” logger level is warn name = “com. WQLM. Boot. User” logger level is info

Additivity’s add-on strategy


      
<configuration scan="true" scanPeriod="30 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.wqlm.boot.user.controller.UserController" ></logger>
    <logger name="com.wqlm.boot.user.controller" ></logger>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
Copy the code

As above, name = “com. WQLM. Boot. User. Controller. UserController” logger without additivity, thus additivity used the default value is true, i.e., Appends its parent logger’s appender to its own logger.

Looking at its parent logger – name = “com. WQLM. Boot. User. The controller” logger, additivity also USES the default values, therefore, It also appends the appender from its parent logger to its own logger. In the XML name = “com. WQLM. Boot. User. The controller” logger parent logger for root logger! Therefore, it appends an appender named STDOUT to its logger

Just go from top to bottom until you find a logger or root logger that shows appender=”false”. Now work your way up from one appender layer to the next, uploading the appender layers until a logger with appender=”false” is displayed

Therefore, name = “com. WQLM. Boot. User. Controller. UserController” logger, there is also an appender named STDOUT, the appender from its parent logger

Normally, just add an appender to the root Logger!! Other loggers either directly or indirectly get the root Logger’s appender

In this case, each logger has its own appender


      
<configuration scan="true" scanPeriod="30 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="STDOUT2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    
    <appender name="STDOUT3" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.wqlm.boot.user.controller.UserController" additivity="true">
        <appender-ref ref="STDOUT3" />
    </logger>

    <logger name="com.wqlm.boot.user.controller">
        <appender-ref ref="STDOUT2" />
    </logger>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
Copy the code

Said one by one First name = “com. WQLM. Boot. User. The controller” additivity is not complete, the default is true, so can increase the root logger appender, in this way, It has two appenders, STDOUT and STDOUT2

By the same token, the name = “com. WQLM. Boot. User. Controller. UserController” will be an additional name = “com. WQLM. Boot. User. The controller” appender, therefore, It has three appenders, STDOUT, STDOUT2, and STDOUT3

What are the following appenders for each logger?


      
<configuration scan="true" scanPeriod="30 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="STDOUT2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    
    <appender name="STDOUT3" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.wqlm.boot.user.controller.UserController" additivity="true">
        <appender-ref ref="STDOUT3" />
    </logger>

    <logger name="com.wqlm.boot.user.controller" additivity="false">
        <appender-ref ref="STDOUT2" />
    </logger>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
Copy the code

Because the name = “com. WQLM. Boot. User. The controller” logger setting additivity = “false”, therefore, it does not add the superclass appender, its only STDOUT2 appender

Name = “com. WQLM. Boot. User. Controller. UserController” appender as STDOUT2, STDOUT3 logger

Root logger — <root>

<root level="">
    <appender-ref ref="" />
</root>
Copy the code

We don’t need the name attribute, and we don’t need the additivity attribute because it’s the root logger. Only level is mandatory

The possible values of level are TRACE, DEBUG, INFO, WARN, ERROR, ALL, and OFF, and are case-sensitive

Root can also contain zero or more

elements