作者:明明如月前辈\链接:https://juejin.cn/post/711704...一、背景在日常开发中,为了方便调试排查,通常会打印很多INFO级别的日志.随着访问量的增加,不小心某天某个日志文件的大小超过了一定的阈值(比如5G),于是收到优化日志大小的告警,不优化反馈给主管一定时间内,尴尬...过多的日志很容易导致一些运维操作消耗机器性能,比如日志文件检索、数据收集、磁盘清理等。那么,原木瘦身的常见思路有哪些呢?本文根据一个具体案例来谈谈我的看法。推荐一个开源免费的SpringBoot最全教程:https://github.com/javastacks/spring-boot-best-practice2.日志瘦身方法2.1只打印必要的日志有时候为了测试方便,很多INFO级别是临时打印的日志。对于此类日志,可以在项目上线前删除不需要的日志或者调整为DEBUG级别。但是,在某些场景下,某些日志可以打印为DEBUG或INFO。INFO级别打印占用空间,在线检查问题时需要DEBUG级别打印。我应该怎么办?我们可以修改日志工具类,支持在上下文中传递某个开关(普通调用没有这个开关,传递公司的Tracer或者RPC上下文),可以将DEBUG日志临时提升到INFO等级。伪代码如下:if(log.isDebugEnable()){log.debug(xxx);}elseif(TracerUtils.openDebug2Info()){log.info("[debug2info]"+xxx);}这样,一些在纠结是否将日志打印成INFO日志,会打印成DEBUG级别的日志,检查问题时会自动升级为INFO日志。为了避免误解,DEBUG提升INFO日志与普通INFO日志区别开来,增加了类似[debug2info]的日志前缀。当然你也可以搞一些其他的表演操作,这里只是举个例子,请举一反三。2.2合并打印一些可以合并的日志,可以考虑合并。如果前后打印IN??FO日志同样的方法:INFO[64-bittraceId]XXXServicebeforeexecutionsize=10INFO[64-bittraceId]XXXServiceafterexecutionsize=4可以合并为一个:INFO[64-bittraceId]XXXService执行前size=10执行后size=42.3对某条log进行简化&缩减&压缩是非常有必要的,但是打印出来的对象有点大。如果能够满足排查需要,我们可以:(1)选择只打印其ID(2)创建一个只保留关键字段的日志专用对象,将其转换为日志专用对象,然后打印。(3)可以使用缩写,如write简化为w,read简化为r,execute简化为e等;比如pipeline里面有20个核心bean,打印日志的时候可以用不同的数字来代替完整的bean名,比如S1,S2,虽然不是那么直观,但是不仅可以查问题,还可以也减少了日志的数量。3.优化案例3.1场景描述一个业务场景涉及到很多bean。为了重用一些公共逻辑,这些bean继承自一个抽象类。在抽象类中,定义了执行bean前后的一些通用逻辑,比如执行前后打印当前pipeline中item的个数。最后一个bean需要在进行结果转换后打印出结果。3.2优化分析3.2.1只打印必要的日志(1)由于当前bean的执行相当于前一个bean的执行,所以只打印执行后的日志,执行前的INFO日志可以删除或更改toDEBUG(onlyprintNecessarylog)(2)通常只有在执行前后大小不一致的情况下才会出现问题,所以可以在执行后打印日志前加上判断,如果执行前后大小相同,它不会被打印出来。(只打印必要的日志)伪代码如下:if(sizeBefore!=sizeAfter){log.info("service:{},beforesize:{},aftersize:{}",getName(),sizeBefore,sizeAfter)}推荐一个开源免费的SpringBoot最全教程:https://github.com/javastacks/spring-boot-best-practice这个trick很有效,因为大多数bean执行前后的大小就是同样,它不会打印此日志。并且假设之前有20条,这个日志需要打印20次,改进后可能只需要打印2-3次。3.2.2日志合并(2)为了方便检查问题,需要先打印执行前的大小,然后将执行前的大小记录在内存中,执行后打印日志时打印执行前的大小。(合并打印)伪代码如下:log.info("service:{},执行前大小:{}",getName(),sizeBefore)log.info("service:{},执行后大小:{}",getName(),sizeBefore,sizeAfter)mergedlog.info("service:{},beforesize:{},aftersize:{}",getName(),sizeBefore,sizeAfter)3.2.3日志精简对于最后result,将result对象(比如XXDTO)转换成只包含id、title等关键信息的log对象(XXSimpleLogDTO),转换成log对象后打印出来。log.info("resultId:{}",result.getId());或log.info("result:{}",toSimpleLog(result));3.3效果评估日志一天产生5G左右,这里的百分比80%左右是打印执行前后的大小,10%左右是打印最终结果,还有一些其他的日志。通过上述方法优化后,每日日志量小于1G。在满足故障排除需求和实现日志瘦身之间存在权衡。4.总结日志瘦身需要权衡,排查必要的日志尽量保持精简。可以通过删除不需要的日志、合并日志、简化日志等方式进行优化。我们也可以进行一些花哨的操作,支持在线DEBUG临时增加INFO(当然也可以使用arthas)来协助我们排查问题。您还有哪些其他好的减肥日记技巧?欢迎在文末评论交流。近期热点文章推荐:1.1000+Java面试题及答案(2022最新版)2.厉害了!Java协程来了。..3.SpringBoot2.x教程,太全面了!4.不要用爆破爆满画面,试试装饰者模式,这才是优雅的方式!!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!
