首页 > 技术文章 > 深入理解Logger日志——日志等级动态调整方法

zhouguanglin 2020-10-15 09:53 原文

深入理解Logger日志——日志等级动态调整

  不用多说在之前的文章也提及过,项目中日志的重要性,但有时候日志又会产生另一种伤害或者排除问题信息不全,如:

  • 某些业务突然暴涨导致日志爆满压爆服务内存,会直接造成系统性能下降,极端情况下,甚至导致系统宕机。
  • 在一些线上问题的排查中,因为缺少很多日志信息,debug日志又无法打开,以至于只能不断的各种方式排查或停下服务添加日志,让人很着急。

  在这种背景下,为了兼顾性能和快速响应线上问题,这时日志级别动态调整的需求是非常需要的,可以在需要解决线上问题时,实时调整线上日志输出级别,获取全面的Debug日志,帮助工程师提高定位问题的效率,这个真的很香。

  目前需要主要功能有:

  • 项目的整体日志等级调整,面对整体大业务形式。
  • 项目中某个单一类的日志等级调整,对于小问题,单一业务的处理非常好,不影响其他业务日志。  

 使用场景

  有了这个需求灵感,上网一查,有了,美团技术团队做了一个组件值得参考,日志级别动态调整——小工具解决大问题

  Copy他们的使用场景描述一下:

场景一

  业务依赖复杂。某一时刻,依赖的下游服务故障,导致请求大量超时,尤其是像外卖这种集中性特别明显的业务,平均每秒QPS在8000以上,1分钟的故障就会集中产生大量的错误日志,导致磁盘IO急剧提高,耗费大量CPU,进而导致整个服务瘫痪。如果该业务不能立即降级,怎么办?

  从代码级别解决问题到发版上线,暂且不说流程长、操作麻烦,同时还存在引入其它故障的高风险。如果系统恰好使用Log4j版本,在极短时间内打印出了海量错误日志,会快速耗尽Buffer区内存,从而拖慢主线程,造成服务性能整体下降,甚至还没有来得及修复问题,海量日志已经拖垮服务,造成服务宕机,损失惨重。

场景二

  大量的订单、结算等客诉问题反馈过来,一线工程师大量精力埋没于排查问题中,而排查定位问题的最终手段仍然是依赖线上日志。由于链路较长,任一日志的缺失,都给问题的排查带来极大的障碍,面对运营的催促,怎么办?

  工程师为了以后排查问题的方便,在任一可能出现异常的地方,都会打印出关键日志,然后发版上线。但好不容易解决了本次问题,还没来得及收获喜悦,就又面临着一个新问题,那就是场景三。

场景三

  由于线上业务系统默认日志打印级别是INFO级别,为了排查问题方便,调试型日志都以该级别打印出来。这样的话给系统带来了额外的负担,在高峰期大量调试日志时会拖慢系统性能,增大出故障的风险,怎么办?

  一方面要快速响应业务,另一方面要兼顾系统性能,能不能两方面兼顾?我们的动态调整日志级别工具正是为了解决这种痛点。

能解决哪些问题

  1. 日志降级。 兼容Log4j、Log4j2和Logback主流日志框架,如果遇到场景一,可以通过我们的日志工具,快速调整日志输出级别,降低系统日志的输出,从而达到日志降级的效果,同时能够给RD争取充裕的排查问题时间。
  2. 规范日志级别滥用,帮助工程师快速定位解决线上问题。 使用日志级别动态调整组件,可以实时动态调整线上服务的日志打印级别,调试型日志可以使用低级别打印出,减轻线上服务的负载压力。遇到排查问题时,可以临时将日志级别调低,快速得到精准化的日志信息,排查解决问题。

 日志等级动态调整四种方法

  经过多次的调查,发现对日志等级的动态调整有很多种方式每一种都有其独特的好处,值得研究。以下日志等级调整以Logback框架为例子,其他的可以参考进行相应的改造互通。

第一种方式:配置文件的自动检测更新

  利用Logback中的配置文件,开启logback.xml的自动扫描 scan = true 来更新日志的配置。

  实践感受:个人感觉手动改配置文件有点恐怖不太安全,只能说可以做急救的一种方式,有可能不好使,不太好设置。

第二种方式:Spring Actuator 监控

  项目中若是SpringBoot为框架的可以引入 spring-boot-starter-actuator 监控依赖,配合好Web,内部有非常多的功能,其中包括日志等级的查看、修改。

  参考文章对Actuator进行相应的介绍:

  针对Loggers做一些介绍:

  Actuator:获取各类监控配置的地址,如下获取Loggers的数据

  

  Loggers endpoint:可以通过GET访问 http://localhost:8080/actuator/loggers 获取所有的Loggers日志对象,配置的loggers的列表和相关的日志等级。

  

  指定获取某个Logger对象信息GET:http://localhost:8080/actuator/loggers/{name}

   指定修改某个日志的日志等级POST:http://localhost:8080/actuator/loggers/{name}

   实践感受:这个方式非常的不错,内容很丰富,就差个页面了,不过这个还是存在一些安全性的问题,需要结合Spring-Security,来配置获取权限,增加安全校验。

  推荐看手把手带你入门 Spring Security!根据项目情况相应配置

第三种方式:Spring Boot Admin 监控管理

  集成Spring Cloud 的Spring Boot Admin 来动态调整日志等级,若是项目为SpringCloud的非常香,其实这个主要是spring-boot-starter-actuator的升级版而已,在外部出现来UI界面,内部还是调用其 actuator/接口进行相应操作。

  推荐参考文章:

  主要界面:

 

  在Spring Boot Admin 中的Logger动态调整,实时反馈到了日志中

   此方法的测试中主要需要注意的是,在Client中Actuator是否与Spring Security配合进行鉴权了,进行相应调整。

   实践感受:第一感觉是Spring家族太强大了,不过这个也是需要配合这SpringCloud一起使用,看看项目是否适合,这也是趋势所在。

 第四种方式:自定义Logger API

  这种方式主要是获取日志实现框架的Logger类,去调整(setLevel)日志等级,因为Slf4j的API中的Logger没有提供相关的日志等级调整,需要去具体的实现类中操作。

  每一种日志实现框架中都有自己的方式获取Loggers的日志集合,若是需要适应不同项目不同的日志类型,需要做好组件的兼容性,个人建议整体项目系统保持统一日志架构。

  推荐一下美团技术团队所做的Github地址:https://github.com/sekift/change-log-level (这个自己造轮子,不会的用上面的Spring Actuator 就很好)

  他们有两种整体和module形式,可根据所需参考所适配。

  

   我个人参考对美团的日志调整项目做了相应的调整,适应自己的当前情况,在下一个文章做具体的介绍。

  项目结构图:

 

 

 具体使用方式

  引入jar包,这个包是个人的,可以根据个人喜爱,随意操作,放在maven私有仓库中

        <dependency>
            <groupId>com.xxxxx.apr</groupId>
            <artifactId>logger</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

  测试中调用:

 

   敬请期待...

  Githubhttps://github.com/LiZhouYan/logger-util

 

推荐阅读