• 快速入门 Logback


    简介

    Logback 旨在作为流行的 log4j 项目的继承者。它是由 log4j 创始人 Ceki Gulcu 设计的。同时它也是 SpingBoot 项目的默认日志框架。

    安装

    因为 logback 需要和 slf4j 一起使用,所以总共需要添加依赖的包有 slf4j-api.jar,logback-core.jar,logback-classic.jar,logback-access.jar 这个暂时用不到所以不添加依赖了。

    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <logback.version>1.1.7logback.version>
        <slf4j.version>1.7.21slf4j.version>
    properties>
    
    <dependencies>
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-apiartifactId>
            <version>${slf4j.version}version>
            <scope>compilescope>
        dependency>
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-coreartifactId>
            <version>${logback.version}version>
        dependency>
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>${logback.version}version>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在 SpringBoot 项目中,如果你引入了 spring-boot-starter-web,那你已经引入了上述的所有依赖。

    配置

    Logback 的配置文件名为 logback.xml,在应用程序启动之后,Logback 会尝试在类路径中寻找该文件,如果没有找到,则会使用 Logback 内部的默认配置。

    如果你的 logback.xml 配置文件在应用程序外部,可以通过环境变量 logback.configurationFile=/path/to/config.xml 来指定外部配置文件的路径。

    configration

    configuration 是 logback.xml 中的顶级元素,它包含了一些属性:

    • scan:布尔类型,如果为 true,则 Logback 会在配置文件修改之后自动重新加载配置。
    • scanPeriod:如果 scan 设置为 true,则可以使用该属性来配置 Logback 扫描配置文件是否变化的扫描周期。
    • debug:布尔类型,该属性表示是否打印 Logback 内部日志,如果为 true,则打印,默认为 false。
    
    <configuration scan="true" scanPeriod="30 seconds" debug="false">
      ...
    configuration> 
    
    • 1
    • 2
    • 3
    • 4

    上述实例中表示开启配置文件扫描,扫描周期为 30s,并且不打印 Logback 内部日志。

    configuration 元素下有三个子元素 appender,logger,root,其中 appender 和 logger 可以是零个或多个,root 元素则做多只能有一个。
    在这里插入图片描述

    property

    用于配置变量,配置的变量可以在 appender 和 logger 中通过 ${} 来使用,可以用于统一配置。

    
    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    appender

    appender 元素用来定义写日志的组件,它有两个必填的属性 name 和 class,name 表示组件的名称和 class 用于配置写日志逻辑的类,不同的类对应不同的写日志方式,目前,Logback 中定义了有 ConsoleAppender(控制台)、FileAppender(文件)、ServerSockerAppender(远程 Socker 服务器)、SMTPAppender(远程邮件服务器)、和 SyslogAppender(远程 Syslog 守护程序) 等 appender;当然,你也可以通过实现 Appender 接口来实现自己的 appender 并在配置文件中使用。

    而这其中最常使用的就是 ConsoleAppender、FileAppender 和 RollingFileAppender。其中 RollingFileAppender 是 FileAppender 子类,它在日志写文件的基础上附加了滚动日志的功能,它解决了日志一直记录在一个文件而造成超大日志文件的痛点。

    ConsoleAppender
    
    <configuration> 
       <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
          <encoder> 
             <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %npattern> 
          encoder> 
       appender> 
    
       <root level="DEBUG"> 
          <appender-ref ref="STDOUT" /> 
       root> 
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    上述示例中的名为 STDOUT 的 appender 使用了 ConsoleAppender 来输出日志,即将日志输出到控制台上,其中的 子标签定对日志进行格式化。

    FileAppender
    
    <configuration> 
      <appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
        <file>testFile.logfile> 
        <append>trueappend> 
        <encoder> 
          <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%npattern> 
        encoder> 
      appender> 
    
      <root level="DEBUG"> 
        <appender-ref ref="FILE" /> 
      root> 
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    上述示例中的名为 FILE 的 appender 使用了 FileAppender 来输出日志,即将日志输出到一个文件中,其中子标签释义如下:

    • file:记录日志的文件名,可以是相对目录也可以是绝对目录,如果上级目录不存在则自动创建
    • append:记录日志之前如果文件已经存在的行为,true 表示在现有文件的末尾追加日志,false 表示清空现有文件内容后写入日志,默认为 true
    • encoder:输出日志的格式
    RollingFileAppender
    
    <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}.logfileNamePattern> 
                <maxHistory>30maxHistory> 
            rollingPolicy> 
            <encoder> 
                <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%npattern> 
            encoder> 
        appender> 
    
        <root level="DEBUG"> 
            <appender-ref ref="ROLLING_FILE" /> 
        root> 
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    上述示例中名为 ROLLING_FILE 的 appender 使用 RollingFileAppender 来输出日志,使用的滚动策略是基于时间的滚动策略,其中子标签释义如下:

    • rollingPolicy:滚动策略,常见的滚动策略有基于时间的滚动策略 TimeBasedRollingPolicy、基于文件大小的滚动策略 SizeBasedTriggeringPolicy
    • encoder:输出日志的格式
    基于时间的滚动策略

    类是 ch.qos.logback.core.rolling.TimeBasedRollingPolicy,常用属性如下:

    • fileNamePattern:必填属性,用于设定新文件的文件名和每次滚动的时间周期,通过 %d 来只当滚动周期,如 logFile.%d{yyyy-MM-dd}.log 表示按天滚动,logFile.%d{yyyy-MM}.log 表示按月滚动,logFile.%d.log 表示按天滚动
    • maxHistory:可选属性,与 fileNamePattern 搭配使用,用于设置可以保留的日志文件的个数。例如如果日志文件 1 个月滚动一次,maxHistory 设置为 5 表示最大保留最近 5 个月的日志文件,如果日志文件 1 天滚动一次,maxHistory 设置为 30 表示最大保留最近 30 天的日志文件
    • totalSizeCap:可选属性,相当于按时间滚动日志的保险,用来控制所有日志文件的总大小,当总大小超过指定的值时,会删除最老的日志文件
    
    <configuration>
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>logFile.logfile>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                
                <fileNamePattern>logFile.%d{yyyy-MM-dd}.logfileNamePattern>
                
                <maxHistory>30maxHistory>
                <totalSizeCap>3GBtotalSizeCap>
            rollingPolicy>
            <encoder>
                <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%npattern>
            encoder>
        appender>
        <root level="DEBUG">
            <appender-ref ref="FILE" />
        root>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    基于时间和文件大小的滚动策略

    类是 ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy,常用属性如下:

    • fileNamePattern:用法和基于时间的滚动策略一样,除了 %d,还需要使用 %i,用于解决没有到下一个滚动时间但是因为文件大小而触发的滚动,文件名一样的问题,%i 从 0 开始递增

    • maxFileSize:每个文件的最大大小,如果超过指定的值会触发滚动

    • maxHistory:用法和基于时间的滚动策略一样

    • totalSizeCap:用法和基于时间的滚动策略一样

    logger

    appender 标签用来配置日志的输出目的地,而 logger 标签可以看做日志的来源,即使从哪个包下或具体哪个类打印的日志,logger 标签可以绑定零个或多个 appender 来指定日志输出目的地。它有以下参数:

    • name:必填属性,指定一个包或具体的类
    • level:可选属性,日志的打印级别,如果没有指定则从父 logger 中继承
    • additivity:可选属性,是否向父 logger 传递日志,布尔类型,默认为 true,表示向父 logger 传递日志

    logger 包含零个或多个子标签 ,它用来绑定 appender。

    在 logback 中,logger 具有树形结构的层级关系,这种层级关系通过包名来构建,如下所示:

    
    <configuration> 
       <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
          <encoder> 
             <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %npattern> 
          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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    上述两个 logger,通过包名的层级结构,name 为 com.test 的 logger 是 name 为 com.test.logback 的父 logger,如果通过包名的层级结构找不到该 logger 的父 logger,那么它的父 logger 就是 root logger,比如,name 为 com.test 的父 logger 就是 root logger,如果之后又定义了一个 name 为 com 的 logger,那么它的父 logger 会更变为新定义的 name 为 com 的 logger,而 name 为 com 的父 logger 就是 root logger。

    通过上面介绍,我们 additivity 属性用于配置当前 logger 是否将日志传递给父 logger,默认为传递(true),以上面的例子来说,如果 com.test.logback 包下的类打印了日志,如果会传递到 name 为 com.test.logback 的 logger,并使用它绑定的 appender 来输出日志,又因为它的 additivity 的值为 true,那么当前 logger 在自己输出日志之后,还会将日志传递给父 logger,也就是 name 为 com.test 的 logger,不合理的使用 additivity 属性可能导致重复打印日志的情况。

    其中 level 属性也与 logger 的层级结构有关,如果当前 logger 没有定义 level 属性,那么将会从最近的定义了 level 属性的父 logger 中继承,因此 root logger 一般都会设置 level 属性,用于给其他的 logger 统一设置 level 属性。

    level 级别:

    • DEBUG:该级别通常用于开发和调试阶段,一般用它来记录详细的程序运行状态信息,比如输入输出、变量值的,这些信息对于排查文件很有帮助,但是在生产环境不建议开启。
    • INFO:该级别用于记录应用程序的重要事件和状态信息,这些信息对于监控和了解应用程序的运行状态非常有用,通常,生成环境会启用该日志级别。
    • WARN:该级别记录潜在的问题和警告信息,这些信息表明应用程序可能会出现问题,但不一定致命。这些日志可以帮助你及时发现潜在的风险。
    • ERROR:该级别用于记录错误事件,例如异常或应用程序中的错误,这些日志通常表明应用程序遇到了问题,需要进行故障排查。
    • FATAL:该级别表示非常严重的错误,通常会导致应用程序无法继续运行。

    优先级从高到低依次是:FATAL -> ERROR -> WARN -> INFO -> DEBUG,开启指定的日志级别,会打印该日志级别的日志和所有优先级高于该日志级别的日志,如设置日志级别是 INFO,那么会打印 FATAL,ERROR,WARN 和 INFO 级别的日志,如果设置日志级别是 WARN,那么会打印 FATAL,ERRO 和 WARN 级别的日志。

    验证 logger 的层级关系

    通过实例来验证上述中 logger 的层级关系,首先创建两个类 com.test.Logback01Testscom.test.logback.Logback02Tests。类定义中省略了 package 和 import 语句。

    com.test.Logback01Tests

    public class Logback01Tests {
    
        private static final Logger log = LoggerFactory.getLogger(Logback01Tests.class);
    
        public void test01(){
    
            log.debug("debug");
            log.info("info");
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    logback.xml

    
    <configuration>
           
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
          <encoder>
             <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %npattern>
          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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    通过 logback.xml 配置预测日志的输出结果。

    因为两个 logger 都设置了 debug 日志级别,所以方法中打印的 debug 和 info 级别两条日志都会打印出来,然后都设置了将日志传递到父 logger 中,则 name 为 com.test.logback 的 logger 会将日志传递到 name 为 com.test 父 logger 中,所以 com.test.logback.Logback02Tests 中的两条日志应该会打印两次,name 为 com.test 的 logger 会将日志传递到 root logger 中,但是 root logger 没有绑定任何的 appender,所以即使传递了也不会打印日志,所以 com.test.Logback01Tests 中的四条日志(加上子 logger 中传递过来的两条日志)应该只会打印一次。

    定义一个测试方法调用两个类的方法。

    public class NormalTests {
    
        @Test
        public void test02(){
            Logback01Tests logback01Tests = new Logback01Tests();
            Logback02Tests logback02Tests = new Logback02Tests();
    
            logback01Tests.test01();
            logback02Tests.test01();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    实际输出结果:

    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 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看到输出结果完全符合我们的预期,读者可以通过扩展这个例子来验证其他的一些问题,如将日志级别设置成 INFO 之后的日志输出应该是怎么样的?

    root

    root 标签用来配置 root logger,它只有一个属性,即 level 属性。与 logger 元素类似,root 元素可以包含零个或多个 子标签。

    在实际使用中,root logger 通常不会绑定 appender,以避免日志重复打印,日志打印被分配到各个子 logger 中来负责。root logger 中会定义一个 level,以保证每个子 logger 都能继承 level。

    完整示例

    <configuration>
        
        
        
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d %p (%file:%line\)- %m%npattern>
                <charset>UTF-8charset>
            encoder>
        appender>
    
        
        
        
        
        <appender name="fileLog"
                  class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>log/file/fileLog.logFile>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>log/file/fileLog.log.%d.%ifileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    
                    <maxFileSize>64 MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
            rollingPolicy>
            <encoder>
                <pattern>
                    %d %p (%file:%line\)- %m%n
                pattern>
                <charset>UTF-8charset>
                
            encoder>
        appender>
    
        
        <appender name="sqlFile"
                  class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>log/sql/sqlFile.logFile>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>log/sql/sqlFile.log.%d.%ifileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    
                    <maxFileSize>64 MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
            rollingPolicy>
            
            <encoder>
                
                <pattern>
                    %d %p (%file:%line\)- %m%n
                pattern>
                <charset>UTF-8charset>
                
            encoder>
        appender>
    
    
        
        <appender name="errorFile"
                  class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>log/error/errorFile.logFile>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>log/error/errorFile.%d.log.%ifileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    
                    <maxFileSize>64 MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
            rollingPolicy>
            
            <encoder>
                
                <pattern>
                    %d %p (%file:%line\)- %m%n
                pattern>
                <charset>UTF-8charset>
                
            encoder>
            
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERRORlevel>
                <onMatch>ACCEPTonMatch>
                <onMismatch>DENYonMismatch>
            filter>
        appender>
        
        
        
        <root level="INFO">
            <appender-ref ref="fileLog" />
            <appender-ref ref="console" />
            <appender-ref ref="errorFile" />
        root>
    
        
        <logger name="com.springboot.demo.mapper" level="DEBUG" additivity="false">
            <appender-ref ref="console" />
            <appender-ref ref="sqlFile" />
        logger>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104

    SpringBoot 中的日志

    SpringBoot 项目的默认日志框架就是 Logback,在 SpingBoot 项目中可以通过 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    参考:
    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

  • 相关阅读:
    Cadence Allegro PCB设计88问解析(十五) 之 Allegro中如何替换过孔类型
    行情分析——加密货币市场大盘走势(10.16)
    设计模式:适配器模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
    GZ035 5G组网与运维赛题第4套
    向已有项目添加LICENSE
    高频面试题
    网页前端设计-作业三(JavaScript)
    【技术积累】软件工程中的测试驱动开发【一】
    Linux源码&文件系统目录结构
    二进制搜索树(BSTs) 和AVL 树
  • 原文地址:https://blog.csdn.net/imonkeyi/article/details/132757856