Quick Start Logback

Introduction

Logback is intended as a successor to the popular log4j project. It was designed by log4j founder Ceki Gulcu. It is also the default logging framework for the SpringBoot project.

Install

Because logback needs to be used together with slf4j, the total dependencies that need to be added include slf4j-api.jar, logback-core.jar, logback-classic.jar, and logback-access.jar. This is not used for the time being, so no dependencies are added.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <logback.version>1.1.7</logback.version>
    <slf4j.version>1.7.21</slf4j.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>${logback.version}</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
    </dependency>
</dependencies>

In the SpringBoot project, if you introduce spring-boot-starter-web, you have introduced all the above dependencies.

Configuration

Logback's configuration file is named logback.xml. After the application starts, Logback will try to find the file in the classpath. If it is not found, the default configuration inside Logback will be used.

If your logback.xml configuration file is outside the application, you can specify the path to the external configuration file through the environment variable logback.configurationFile=/path/to/config.xml.

configration

configuration is the top-level element in logback.xml and contains some attributes:

  • scan: Boolean type, if true, Logback will automatically reload the configuration after the configuration file is modified.
  • scanPeriod: If scan is set to true, you can use this property to configure the scan period for changes in the Logback scan configuration file.
  • debug: Boolean type, this property indicates whether to print the Logback internal log. If true, it will be printed. The default is false.
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds" debug="false">
  ...
</configuration> 

In the above example, configuration file scanning is enabled, the scanning period is 30s, and Logback internal logs are not printed.

There are three sub-elements under the configuration element: appender, logger, and root. Appender and logger can be zero or more, and the root element can only have one.
Insert image description here

property

is used to configure variables. The configured variables can be used in appender and logger through ${} and can be used for unified configuration.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    
    <property name="PATTERN" value="%-4relative [%thread] %-5level %logger{35} - %msg %n" /> 
    
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
      <encoder> 
         <pattern>${PATTERN}</pattern> 
      </encoder> 
   </appender> 

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

appender

The appender element is used to define the component that writes logs. It has two required attributes, name and class. Name represents the name of the component and class is used to configure the class for logging logic. Different classes correspond to different log writing methods. Currently, Logback defines appenders such as ConsoleAppender (console), FileAppender (file), ServerSockerAppender (remote Socker server), SMTPAppender (remote mail server), and SyslogAppender (remote Syslog daemon); of course, you can also implement the Appender interface To implement your own appender and use it in the configuration file.

The most commonly used ones are ConsoleAppender, FileAppender and RollingFileAppender. Among them, RollingFileAppender is a subclass of FileAppender. It adds the function of rolling logs on the basis of writing logs to files. It solves the pain point of extremely large log files caused by logs being recorded in one file all the time.

ConsoleAppender
<?xml version="1.0" encoding="UTF-8"?>
<configuration> 
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
      <encoder> 
         <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> 
      </encoder> 
   </appender> 

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

The appender named STDOUT in the above example uses ConsoleAppender to output the log, that is, the log is output to the console, and the <encoder> subtag is used to format the log.

FileAppender
<?xml version="1.0" encoding="UTF-8"?>
<configuration> 
  <appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
    <file>testFile.log</file> 
    <append>true</append> 
    <encoder> 
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
    </encoder> 
  </appender> 

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

The appender named FILE in the above example uses FileAppender to output the log, that is, to output the log to a file. The sub-tags are explained as follows:

  • file: The file name for recording logs. It can be a relative directory or an absolute directory. If the upper-level directory does not exist, it will be automatically created.
  • append: If the file already exists before recording the log, true means appending the log to the end of the existing file, false means clearing the existing file content and then writing the log. The default is true.
  • encoder: format of output log
RollingFileAppender
<?xml version="1.0" encoding="UTF-8"?>
<configuration> 
    <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
            <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern> 
            <maxHistory>30</maxHistory> 
        </rollingPolicy> 
        <encoder> 
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
        </encoder> 
    </appender> 

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

