Logback日志框架使用详解以及如何Springboot快速集成

Logback简介

日志系统是用于记录程序的运行过程中产生的运行信息、异常信息等,一般有8个级别,从低到高为All < Trace < Debug < Info < Warn < Error < Fatal < OFF

  1. off 最高等级,用于关闭所有日志记录。
  2. fatal 指出每个严重的错误事件将会导致应用程序的退出。
  3. error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
  4. warn 表明会出现潜在的错误情形。
  5. info 一般和在粗粒度级别上,强调应用程序的运行全程。
  6. debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
  7. trace 该级别日志,默认情况下,既不打印到终端也不输出到文件。此时,对程序运行效率几乎不产生影响
  8. all 最低等级,用于打开所有日志记录。

Logback和Log4j都是为Java应用程序提供的比较流行的开源日志框架,它们都由同一个开发者创建和维护,但在功能和性能上存在一些差异,Logback可以认为是log4j的改进版,在性能、配置应用上都要优于log4j,Logback主要由三个模块构成:logback-core,logback-classic和logback-access。其中,logback-core是其他两个模块的基础,提供了Logback的核心功能。logback-classic模块实现了简单日志门面SLF4J,而logback-access模块则主要作为一个与Servlet容器交互的模块,提供与HTTP访问相关的一些功能。

Logback配置详解

Spring Boot默认是使用Logback的,并且提供了自动配置,默认使用logback-spring.xml作为配置文件的名称,当然,也可以在application.properties或application.yml中配置。下面分享一下logback-spring.xml中常用的一些标签

configuration

configuration为根节点,有scan、scanPeriod、debug三个属性;

scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。

scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。

debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

xml 复制代码
<configuration scan="true" scanPeriod="60 seconds" debug="false">  
      <!-- 其他配置省略-->  
</configuration>

property

property是configuration的子标签,有两个属性name和value:name变量的名称,value变量的值。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="trace"></property>
    <!-- 日志路径-->
    <property name="logPath" value="/logs"></property>
    <!-- 最大保存时间 60天-->
    <property name="maxHistory" value="60"/>
</configuration>

logger

logger节点,可选节点,作用是指明具体的包或类的日志输出级别,以及要使用的;

  1. name:必写属性,指定具体包或类,被指定的包或类中的日志输出将遵从该logger规定配置;
  2. level:非必写属性,指定日志输出级别,该级别将覆盖root配置的输出级别;
  3. addtivity:非必写属性,是否向上级loger传递打印信息,默认是true;
  4. appender-ref:引用的appender,引用后将实现appender中定义的行为。一个logger可以有多个引用,互不影响;

root

root节点,必选节点,用来指定最基础的日志输出级别并指定,可以理解为根logger。

appender

appender是configuration的子节点,也是非常关键的一个节点,它有两个必要属性name和class,name指定appender名称,class指定appender的全限定名。

appender有四种类型,如下(其中第四种比较特殊,后面再说):

  1. ConsoleAppender(控制台日志)
  2. FileAppender(文件日志)
  3. RollingFileAppender(滚动文件日志)
  4. AsyncAppender(异步日志)

appender内的有一个子标签encoder,有两个作用,一是把日志信息转换成字节数组,二是把字节数组写入到输出流,可以用于定义输出日志内容的编码格式、日志格式;其中endcoder内的子标签charset用于定义输出日志内容的编码格式,子标签pattern用于定义输出日志的具体格式;

  1. %date:表示日期
  2. %thread:表示线程名
  3. %-5level:表示级别从左显示 5 个字符宽度
  4. %logger{36}:表示 Logger 名字最长 36 个字符
  5. %msg:表示日志消息
  6. %n:换行符
  7. %line:表示当前日志事件的行号

ConsoleAppender

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="INFO"></property>
    <!-- lOGGER  PATTERN 根据个人喜好选择匹配  -->
    <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n"></property>
    <!-- 控制台的标准输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${logPattern}</pattern>
        </encoder>
    </appender>
    <root level="${logLevel}">
        <appender-ref ref="console"/>
    </root>
</configuration>

FileAppender与RollingFileAppender

FileAppender与RollingFileAppender都是用于将日志写入文件的组件,配置属性基本相同,因此这里放在一起来说,但是需要注意的是二者在日志文件处理方式上有所不同,FileAppender将所有的日志信息写入一个指定的文件中,当文件达到一定大小或时间点时,它会被新的日志文件所替代。而RollingFileAppender则会在日志文件达到指定大小时,创建新的日志文件继续写入,并且保留一定数量的旧日志文件。

以下是RollingFileAppender和FileAppender的主要区别:

