【精准打击】logback.xml从入门到了解

RT

最近在学习总结logback的一些知识,不知道你们是何感觉,反正我看了很多文章之后,印象总是不深刻。所谓“好记性不如烂笔头”,所以就干脆写个blog,顺带学习一下。另外你们懂的,就像LOL王者大佬永远无法预判青铜仔的操作一样,只有“菜鸡才知道菜鸡”的想法、痛点

阅读对象

  • logback.xml配置小白

温馨提示

  1. 本文总共有5912个字,预计耗时15分钟可以看完
  2. 所有标题带“*”的皆为重点知识,一定要理解
  3. 本文只是简单的介绍每个标签的意思,但我可以保证,通过本文你基本能够在生产项目上使用、配置logback日志框架了。

*读前须知

什么是logback?

答:logback是一个非常好用,且流行的日志框架。 面对当下java环境日志产品的内卷(4个Log产品,3个Log接口,非常驳杂),如果你对”应该使用什么日志接口“没什么概念,推荐直接使用 logback+slf4j的日志组合!

*logback日志的核心是什么?

答:关于Logback日志的核心,我们只需要了解3个单词:Logger(记录器),Appenders(附加器),Layout(布局)

  • Logger:记录器,是我们在编写logback.xml文件的时候,configuration下的基本标签。它的作用,等价于如下代码
//import ch.qos.logback.classic.Logger;  这是org.slf4j.Logger的一个实现示例
//import org.slf4j.LoggerFactory;
Logger logger = (Loggger)LoggerFactory.getLogger(TestRestFulController.class);

准确来说,当我们在logback-spring.xml下这样写的时候,等价于上面这条语句:

<configuration>
  <logger name="com.this.is.a.example.name"/>
</configuration>
  • Appender:有道翻译一下,他的意思是“附加器”,“输出目的地”,“输出源”。到了这里其实就不难理解了,顾名思义,它表示的是:日志输出目的地、输出源、输出媒介。那我们日志输出的目的地有什么?是什么?无非就是“控制台”、“某个指定的日志文件”呗。
  • Layout:暂时不介绍。其实核心是上面两个元素

*logback.xml文件标签解析

下面是一个简单的logback.xml文件解析,请仔细阅读,关键内容就在里面了,并且已经写了注释

