利用logback 设置不同包下的日志级别

 更新时间:2020年12月03日 15:42:23   作者:小杰68  
这篇文章主要介绍了利用logback 设置不同包下的日志级别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

1、实现效果:项目的整体的日志打印级别为ERROR,但在某个包下或某个类想打印INFO级别的日志。

2、配置:

FILE是ERROR级别日志打印;

SPECIAL 是INFO级别日志打印;

FILE与SPECIAL唯一不同是日志保存路径不同,其它策略相同;

通过 logger标签指定包路径或类路径并引用SPECIAL;

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <contextName>test</contextName>
 <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
   <fileNamePattern>${catalina.home}/logs/test/test.%d.%i.log</fileNamePattern>
   <maxHistory>30</maxHistory>
   <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    <maxFileSize>10MB</maxFileSize>
   </timeBasedFileNamingAndTriggeringPolicy>
  </rollingPolicy>
  <encoder>
   <pattern>%d %p (%file:%line\)- %m%n -[%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}]</pattern>
   <charset>UTF-8</charset>
  </encoder>
 </appender>

 <appender name="SPECIAL" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
   <fileNamePattern>${catalina.home}/logs/test/special/special.%d.%i.log</fileNamePattern>
   <maxHistory>30</maxHistory>
   <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    <maxFileSize>10MB</maxFileSize>
   </timeBasedFileNamingAndTriggeringPolicy>
  </rollingPolicy>
  <encoder>
   <pattern>%d %p (%file:%line\)- %m%n -[%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}]</pattern>
   <charset>UTF-8</charset>
  </encoder>
 </appender>

 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
   <pattern>%d %p (%file:%line\)- %m%n </pattern>
   <charset>UTF-8</charset>
  </encoder>
 </appender>
 <!--打印SQL-->
 <logger name="daoLog" level="ERROR" />
 <!-- 记录special操作日志 -->
 <logger name="aaa.bbb.ccc.DemoService" level="INFO" >
  <appender-ref ref="SPECIAL"/>
 </logger>

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

补充知识:logback框架使用误区 如何将所有包的ERROR级别日志集中打印到一个日志文件中

早就想写这个事情了,起因是自己想写一个东西,其中使用logback日志框架记录日志

打算 将所有包的ERROR及以上级别日志打到一个文件中,各个包下的日志打到对应包的文件中。

起初写的xml配置类似于这样:

<!-- 其中一个appender,其他appender与其相同 ,只有name、file和fileNamePattern不同-->
<appender name="ALL-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
 <file>all-error.log</file>
 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  <fileNamePattern>
   ${log_dir}/all-error.%d{yyyy-MM-dd}.%i.log
  </fileNamePattern>
  <maxFileSize>100MB</maxFileSize>
  <maxHistory>60</maxHistory>
  <totalSizeCap>20GB</totalSizeCap>
 </rollingPolicy>
 <encoder>
  <pattern>
   %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
  </pattern>
 </encoder>
</appender>
<logger name="com.some.package1" level="INFO" additivty="true">
 <appender-ref ref="appender-1"/>
</logger>
<logger name="com.some.package2" level="INFO" additivty="true">
 <appender-ref ref="appender-2"/>
</logger>

<logger name="com.some" level="ERROR" additivty="true">
 <appender-ref ref="ALL-ERROR"/>
</logger>

然而运行后却发现,这样配置后的,并没有达到预期目标。

反而,所有INFO及以上的信息,不仅在appender appender-1和appender-2对应的日志文件中有,在appender为ALL-ERROR对应的日志文件中也都有,这是为何?

追踪了一下断点,发现如下代码片段:

/**
 * Invoke all the appenders of this logger.
 * 
 * @param event
 *   The event to log
 */
public void callAppenders(ILoggingEvent event) {
 int writes = 0;
 for (Logger l = this; l != null; l = l.parent) {
  writes += l.appendLoopOnAppenders(event);
  if (!l.additive) {
   break;
  }
 }
 // No appenders in hierarchy
 if (writes == 0) {
  loggerContext.noAppenderDefinedWarning(this);
 }
}

这段代码来自logback的 ch.qos.logback.classic.Logger文件,是最终决定日志内容输出在哪里的代码。

从这段代码我们可以发现:

1. logback会找到第一个符合日志级别要求的logger,然后将日志内容输入到这个logger下配置的appender中。举例来说:如果有一个com.some.package1内的类的INFO级别日志,那么首先会找到logger com.some.package1,然后找到logger下配置的appender appender-1;最后根据appender-1的配置,将日志内容输出到appender-1配置的文件中。

2. 之后,logback根据additivty检查logger是否允许继承,如果配置为true(默认为true),则查找上一级logger(实际是按照以包名为name查找上一层包的logger),找到logger后,不再判断logger配置是否符合日志级别要求,直接找到对应的appender,将日志内容输出。

