Logback日志小记

日志系统

Java中常用的日志系统有很多,比如logging、log4j、logback等等。广泛使用的是logback+slf4j,同时代码里加入Lombok的插件,这样快速方便的使用日志。

一、包引入

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

这个包已经包括了logback-core、slf4j-api,所以只要包含一个包就可以了。

二、配置文件

Logback默认配置的步骤:

  • 检查是否配置了系统变量logback.configurationFile,有则使用此配置的路径中的logback配置文件
  • 在classpath下查找 logback-test.xml文件
  • 第二步没找到,则在classpath下查找logback.groovy文件
  • 第三步没找到,则在classpath下查找logback.xml文件,推荐
  • 第四步没找到,通过spi机制,查找META-INF\services\ch.qos.logback.classic.spi.Configurator 配置的 com.qos.logback.classic.spi.Configurator(此类在logback-classic jar中)的实现类,调用他的configure方法进行配置。
  • 第五步没找到,使用默认的BasicConfigurator(实现了Configurator接口)进行配置。以上的寻找配置的代码在ch.qos.logback.classic.util.ContextInitializer.autoConfig中可以找到。

三、组件

LogBack
appender
logger
layout
  • logger:作为日志的记录器,拥有自己的日志级别。
  • appender:主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、PostreSQL、 Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。
  • layout:格式化日志的样式,可以搭载在不同的appender中。

四、配置文件例子

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="60 seconds">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <pattern><![CDATA[
				%-20(%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] ) %-5level %logger{80}[%L] - %msg%n
          ]]></pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <appender name="AppenderError" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${catalina.base}/logs/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${catalina.base}/logs/error.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <append>true</append>
        <encoder>
            <pattern><![CDATA[
                        %-20(%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] ) %-5level %logger{80} - %msg%n
                  ]]></pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    
    <appender name="AppenderInfo" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${catalina.base}/logs/info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${catalina.base}/logs/info.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <append>true</append>
        <encoder>
            <pattern><![CDATA[
                        %-20(%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] ) %-5level %logger{80} - %msg%n
                  ]]></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="AppenderDebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${catalina.base}/logs/debug.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${catalina.base}/logs/debug.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <append>true</append>
        <encoder>
            <pattern><![CDATA[
                        %-20(%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] ) %-5level %logger{80} - %msg%n
                  ]]></pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
    </appender>
    
    <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
    
    <logger name="com.demo.service" level="error"/>

    <root level="${log.level}">
        <appender-ref ref="AppenderError"/>
        <appender-ref ref="AppenderInfo"/>
        <appender-ref ref="AppenderDebug"/>
    </root>
</configuration>

1、configuration

配置的结构,以configuration包含块为文件,带有3个参数。

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

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

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

2、appender

日志输出的目的地,常用的有ConsoleAppender-输出到控制台FileAppender-输出到文件RollingFileAppender-滚动记录文件

2.1 ConsoleAppender-输出到控制台
  • <encoder>:对日志进行格式化。作用等同于layout
  • <target>:输出控制台日志,字符串 System.out 或者 System.err ,默认 System.out
2.2 FileAppender-输出到文件
  • <file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
  • <append>:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。
  • <encoder>:对日志进行格式化。作用等同于layout
  • <prudent>:如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认是 false。
2.3 RollingFileAppender-滚动记录文件

最为常见的日志方式。滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。这里的条件可以是时间、文件大小等等。

  • <file>、<append>、<encoder>和之前都一样
  • <rollingPolicy>指定滚动策略:TimeBasedRollingPolicy-基于时间的回滚、FixedWindowRollingPolicy-基于窗口滚动、SizeAndTimeBasedRollingPolicy-按照时间和大小滚动
  • <filter> 过滤策略,根据条件输出:LevelFilter-根据日志级别进行过滤、ThresholdFilter-过滤掉低于指定临界值的日志、 EvaluatorFilter-评估、鉴别日志是否符合指定条件

例子:

<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    	<fileNamePattern>/logback/log/test-%d{yyyy-MM-dd}.log</fileNamePattern>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
</appender>

时间回滚策略。

  • <FileNamePattern>设置滚动生成文件的格式,这里设置的精确到天,也就是按照天滚动,如果时间设置精确到秒,就按秒来滚动。
  • <maxHistory>设定最大的文件数,比如按天滚动,这里设置了30天,在第31天日志生成的时候,第一天的日志就会被删掉
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
        <fileNamePattern>/logback/log/test-%i.log</fileNamePattern>
        <minIndex>1</minIndex>
        <maxIndex>3</maxIndex>
    </rollingPolicy>
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
	    <maxFileSize>1MB</maxFileSize>
    </triggeringPolicy>
</appender>

固定文件大小回滚策略。

  • <fileNamePattern>定义文件名称的时候使用%i作为占位符,滚动后会数值替换
  • <minIndex> 开始的索引
  • <maxIndex> 最大索引,听说有最大值12,还没验证过
  • <triggeringPolicy> 触发器:SizeBasedTriggeringPolicy文件大小触发器,maxFileSize:最大文件大小
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
</appender>

