• 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三个属性;

    1. scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
    2. scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
    3. debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
    1. <configuration scan="true" scanPeriod="60 seconds" debug="false">
    2. configuration>

    property

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

    1. "1.0" encoding="UTF-8"?>
    2. <configuration scan="true" scanPeriod="60 seconds" debug="false">
    3. <property name="appName" value="logback-demo">property>
    4. <property name="logLevel" value="trace">property>
    5. <property name="logPath" value="/logs">property>
    6. <property name="maxHistory" value="60"/>
    7. 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
    1. "1.0" encoding="UTF-8"?>
    2. <configuration scan="true" scanPeriod="60 seconds" debug="false">
    3. <property name="appName" value="logback-demo">property>
    4. <property name="logLevel" value="INFO">property>
    5. <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
    6. <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    7. <encoder>
    8. <charset>UTF-8charset>
    9. <pattern>${logPattern}pattern>
    10. encoder>
    11. appender>
    12. <root level="${logLevel}">
    13. <appender-ref ref="console"/>
    14. root>
    15. 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及以上的日志消息会被记录到文件中,其他级别的日志消息将被拦截。

    1. "1.0" encoding="UTF-8"?>
    2. <configuration scan="true" scanPeriod="60 seconds" debug="false">
    3. <property name="appName" value="logback-demo">property>
    4. <property name="logLevel" value="info">property>
    5. <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
    6. <property name="logPath" value="./logs">property>
    7. <property name="maxHistory" value="60"/>
    8. <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    9. <encoder>
    10. <charset>UTF-8charset>
    11. <pattern>${logPattern}pattern>
    12. encoder>
    13. appender>
    14. <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
    15. <file>${logPath}/${appName}_info.logfile>
    16. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    17. <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
    18. <maxFileSize>10MBmaxFileSize>
    19. <maxHistory>${maxHistory}maxHistory>
    20. <totalSizeCap>1GBtotalSizeCap>
    21. rollingPolicy>
    22. <encoder>
    23. <pattern>${logPattern}pattern>
    24. <charset>utf-8charset>
    25. encoder>
    26. <filter class="ch.qos.logback.classic.filter.LevelFilter">
    27. <level>INFOlevel>
    28. <onMatch>ACCEPTonMatch>
    29. <onMismatch>DENYonMismatch>
    30. filter>
    31. appender>
    32. <root level="${logLevel}">
    33. <appender-ref ref="console"/>
    34. <appender-ref ref="file_info"/>
    35. root>
    36. 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的异步日志,有兴趣的小伙伴可移步参考一下。

    1. "1.0" encoding="UTF-8"?>
    2. <configuration scan="true" scanPeriod="60 seconds" debug="false">
    3. <property name="appName" value="logback-demo">property>
    4. <property name="logLevel" value="info">property>
    5. <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
    6. <property name="logPath" value="./logs">property>
    7. <property name="maxHistory" value="60"/>
    8. <property name="queueSize" value="512">property>
    9. <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    10. <encoder>
    11. <charset>UTF-8charset>
    12. <pattern>${logPattern}pattern>
    13. encoder>
    14. appender>
    15. <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
    16. <file>${logPath}/${appName}_info.logfile>
    17. <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    18. <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
    19. <maxFileSize>10MBmaxFileSize>
    20. <maxHistory>${maxHistory}maxHistory>
    21. <totalSizeCap>1GBtotalSizeCap>
    22. rollingPolicy>
    23. <encoder>
    24. <pattern>${logPattern}pattern>
    25. <charset>utf-8charset>
    26. encoder>
    27. <filter class="ch.qos.logback.classic.filter.LevelFilter">
    28. <level>INFOlevel>
    29. <onMatch>ACCEPTonMatch>
    30. <onMismatch>DENYonMismatch>
    31. filter>
    32. appender>
    33. <appender name="async_log_info" class="ch.qos.logback.classic.AsyncAppender">
    34. <discardingThreshold>0discardingThreshold>
    35. <queueSize>${queueSize}queueSize>
    36. <neverBlock>trueneverBlock>
    37. <appender-ref ref="file_info"/>
    38. appender>
    39. <root level="${logLevel}">
    40. <appender-ref ref="console"/>
    41. <appender-ref ref="file_info"/>
    42. <appender-ref ref="async_log_info"/>
    43. root>
    44. configuration>

    Logback与Springboot

    引入依赖

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

    1. <dependency>
    2. <groupId>ch.qos.logbackgroupId>
    3. <artifactId>logback-classicartifactId>
    4. <version>1.2.11version>
    5. 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(“名称”);
    1. @Component
    2. public class DemoTask {
    3. private final static Logger logger= LoggerFactory.getLogger(DemoTask.class);
    4. @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
    5. public void test() {
    6. logger.info("-------------");
    7. logger.trace("trace");
    8. logger.debug("debug");
    9. logger.info("info");
    10. logger.warn("warn");
    11. logger.error("error");
    12. logger.info("-------------");
    13. }
    14. }
    1. @Sl4j注解:如果引入了lombok可以在类上标记@Sl4j,Lombok会在类中自动生成一个名为log的静态final成员变量;
    1. <dependency>
    2. <groupId>org.projectlombokgroupId>
    3. <artifactId>lombokartifactId>
    4. <optional>trueoptional>
    5. dependency>
    1. @Component
    2. @Slf4jj
    3. public class DemoTask {
    4. @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
    5. public void test() {
    6. log.info("-------------");
    7. log.trace("trace");
    8. log.debug("debug");
    9. log.info("info");
    10. log.warn("warn");
    11. log.error("error");
    12. log.info("-------------");
    13. }
    14. }

    文章中展示了关键性代码,示例全部代码地址:凡夫贩夫 / logback-demo · GitCode

     

  • 相关阅读:
    PMAL: Open Set Recognition via Robust Prototype Mining
    亚商投资顾问 早餐FM/1123 加快构建与国际相衔接的金融制度体系和监管模式
    面试官问:Go 中的参数传递是值传递还是引用传递?
    java.util.ConcurrentModificationException异常原因及解决方法
    MyBatis-plus+注解形式实现项目与数据库绑定动态更新
    Mysql 设计数据表的原则
    Android11 framework Handler
    团队建设构想之测试系统篇--mediawiki部署
    mybatis笔记 映射配置文件
    基于springboot、springcloud的集成大屏、权限管理的后台框架
  • 原文地址:https://blog.csdn.net/fox9916/article/details/133691681