The appender named ROLLING_FILE in the above example uses RollingFileAppender to output logs. The rolling strategy used is a time-based rolling strategy, where the sub-tags are explained as follows:

  • rollingPolicy: rolling policy. Common rolling policies include time-based rolling policy TimeBasedRollingPolicy and file size-based rolling policy SizeBasedTriggeringPolicy.
  • encoder: format of output log
Time-based rolling strategy

The class is ch.qos.logback.core.rolling.TimeBasedRollingPolicy, and the commonly used attributes are as follows:

  • fileNamePattern: required attribute, used to set the file name of the new file and the time period of each scrolling. Use %d to set the scrolling period, such as logFile.%d{yyyy-MM-dd}.log means rolling by day, logFile.%d{yyyy-MM}.log means rolling by month, logFile.%d.log means rolling by day
  • maxHistory: optional attribute, used with fileNamePattern to set the number of log files that can be retained. For example, if the log file is rolled once a month, maxHistory is set to 5, which means that the log files of the last 5 months will be retained at the maximum. If the log file is rolled once every day, maxHistory is set to 30, which means that the log files of the last 30 days will be retained at the maximum.
  • totalSizeCap: Optional attribute, equivalent to insurance for rolling logs by time, used to control the total size of all log files. When the total size exceeds the specified value, the oldest log file will be deleted
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logFile.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--             按天轮转 -->
            <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!--             保存 30 天的历史记录,最大大小为 3GB -->
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="FILE" />
    </root>
</configuration>
Rolling strategy based on time and file size

The class is ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy, and the commonly used attributes are as follows:

  • fileNamePattern: The usage is the same as the time-based scrolling strategy. In addition to %d, you also need to use %i to solve the problem that the next scrolling time is not reached. The scrolling triggered by the file size has the same problem with the file name, %i starts from 0 and increments

  • maxFileSize: The maximum size of each file. If it exceeds the specified value, scrolling will be triggered.

  • maxHistory: Usage is the same as time-based scrolling strategy

  • totalSizeCap: Usage is the same as time-based rolling strategy

logger

The appender tag is used to configure the output destination of the log, and the logger tag can be regarded as the source of the log. Even if the log is printed from which package or specific class, the logger tag can be bound to zero or more appenders to specify the log output purpose. land. It has the following parameters:

  • name: required attribute, specify a package or specific class
  • level: Optional attribute, the printing level of the log. If not specified, it is inherited from the parent logger.
  • additivity: Optional attribute, whether to transfer logs to the parent logger, Boolean type, default is true, indicating that logs are transferred to the parent logger

logger contains zero or more sub-tags <appender-ref> , which is used to bind appenders.

In logback, loggers have a hierarchical relationship in a tree structure. This hierarchical relationship is constructed through package names, as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<configuration> 
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
      <encoder> 
         <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> 
      </encoder> 
   </appender>
    
    <logger name="com.test.logback" level="debug" additivity="true">
        <appender-ref ref="STDOUT" />
    </logger>
    
    <logger name="com.test" level="debug" additivity="true">
        <appender-ref ref="STDOUT" />
    </logger>

   <root level="debug"> 
   </root> 
</configuration>

The above two loggers, through the hierarchical structure of the package name, the logger named com.test is the parent logger named com.test.logback. If the package name is passed If the parent logger of the logger cannot be found in the hierarchical structure, then its parent logger is the root logger. For example, the parent logger with the name com.test is the root logger. If another logger with the name The parent logger is the root logger. , and its name is com's logger, then its parent logger will be changed to the newly defined logger whose name is comcom

Through the above introduction, our additivity attribute is used to configure whether the current logger will pass the log to the parent logger. The default is to pass (true). In the above example, if com.test.logback package The class below prints the log. If it is passed to the logger whose name is com.test.logback, and its bound appender is used to output the log, and because its additivity value is true, then the current logger is in After outputting the log, the log will also be passed to the parent logger, that is, the logger with the name com.test. Unreasonable use of the additivity attribute may result in repeated log printing.