这就带来了一个问题,位于低层次包的logger,在接收到日志后,不仅会把它输出到自身的appender中,还会将其传递给位于高层次包logger的appender中,无论高层次包logger配置的日志级别是什么。正因为如此,所以我打算将所有包的ERROR级别 日志输出到一个文件的目的没有实现,反而所有INFO及以上级别的日志都输出了。

按照这个思路,如果logger com.some.package1和com.some.package2日记级别为ERROR,而logger com.some日志级别为INFO的话,是否所有INFO及以上级别的日志都可以记入logger com.some对应的appender下,而ERROR及以上级别的日志会记入logger com.some.package1和com.some.package2呢?测试证明,是这样。

知道了为什么上面的配置达不到目的,接下来要考虑的是,借助什么方式实现这个需求呢?

logback提供了实现需求的方式:借助Filter来做:

既然logger无法判断日志级别,那我们可以在对应的appender里判断日志级别。

logback的过滤器使用起来可以达到对每一条日志的DENY、ACCEPT和NEUTRAL。

根据文章开始提出的需求,我们需要的是一个绑定appender的,过滤日志等级的filter,那么ch.qos.logback.classic.filter.ThresholdFilter正好是我们需要的。通过加入如下配置,appender ALL-ERROR将只能接受ERROR及以上的日志:

<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
 <level>INFO</level> 
</filter> 

完整的xml配置如下,仅改变了filter的部分,就实现了需求:

<!-- 其中一个appender,其他appender与其相同 ,只有name、file和fileNamePattern不同,并且没有filter的标签-->
<appender name="ALL-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
 <file>all-error.log</file>
 <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
  <level>ERROR</level> 
 </filter> 
 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  <fileNamePattern>
   ${log_dir}/all-error.%d{yyyy-MM-dd}.%i.log
  </fileNamePattern>
  <maxFileSize>100MB</maxFileSize>
  <maxHistory>60</maxHistory>
  <totalSizeCap>20GB</totalSizeCap>
 </rollingPolicy>
 <encoder>
  <pattern>
   %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
  </pattern>
 </encoder>
</appender>
<logger name="com.some.package1" level="INFO" additivty="true">
 <appender-ref ref="appender-1"/>
</logger>
<logger name="com.some.package2" level="INFO" additivty="true">
 <appender-ref ref="appender-2"/>
</logger>

<logger name="com.some" level="ERROR" additivty="true">
 <appender-ref ref="ALL-ERROR"/>
</logger>

更多关于logback的Filter的讲解,请见

1. logback filter文档

以上这篇利用logback 设置不同包下的日志级别就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 设计模式系列之组合模式及其在JDK和MyBatis源码中的运用详解

    设计模式系列之组合模式及其在JDK和MyBatis源码中的运用详解

    这篇文章主要介绍了组合模式及其在JDK和MyBatis源码中的运用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • springboot项目打docker镜像实例(入门级)

    springboot项目打docker镜像实例(入门级)

    最近做个项目,我们想把自己的程序打包成镜像,并运行在docker容器中,本文主要介绍了springboot项目打docker镜像实例,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • Springboot配置返回日期格式化五种方法详解

    Springboot配置返回日期格式化五种方法详解

    本文主要介绍了Springboot配置返回日期格式化五种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 在SpringBoot中配置Thymeleaf的模板路径方式

    在SpringBoot中配置Thymeleaf的模板路径方式

    这篇文章主要介绍了在SpringBoot中配置Thymeleaf的模板路径方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 浅谈ArrayList和LinkedList到底谁更快

    浅谈ArrayList和LinkedList到底谁更快

    今天给大家带来的是关于Java的相关知识,文章围绕着ArrayList和LinkedList到底谁更快展开,文中有非常详细的介绍,需要的朋友可以参考下
    2021-06-06
  • spring-Kafka中的@KafkaListener深入源码解读

    spring-Kafka中的@KafkaListener深入源码解读

    本文主要通过深入了解源码,梳理从spring启动到真正监听kafka消息的这套流程,从spring启动开始处理@KafkaListener,本文结合实例流程图给大家讲解的非常详细,需要的朋友参考下
    2023-02-02
  • 图解如何在Spring Boot中使用JSP页面

    图解如何在Spring Boot中使用JSP页面

    这篇文章主要介绍了图解如何在Spring Boot中使用JSP页面,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • MyBatis处理mysql主键自动增长出现的不连续问题解决

    MyBatis处理mysql主键自动增长出现的不连续问题解决

    本文主要介绍了MyBatis处理mysql主键自动增长出现的不连续问题解决,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 详解Struts2拦截器机制

    详解Struts2拦截器机制

    这篇文章主要介绍了详解Struts2拦截器机制,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • shiro之记住登录信息

    shiro之记住登录信息

    Shiro提供了记住我(RememberMe)的功能,当关闭浏览器时下次再次打开还能记住你的信息,下面小编给大家分享shiro之记住登录信息的相关知识,感兴趣的朋友一起看看吧
    2017-09-09

最新评论