RollingFileAppender

  1. 日志滚动:当日志文件达到指定大小时,RollingFileAppender会自动创建一个新的日志文件,并将当前日志文件中的内容复制到新文件中。新创建的日志文件的名称会加上一个时间戳或索引号,以便区分。
  2. 日志文件保留:RollingFileAppender可以设置保留的日志文件数量。当超过这个数量时,最早创建的日志文件会被自动删除。
  3. 日志索引:RollingFileAppender还可以生成一个索引文件,用于记录所有滚动日志文件的名称和位置信息。这样可以在需要查看历史日志时,快速定位到需要的日志文件。

FileAppender

  1. 日志输出:FileAppender将日志输出到一个指定的文件中,不进行滚动操作。当文件达到一定大小限制时,FileAppender会停止写入新的日志信息,并创建一个新的日志文件继续写入。
  2. 日志文件命名:FileAppender可以设置日志文件的名称和位置,但不会像RollingFileAppender那样添加时间戳或索引号。
  3. 需要注意的是,RollingFileAppender和FileAppender在配置上略有不同。例如,RollingFileAppender需要指定日志文件的最大大小和保留数量,而FileAppender则需要指定日志文件的最大大小和文件数量等参数。

另外这里着重说一下maxFileSize和maxHistory,以及filter标签,maxFileSize 是用来限制单个日志文件的最大大小。例如,如果你设置 maxFileSize 为 10MB,那么当日志文件达到 10MB 时,Logback 会开始创建新的日志文件(例如,app.log.1,app.log.2,等等)。旧的日志文件将被保留,直到达到配置的 maxHistory 天数。

而 totalSizeCap 是用来限制所有日志文件的总大小。例如,如果你设置 totalSizeCap 为 1GB,那么当所有日志文件的总大小达到 1GB 时,Logback 会开始删除旧的日志文件,以便为新的日志文件腾出空间。这个属性对于防止日志文件占用过多的磁盘空间非常有用。

注意,totalSizeCap 和 maxFileSize 不建议同时使用。如果同时设置,totalSizeCap 将优先于 maxFileSize。也就是说,当达到 totalSizeCap 时,将删除旧的日志文件,无论这些文件是否达到了 maxFileSize。

在Logback中,filter标签用于过滤日志消息。通过在filter标签中定义条件,可以实现对日志消息的筛选和拦截,实现根据指定的条件来控制哪些日志消息应该被记录。

  1. filter标签有三种类型:onMatch、onMismatch和always。这些类型决定了在过滤器匹配或不匹配时应该执行的操作。
  2. onMatch:当过滤器条件匹配时执行的操作。通常,你可以将其设置为记录匹配的日志消息或采取其他所需的操作。
  3. onMismatch:当过滤器条件不匹配时执行的操作。通常情况下,你可以将其设置为记录不匹配的日志消息或采取其他所需的操作。
  4. always:无论过滤器条件是否匹配,都会执行的操作。这通常用于对日志消息进行一些通用的处理或记录。