The level attribute is also related to the hierarchical structure of the logger. If the current logger does not define the level attribute, it will be inherited from the nearest parent logger that defines the level attribute. Therefore, the root logger generally sets the level attribute for other loggers. Set the level attribute uniformly.

level level:

  • DEBUG: This level is usually used in the development and debugging stages. It is generally used to record detailed program running status information, such as input, output, and variable values. This information is very helpful for troubleshooting files, but it is not recommended to turn it on in a production environment.
  • INFO: This level is used to record important events and status information of the application. This information is very useful for monitoring and understanding the running status of the application. Usually, the production environment will enable this log level.
  • WARN: This level logs potential problems and warning messages that indicate problems with the application that may occur but are not necessarily fatal. These logs can help you detect potential risks in a timely manner.
  • ERROR: This level is used to log error events, such as exceptions or errors in the application. These logs usually indicate that the application has encountered a problem and requires troubleshooting.
  • FATAL: This level indicates a very serious error that usually prevents the application from continuing to run.

The priorities from high to low are: FATAL -> ERROR -> WARN -> INFO -> DEBUG. When the specified log level is turned on, logs of this log level and all logs with a priority higher than this log level will be printed. For logs, if the log level is set to INFO, FATAL, ERROR, WARN and INFO level logs will be printed. If the log level is set to WARN, FATAL, ERRO and WARN level logs will be printed.

Verify the hierarchical relationship of loggers

Use an example to verify the hierarchical relationship of loggers above. First create two classes com.test.Logback01Tests and com.test.logback.Logback02Tests. package and import statements are omitted from the class definition.

com.test.Logback01Tests

public class Logback01Tests {
    
    

    private static final Logger log = LoggerFactory.getLogger(Logback01Tests.class);

    public void test01(){
    
    

        log.debug("debug");
        log.info("info");

    }
}

com.test.logback.Logback02Tests

public class Logback02Tests {
    
    

    private static final Logger log = LoggerFactory.getLogger(Logback02Tests.class);

    public void test01(){
    
    
        log.debug("debug");
        log.info("info");
    }

}

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
       
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
         <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
      </encoder>
   </appender>

    <logger name="com.test.logback" level="debug" additivity="true">
        <appender-ref ref="STDOUT" />
    </logger>

    <logger name="com.test" level="debug" additivity="true">
        <appender-ref ref="STDOUT" />
    </logger>

   <root level="debug">
   </root>
</configuration>

Configure the output results of the prediction log through logback.xml.

Because both loggers have set the debug log level, the debug and info level logs printed in the method will be printed, and then both logs are set to be passed to the parent logger, so the name is com.test The logger of .logback will transfer the logs to the parent logger named com.test, so the two logs in com.test.logback.Logback02Tests should be printed twice, and the logger named com.test will transfer the logs. to the root logger, but the root logger is not bound to any appender, so even if it is passed, the log will not be printed, so the four logs in com.test.Logback01Tests (plus the two passed from the child logger log) should only be printed once.

Define a test method that calls methods of both classes.

public class NormalTests {
    
    

    @Test
    public void test02(){
    
    
        Logback01Tests logback01Tests = new Logback01Tests();
        Logback02Tests logback02Tests = new Logback02Tests();

        logback01Tests.test01();
        logback02Tests.test01();
    }
}

Actual output:

127  [main] DEBUG com.test.Logback01Tests - debug 
129  [main] INFO  com.test.Logback01Tests - info 
129  [main] DEBUG com.test.logback.Logback02Tests - debug 
129  [main] DEBUG com.test.logback.Logback02Tests - debug 
129  [main] INFO  com.test.logback.Logback02Tests - info 
129  [main] INFO  com.test.logback.Logback02Tests - info 

It can be seen that the output results are completely in line with our expectations. Readers can extend this example to verify other issues, such as what should the log output look like after setting the log level to INFO?