<?xml version="1.0" encoding="UTF-8" ?>
<!--
configuration是logback的根标签
scan="true" 表示配置文件发生了改变会自动加载
scanPeriod="60 seconds" 检测配置文件修改的时间间隔,默认的单位是毫秒,这里我们设置的表示每分钟检测
debug="false" debug如果设置为true,表示我们会打印出来logback自身实时的运行信息,很显然我们是不需要的,人家成熟的软件比咱小辣鸡写的好多了
-->
<configuration
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNameSpaceSchemaLocation="logback.xsd"
        scan="true"
        scanPeriod="60 seconds"
        debug="false">

    <!--
    定义一些常量,方便后续使用
    1、日志默认打印格式
    name:DEFAULT_LOG_PATTERN。 表示定义的常量名叫DEFAULT_LOG_PATTERN,后面可以通过el表达式使用这个常量。
    value解析:
        %d{yyyy-MM-dd HH:mm:ss.SSS}:定义一条日志的展示时间
        %-5level:表示空出5个空格
        %thread:表示执行日志的线程
        %logger{40}:显示我们在哪个类(全限定名)里面记录日志,后面的{40}表示这个类名展示的最大长度是40
        %msg:表示我们的日志信息
        %n:表示换行
    -->
    <property name="DEFAULT_LOG_PATTERN"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%thread] %logger{40} : %msg%n"/>

    <!--    定义日志的输出路径-->
    <property name="FILE_PATH" value="F:\\log"/>

    <!--
    2、定义日志输出的媒介
    我们知道,日志的输出是有级别的,优先级从低到高分别是:trace < debug < info < warn < error
    -->
    <!--
    2.1、定义console的日志打印,即控制台。注意,这里的媒介是【控制台】,我们再联系一下最上面提到的Appender的概念
    name="consoleLog":定义一个名字叫做"consoleLog"的日志附加器
    class="ch.qos.logback.core.ConsoleAppender":表示日志附加器采用的策略是ConsoleAppender。即打印到控制台
    -->
    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 默认情况下,每个日志事件都会立即刷新到基础输出流。 这种默认方法更安全,因为如果应用程序在没有正确关闭appender的情况下退出,则日志事件不会丢失。
        但是,为了显着增加日志记录吞吐量,您可能希望将immediateFlush属性设置为false -->
        <immediateFlush>false</immediateFlush>
        <encoder>
            <!--输出格式,上面声明的常量-->
            <pattern>${DEFAULT_LOG_PATTERN}</pattern>
            <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--
    2.2、定义debug级别的日志输出,并且采用RollingFileAppender表示日志会滚动打印。注意,这里的媒介是【文本文件】
    name="debugLog":定义一个名字叫做"debugLog"的日志附加器
    class="ch.qos.logback.core.rolling.RollingFileAppender":表示日志附加器采用的策略,以滚动文件形式记录
    -->
    <appender name="debugLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--定义文件的路径-->
        <file>${FILE_PATH}/debug.log</file>
        <!--定义日志滚动策略,TimeBasedRollingPolicy是一个基于时间的滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            设置按每天的方式来生成文件
            如果把%d{yyyy-MM-dd}换成%d{yyyy-MM-dd_HH_mm}则表示按每分钟来生成。(PS:文件名不能有空格)
            log.gz:gz则表示自动压缩日志文件,不需要压缩,则不要以gz结尾
            -->
            <fileNamePattern>${LOG_PATH}/debug-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
            <!--设置文件最搭保存的历史数据,这里默认30天-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!--定义日志输出的格式,上面声明的常量-->
        <encoder>
            <pattern>${DEFAULT_LOG_PATTERN}</pattern>
        </encoder>
        <!--        定义日志记录的过滤器,很显然,在这里我们当然选择“级别”过滤器-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--定义debug级别-->
            <level>DEBUG</level>
            <!--如果匹配,则同意打印-->
            <onMatch>ACCEPT</onMatch>
            <!--如果不匹配,则拒绝打印-->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 2.3、定义info级别的日志输出,并且采用RollingFileAppender表示日志会滚动打印-->
    <appender name="infoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--定义文件的路径-->
        <file>${FILE_PATH}/info.log</file>
        <!--定义日志滚动策略,TimeBasedRollingPolicy是一个基于时间的滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            设置按每天的方式来生成文件
            如果把%d{yyyy-MM-dd}换成%d{yyyy-MM-dd_HH_mm}则表示按每分钟来生成。(PS:文件名不能有空格)
            log.gz:gz则表示自动压缩日志文件,不需要压缩,则不要以gz结尾
            -->
            <fileNamePattern>${LOG_PATH}/debug-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
            <!--设置文件最搭保存的历史数据,这里默认30天-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!--定义日志输出的格式-->
        <encoder>
            <!--定义日志输出的格式,上面声明的常量-->
            <pattern>${DEFAULT_LOG_PATTERN}</pattern>
        </encoder>
        <!--        定义日志记录的过滤器,很显然,在这里我们当然选择“级别”过滤器-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--定义info级别-->
            <level>INFO</level>
            <!--如果匹配,则同意打印-->
            <onMatch>ACCPET</onMatch>
            <!--如果不匹配,则拒绝打印-->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--
    根记录器(项目所有的日志都会经过这里)
    其实,日志的记录器就像是管道设计一样。字符流进来的时候,会一一通过<appender-ref>设置的管道中,然后根据设置的条件(<filter>标签),匹配则输出
    -->
    <root level="info">
        <appender-ref ref="consoleLog" />
    </root>

    <!--
    PS:这里有一个重重重重重重重重重重重重重重重重点,也是我之前没理解的点
    <logger>跟<root>是什么关系呢?父子关系!(大哥们这个是java代码写的一个api,xml只是约定一些配置!约定!!配置!!understand??)
    <logger>继承于<root>,所以,当<logger>没有指定level的时候,会自动继承<root>标签的level属性
    所以,日志记录的过程,就是在走职责链的过程,即一一通过logger过滤器
    -->
    <!--
    配置我们自己写的代码的日志记录器
    name="com.shen.boot":表示对应包里面的类代码产生的日志才会被下面的记录器记录,否则不会
    level="debug":表示我们的日志记录的级别是debug
    additivity="true":表示我们自定义的记录器日志输出
    -->
    <logger name="com.shen" level="debug" additivity="true">
        <appender-ref ref="debugLog" />
    </logger>
    <logger name="com.shen.boot" level="debug" additivity="true">
        <appender-ref ref="debugLog" />
        <appender-ref ref="infoLog" />
    </logger>
</configuration>

我知道,应该有不少人没有耐心阅读上面这个文件,但我告诉你,B也要B自己看完,里面我加了很多注释,基本上都是必要的内容。自觉点,赶紧回头再看一遍
以上内容都看完了吧,我想你也许有如下疑问,下面还是用我最喜欢的问答形式解答疑问。

日志记录的内部流程是怎样的?

答:如下图所示,用一个简单的流程图表示:
logback日志内部处理流程图
上图有两点需要补充:(我希望你们最好知道“职责链”这个设计模式,可以更好的了解。设计模式传送门

  1. logger过滤器,里面的各个过滤器是如何排序,并且传递的?他们是自下而上,逐级调用的,如下图所示:
    在这里插入图片描述
    我相信这个已经很清晰了吧?这张图也说明了additivity这个属性的用法。
  2. appender过滤器里面的逻辑是什么?
    答:过滤器嘛,逻辑不就是逐个调用吗,至于在这个appender会不会写日志,就是根据你在appender里面的配置咯。如下,你的infoLog配置不就是”只要info级别“的日志吗
	<!--infoLog的filter片段-->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--定义info级别-->
            <level>INFO</level>
            <!--如果匹配,则同意打印-->
            <onMatch>ACCPET</onMatch>
            <!--如果不匹配,则拒绝打印-->
            <onMismatch>DENY</onMismatch>
        </filter>

root标签跟logger标签的关系如何理解?

答:root跟logger之间是父子关系,logger继承于root。细心的朋友肯定看到我在xml文件中的注释了,他们就是用java代码写的,这两个之间就是logger类继承了root类

感谢

来自B站的V哥教程 logback小白入门课程
以及一些CSDN大佬的博客,查阅了不少资料,但这次是第二次总结了,然后第一次总结的时候没记录出处,所以没办法溯源了

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

验证码有毒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值