固定文件大小和时间回滚策略。很多人认为TimeBasedRollingPolicy搭配SizeBasedTriggeringPolicy可以使用固定大小和时间的回滚,但是官网说了,这两个有冲突,会导致并不能按照原先的想法去做,必须使用SizeAndTimeBasedRollingPolicy的回滚策略。

  • <maxFileSize> 文件最大大小,每次当前日志文件在当前时间段结束之前达到maxFileSize时,将使用从0开始的递增索引进行归档。
  • <maxHistory> 最大周期数,您需要使用maxHistory属性指定要保留的周期数。
  • <totalSizeCap> 可选,控制所有存档文件的总大小。当超过总大小上限时,最早的档案将被异步删除。 totalSizeCap属性还需要设置maxHistory属性。此外,始终首先应用“最大历史记录”限制,然后应用“总大小上限”限制。
2.4 Filter

filter按照上诉的介绍,是appender的记入日志的过滤器。

filter过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一。返回DENY,日志将立即被抛弃不再经过其他过滤器;返回NEUTRAL,有序列表里的下个过滤器过接着处理日志;返回ACCEPT,日志会被立即处理,不再经过剩余过滤器。

过滤器被添加到appender中,为appender添加一个或多个过滤器后,可以用任意条件对日志进行过滤。 有多个过滤器时,按照配置顺序执行。

2.4.1 LevelFilter

级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。有以下子节点:

  • <level>:设置过滤级别
  • <onMatch>:用于配置符合过滤条件的操作
  • <onMismatch>:用于配置不符合过滤条件的操作
<appender name="AppenderDebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>DEBUG</level>
    <onMatch>ACCEPT</onMatch>   
    <onMismatch>DENY</onMismatch> 
  </filter>
</appender>

将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。

2.4.2 ThresholdFilter

临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。

<appender name="AppenderDebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>INFO</level>
  </filter>
</appender>

过滤掉所有低于INFO级别的日志。

2.4.3 EvaluatorFilter

求值过滤器,评估、鉴别日志是否符合指定条件。

  • <evaluator>:鉴别器,常用的鉴别器是JaninoEventEvaluator,也是默认的鉴别器,它以任意的java布尔值表达式作为求值条件,求值条件在配置文件解释过成功被动态编译,布尔值表达式返回true就表示符合过滤条件。evaluator有个子标签<expression>,用于配置求值条件。
  • <onMatch>:用于配置符合过滤条件的操作
  • <onMismatch>:用于配置不符合过滤条件的操作
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">   
  <filter class="ch.qos.logback.core.filter.EvaluatorFilter">         
    <evaluator> <!-- 默认为 ch.qos.logback.classic.boolex.JaninoEventEvaluator -->   
      <expression>return message.contains("billing");</expression>   
    </evaluator>   
    <OnMatch>ACCEPT </OnMatch>  
    <OnMismatch>DENY</OnMismatch>  
  </filter>   
</appender>   

过滤掉所有日志消息中不包含“billing”字符串的日志。

3、logger

<configuration debug="true" scan="true" scanPeriod="60 seconds">
    <logger name="com.example.logback.logger" level="info">
      	<!-- 指定输出的appender -->
        <appender-ref ref="logger_stdout"/>
    </logger>
</configuration>

可以根据logger中的name属性指定某个文件或者文件夹输出的日志级别,并通过appender-ref指定日志的输出appender。还有一个additivity属性,如果设置为false的话就不会向上传递。什么意思呢?就是你在name中指定地方产生日志,这个日志会根据当前的logger配置输出,如果additivity=true,并且有上一级(包括root级别),则向上传递,可能还会再打印一遍。

4、root

整个项目的根级别日志设置

 <root level="${logLevel}">
        <appender-ref ref="AppenderError"/>
        <appender-ref ref="AppenderInfo"/>
        <appender-ref ref="AppenderDebug"/>
 </root>

上面这种,想使用yml或者properties里的参数,就得将logback.xml更名成logback-spring.xml,因为spring先加载logback.xml然后再加载配置,然后再加载logback-spring.xml。

<configuration debug="false" scan="true" scanPeriod="60 seconds">
    <springProperty scope="context" name="logLevel" source="log.level"/>
</configuration>

五、案例

1、巧妙运用logger和root

<configuration debug="false" scan="true" scanPeriod="60 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <pattern><![CDATA[
				%-20(%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] ) %-5level %logger{80}[%L] - %msg%n
          ]]></pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
  
    <logger name="org.example.logback.logger" level="ERROR"/>

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

在上面这个配置中,在org.example.logback.logger包下的日志,日志级别是ERROR,但是没有appender,说明ERROR日志会被传到上级被记录,本logger不起任何作用。如果是INFO日志,因为和本级日志级别优先级低,所以被抛弃也不传送到上层。所以这种写法很好的限制某个包下日志级别,但又不阻碍其他包的日志传递。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值