logback没有输出更高一级的日志

问题:

logback和log4j一样,属于日志输出系统。当你使用logback的时候,你是否遇到过当你配置了INFO日志级别之后,输出的只有一种级别的日志(如:INFO),warn、error更高级别的日志没有输出,这是为何呢?我在使用SpringBoot中的logback就遇到了这个问题。

原因:

我的配置文件logback.xml是这样写的:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <!-- 控制台打印日志的相关配置 --> 
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <!-- 日志格式 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - [%class:%line] - %m%n</pattern>
    </encoder>
    <!-- 日志级别过滤器 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <!-- 过滤的级别 -->
      <level>INFO</level>
  	  <!-- 匹配时的操作:接收(记录) -->
      <onMatch>ACCEPT</onMatch>
      <!-- 不匹配时的操作:拒绝(不记录) -->
      <onMismatch>DENY</onMismatch>
    </filter>
  </appender>


  <!-- 基于dubug处理日志:具体控制台或者文件对日志级别的处理还要看所在appender配置的filter,如果没有配置filter,则使用root配置 -->
  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

结果发现日志打印只有INFO级别,高于INFO或者低于INFO的都没有打印。我们知道很多时候我们要求是高于INFO的(如:WARN、ERROR)都要打印的。问题在哪里呢?(问题就在于网上拷贝了被人的xml配置文件)

查看filter:ch.qos.logback.classic.filter.LevelFilter类

public class LevelFilter extends AbstractMatcherFilter<ILoggingEvent> {

    Level level;

    @Override
    public FilterReply decide(ILoggingEvent event) {
        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }
        //*****问题就在这里*****//
        if (event.getLevel().equals(level)) {
            return onMatch;
        } else {
            return onMismatch;
        }
    }

    public void setLevel(Level level) {
        this.level = level;
    }

    public void start() {
        if (this.level != null) {
            super.start();
        }
    }
}

我们发现代码中只要日志级别level不是绝对相等(.equals)就判断为onMismatch,这显然是不符合要求的。

怎么解决呢?

解决方案:

查看ch.qos.logback.classic.filter包下还有另一个filter : ThresholdFilter,使用这个作为过滤器,不需要配置<onMatch>和<onMismatch>,如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <!-- 控制台打印日志的相关配置 --> 
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <!-- 日志格式 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - [%class:%line] - %m%n</pattern>
    </encoder>
    <!-- 日志级别过滤器 -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <!-- 过滤的级别 -->
      <level>INFO</level>
    </filter>
  </appender>


  <!-- 基于dubug处理日志:具体控制台或者文件对日志级别的处理还要看所在appender配置的filter,如果没有配置filter,则使用root配置 -->
  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

测试结果满足要求。

再看这个ThresholdFilter代码:

public class ThresholdFilter extends Filter<ILoggingEvent> {

    Level level;

    @Override
    public FilterReply decide(ILoggingEvent event) {
        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }
        //这里是问题的关键
        if (event.getLevel().isGreaterOrEqual(level)) {
            return FilterReply.NEUTRAL;
        } else {
            return FilterReply.DENY;
        }
    }

    public void setLevel(String level) {
        this.level = Level.toLevel(level);
    }

    public void start() {
        if (this.level != null) {
            super.start();
        }
    }
}

我们发现ThresholdFilter中level用了isGreaterOrEqual(),这是满足要求的。

说明:

这里只是分享自己遇到的一个问题,并不是要说明LevelFilter有bug,或许这个filter是为了满足输出指定级别的日志,而不是高于某个级别的日志。因此当你想输出高于某个级别的日志的时候,建议你使用ThresholdFilter。

最后上传一个logback.xml配置文件,方便日后查阅

logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <!-- 控制台打印日志的相关配置 --> 
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <!-- 日志格式 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - [%class:%line] - %m%n</pattern>
    </encoder>
    <!-- 日志级别过滤器 -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <!-- 过滤的级别 -->
      <level>INFO</level>
    </filter>
  </appender>

	<!-- 文件保存日志的相关配置 --> 
  <appender name="INFO-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
     <!-- 保存日志文件的路径 -->
    <file>D:/app_logs/SpringBoot-Logging.log</file>
    <!-- 日志格式 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - [%class:%line] - %m%n</pattern>
    </encoder>
    <!-- 日志级别过滤器 -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <!-- 过滤的级别 -->
      <level>INFO</level>
    </filter>
    <!-- 循环政策:基于时间创建日志文件 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- 日志文件名格式 -->
      <fileNamePattern>SpringBoot-Logging.%d{yyyy-MM-dd}.log</fileNamePattern>
      <!-- 最大保存时间:30天-->
      <maxHistory>30</maxHistory>
    </rollingPolicy>
  </appender>
  
  <!-- 文件保存日志的相关配置 --> 
  <appender name="ERROR-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
     <!-- 保存日志文件的路径 -->
    <file>D:/app_logs/SpringBoot-Logging-error.log</file>
    <!-- 日志格式 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - [%class:%line] - %m%n</pattern>
    </encoder>
    <!-- 日志级别过滤器 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <!-- 过滤的级别 -->
      <level>ERROR</level>
      <!-- 匹配时的操作:接收(记录) -->
      <onMatch>ACCEPT</onMatch>
      <!-- 不匹配时的操作:拒绝(不记录) -->
      <onMismatch>DENY</onMismatch>
    </filter>
    <!-- 循环政策:基于时间创建日志文件 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- 日志文件名格式 -->
      <fileNamePattern>SpringBoot-Logging-error.%d{yyyy-MM-dd}.log</fileNamePattern>
      <!-- 最大保存时间:30天-->
      <maxHistory>30</maxHistory>
    </rollingPolicy>
  </appender>

  <!-- 基于dubug处理日志:具体控制台或者文件对日志级别的处理还要看所在appender配置的filter,如果没有配置filter,则使用root配置 -->
  <root level="debug">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="INFO-OUT" />
    <appender-ref ref="ERROR-OUT" />
  </root>
</configuration>

author:蓝何忠

email:lanhezhong@163.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值