root

The root tag is used to configure the root logger. It has only one attribute, the level attribute. Like the logger element, the root element can contain zero or more <appender-ref> child tags.

In actual use, the root logger usually does not bind appenders to avoid repeated log printing. Log printing is assigned to each sub-logger. A level will be defined in the root logger to ensure that each child logger can inherit the level.

Complete example

<configuration>
    <!--本文主要输出日志为控制台日志,系统日志,sql日志,异常日志-->
    <!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,,,, -->
    <!--控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d %p (%file:%line\)- %m%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--系统info级别日志-->
    <!--<File> 日志目录,没有会自动创建-->
    <!--<rollingPolicy>日志策略,每天简历一个日志文件,或者当天日志文件超过64MB时-->
    <!--encoder 日志编码及输出格式-->
    <appender name="fileLog"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>log/file/fileLog.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/file/fileLog.log.%d.%i</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- or whenever the file size reaches 64 MB -->
                <maxFileSize>64 MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>
                %d %p (%file:%line\)- %m%n
            </pattern>
            <charset>UTF-8</charset>
            <!-- 此处设置字符集 -->
        </encoder>
    </appender>

    <!--sql日志-->
    <appender name="sqlFile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>log/sql/sqlFile.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/sql/sqlFile.log.%d.%i</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- or whenever the file size reaches 64 MB -->
                <maxFileSize>64 MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!--对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。-->
        <encoder>
            <!--用来设置日志的输入格式-->
            <pattern>
                %d %p (%file:%line\)- %m%n
            </pattern>
            <charset>UTF-8</charset>
            <!-- 此处设置字符集 -->
        </encoder>
    </appender>


    <!--异常日志-->
    <appender name="errorFile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>log/error/errorFile.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/error/errorFile.%d.log.%i</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- or whenever the file size reaches 64 MB -->
                <maxFileSize>64 MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!--对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。-->
        <encoder>
            <!--用来设置日志的输入格式-->
            <pattern>
                %d %p (%file:%line\)- %m%n
            </pattern>
            <charset>UTF-8</charset>
            <!-- 此处设置字符集 -->
        </encoder>
        <!--
            日志都在这里 过滤出 error
            使用 try {}catch (Exception e){} 的话异常无法写入日志,可以在catch里用logger.error()方法手动写入日志
            -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--  日志输出级别 -->
    <!--All\DEBUG\INFO\WARN\ERROR\FATAL\OFF-->
    <!--打印info级别日志,分别在控制台,fileLog,errorFile输出
        异常日志在上面由过滤器过滤出ERROR日志打印
    -->
    <root level="INFO">
        <appender-ref ref="fileLog" />
        <appender-ref ref="console" />
        <appender-ref ref="errorFile" />
    </root>

    <!--打印sql至sqlFile文件日志-->
    <logger name="com.springboot.demo.mapper" level="DEBUG" additivity="false">
        <appender-ref ref="console" />
        <appender-ref ref="sqlFile" />
    </logger>
</configuration>

Logs in SpringBoot

The default logging framework of the SpringBoot project is Logback. In the SpringBoot project, the log printing behavior can be configured through application.properties.

# 设置logback.xml位置
logging.config=classpath:log/logback.xml

# 为不同的包名设置不同的打印级别
# org.springframework.web 包的打印级别为 debug
logging.level.org.springframework.web=debug
# org.hibernate 包的打印级别为 error
logging.level.org.hibernate=error

# 指定日志文件的名称
logging.file.name=springboot.log
# 指定日志文件的全路径,它包含了指定日志文件名称的功能
logging.file.name=/usr/log/springboot.log

Reference:
https://logback.qos.ch/manual/index.html

https://blog.csdn.net/weixin_41377777/article/details/120962037

https://www.cnblogs.com/gavincoder/p/10091757.html

https://juejin.cn/post/6844903841318567949

Guess you like

Origin blog.csdn.net/imonkeyi/article/details/132757856