在下面的示例中,我们使用了一个名为ThresholdFilter的过滤器,它根据日志级别进行过滤。我们将level属性设置为info,这意味着只有级别为info及以上的日志消息会被记录到文件中,其他级别的日志消息将被拦截。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="info"></property>
    <!-- lOGGER  PATTERN 根据个人喜好选择匹配  -->
    <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n"></property>
    <!-- 日志路径-->
    <property name="logPath" value="./logs"></property>
    <!-- 最大保存时间 60天-->
    <property name="maxHistory" value="60"/>
    <!-- 控制台的标准输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${logPattern}</pattern>
        </encoder>
    </appender>
    <!-- INFO 级别的日志记录  -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logPath}/${appName}_info.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 限制单个日志文件的大小-->
            <maxFileSize>10MB</maxFileSize>
           <!--最大保存时间-->
            <maxHistory>${maxHistory}</maxHistory>
            <!-- 所有日志文件总大小的限制-->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>${logPattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <root level="${logLevel}">
        <appender-ref ref="console"/>
        <appender-ref ref="file_info"/>
    </root>
</configuration>

AsyncAppender

上面已经说了,四种类型的appender,AsyncAppender比较特殊,特殊就在于记录日志时从同步或异步的角度来看,前三者属于同步日志,后者属于异步日志。Logback的同步日志是立即写入磁盘的日志,而异步日志是通过线程池异步处理写入磁盘的日志。

Logback异步输出的原理是:先写入到缓冲区,当缓冲区满了或者达到一定时间,再把缓冲区的数据一次性写入磁盘,这样可以减少磁盘IO操作,提高性能。

Logback异步输出的配置是:配置一个,例如,然后在中配置一个,表示缓冲区的大小,再配置一个,表示缓冲区达到这个阈值时,会触发一个强制写入磁盘的操作。

  1. queueSize:控制阻塞队列大小,使用的ArrayBlockingQueue阻塞队列,默认容量256:内存中最多保存256条日志
  2. discardingThreshold:丢弃日志的阈值,为防止队列满后发生阻塞。默认队列剩余容量 < 队列长度的20%,就会丢弃TRACE、DEBUG和INFO级日志;若discardingThreshold = 0,那么队列满时再有日志写入就会阻塞。若discardingThreshold != 0,也只丢弃≤INFO级日志,出现大量错误日志时,还是会阻塞。
  3. neverBlock:控制队列满时,加入的数据是否直接丢弃,不会阻塞等待,默认是false;队列满时:offer不阻塞,而put会阻塞;neverBlock为true时,使用offer

在《基于Redis实现消息队列的实践》遇到的明明程序执行结果正常,就是看不到过程日志,最后的解决办法就使用了logback的异步日志,有兴趣的小伙伴可移步参考一下。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="info"></property>
    <!-- lOGGER  PATTERN 根据个人喜好选择匹配  -->
    <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n"></property>
    <!-- 日志路径-->
    <property name="logPath" value="./logs"></property>
    <!-- 最大保存时间 60天-->
    <property name="maxHistory" value="60"/>
    <!-- 异步缓冲队列的深度,该值会影响性能.默认值为256 -->
    <property name="queueSize" value="512"></property>

    <!-- 控制台的标准输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${logPattern}</pattern>
        </encoder>
    </appender>
    <!-- INFO 级别的日志记录  -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logPath}/${appName}_info.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 限制单个日志文件的大小-->
            <maxFileSize>10MB</maxFileSize>
           <!--最大保存时间-->
            <maxHistory>${maxHistory}</maxHistory>
            <!-- 所有日志文件总大小的限制-->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>${logPattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <appender name="async_log_info" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>${queueSize}</queueSize>
        <!-- 设置该属性 logback 会使用 ArrayBlockingQueue 的非阻塞方法 offer 代替 put, 防止在队列满时阻塞业务线程 -->
        <neverBlock>true</neverBlock>
        <appender-ref ref="file_info"/>
    </appender>
    <root level="${logLevel}">
        <appender-ref ref="console"/>
        <appender-ref ref="file_info"/>
        <appender-ref ref="async_log_info"/>
    </root>
</configuration>

Logback与Springboot

引入依赖

如果项目是Springboot项目,默认已经引入,不需要额外引入依赖,如果确实需要,可参考:

xml 复制代码
<dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.11</version>        
    </dependency>

配置文件

配置文件命名

在Springboot项目中,默认的配置文件名称是logback-spring.xml,官方也推荐使用这样的命名方式,logback本身默认的配置文件名称是logback.xml

配置文件加载顺序

在工程resources目录下建立logback.xml,配置文件的加载顺序是:

  1. logback首先会试着查找logback.groovy文件;
  2. 当没有找到时,继续试着查找logback-test.xml文件;
  3. 当没有找到时,继续试着查找logback.xml文件,如果是Springboot项目,则找logback-spring.xml;
  4. 如果仍然没有找到,则使用默认配置(打印到控制台);

程序中注入logger

在程序中注入logger有两种方式:

  1. final static Logger logger = LoggerFactory.getLogger("名称");
java 复制代码
@Component
public class DemoTask {
    private final static Logger logger= LoggerFactory.getLogger(DemoTask.class);

    @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
    public void test() {
        logger.info("-------------");
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");
        logger.info("-------------");
    }
}
  1. @Sl4j注解:如果引入了lombok可以在类上标记@Sl4j,Lombok会在类中自动生成一个名为log的静态final成员变量;
typescript 复制代码
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>@Component
@Slf4jj
public class DemoTask {
    @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
    public void test() {
        log.info("-------------");
        log.trace("trace");
        log.debug("debug");
        log.info("info");
        log.warn("warn");
        log.error("error");
        log.info("-------------");
    }
}

文章中展示了关键性代码,示例全部代码地址:gitcode.net/fox9916/log...

相关推荐
wn53112 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
bjzhang7522 分钟前
SpringBoot开发——集成Tess4j实现OCR图像文字识别
spring boot·ocr·tess4j
flying jiang27 分钟前
Spring Boot 入门面试五道题
spring boot
小菜yh28 分钟前
关于Redis
java·数据库·spring boot·redis·spring·缓存
希冀12335 分钟前
【操作系统】1.2操作系统的发展与分类
后端
GoppViper1 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
爱上语文2 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
荆州克莱2 小时前
springcloud整合nacos、sentinal、springcloud-gateway,springboot security、oauth2总结
spring boot·spring·spring cloud·css3·技术
serve the people2 小时前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
罗政8 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端