有关日志打印的几点经验
前段时间,完善智能导航发送告警短信中短信太长接收不到的bug,牵涉出了日志打印的问题;日志打印这件事说小事小,说大也大,写好日志能方便自己调试代码和发现解决问题,以下就是有关日志打印自己总结的几点经验教训:
日志打印应该分层、分角度,一个好的日志不应该只打印与业务有关的日志。
日志打印应该从以下几个方面去打印:
模块运行日志:模块运行日志包括消息队列的监控、线程的运行状态。该日志应该以INFO级别打印,并且采用间隔打印,或叫做定时打印。以减少日志打印总量。从该角度可以反应出该模块是否有消息队列积压,是否所有线程都运行正常。消息队列的打印可以采用日下格式:
使用统一的关键字Monitor来标示模块运行日志。队列监控日志使用|队列名|消息放入速度|消息取出速度|消息放入个数|消息取出个数|当前队列消息个数|。线程监控日志使用|线程名|线程状态码|,线程状态码可以自己扩展。0表示正常1表示运行结束2表示线程阻塞。
09:16:59.347 INFO |Monitor|ReceiveTimerQueue|0/s|0/s|0|0|0|
09:16:59.347 INFO |Monitor|SendRegistQueue|0/s|0/s|0|0|0|
09:16:59.347 INFO |Monitor|boss->omc|0/s|0/s|0|0|0|
09:16:59.347 INFO |Monitor|SendQueue|0/s|0/s|0|0|0|
09:16:59.347 INFO |Monitor|boss->pss|0/s|0/s|7037|7037|0|
09:16:59.347 INFO |Monitor|ReceiveAuthQueue|0/s|0/s|0|0|0|
09:16:59.347 INFO |Monitor|ReceiveQueue|0/s|0/s|0|0|0|
09:16:59.348 INFO |Monitor|receiveHandler5|0|SendHandler1|0|receiveAuthMsgHandleThread1|0|
receiveTimerMsgHandler1|0|SendRegHandler|0|SendHandler3|0|SendHandler2|0|receiveHandler4|0|receiveHandler8|0|receiveHandler7|0|receiveHandler2|0|receiveHandler3|0|receiveHandler6|0|receiveHandler1|0|
业务日志:业务日志打印用户请求流程,能够清楚的使用某几个关键字可以提取一个用户的业务流程就可以。业务日志要分详细日志,如上BossAgent打印的日志,非常详细,应该都打印DEBUG级别的日志,而另外就需要打印总结性日志,总结性日志以INFO级别打印,包括|请求开始时间|请求结束时间|请求主体|请求类型|请求结果|请求外部资源返回结果|。其中请求主体可以继续扩展,如BossAgent的请求主体可以扩展为|手机号码|省份编码|MM2消息SEQUENCE|,DSS的请求主体可能属性更多一些,|手机号码|手机密码|手机UA|手机MOD|手机MAN|计费类型|套餐类型|白名单|。
模块性能日志:模块的性能日志应该能够通过该日志清晰的反应该模块目前性能,包括外部请求的压力,内部请求处理速度。
模块外部资源日志:模块的外部资源日志需要详细记录,现今单独的模块很少见了,很多大型复杂的系统往往是由多个模块构成,模块间采用或标准或私有协议进行通信。这种场景下爆发的问题往往比较复杂,并且与多个模块都有关系或是责任。所以在模块级别上将该模块所依赖的外部资源都打印出来非常重要,通过这些日志应该能够完成快速定位问题与哪些模块相关联或是哪些模块需要负根本责任。通常模块的外部资源包括数据库,系统间内部模块、第三方系统。如BossAgent的外部资源包括数据库,系统间内部模块为PSS、第三方系统应该是一级Boss。数据库资源的打印应该包括所有的SQL语句,这个非常重要,无论是问题的定位还是后续的SQL优化,还是数据库架构的调整,都需要这些信息能够快读的整理出该模块所有的SQL语句,提供给专业的DBA进行分析。SQL语句的打印还应该包括参数的打印。
第三方系统的打印主要包括,请求压力的统计、截流告警、请求处理的延迟、以及超时。
1、对异常的打印
异常日志的打印对于问题的分析和定义有极大的帮助,异常日志的打印应该注意以下几点,杂异常分支必须打印日志。如switch case语句块中的default,if else中的 else分支。Try catch语句块中catch分支。对于catch分支的打印,应该尽量使用标准的异常打印,不应该打印的控制台上,对于异常的处理不在本开发指南的讨论范围,所以简单说明。异常应该打印堆栈信息,并且打印日志发生的场景。
2、日志级别
日志级别对于定位问题的重要性,在现网运营的过程中,往往都会打印低级别的日志,一些过于详细得日志记录程DEBUG,而一些总结性的日志记录为INFO级别,对于外部资源日志,如果日志过于庞大,请将日志打印为DEBUG日志,在此基础上在抽取总结性日志,打印为INFO日志。
3、考虑日志对性能的影响
日志的频繁打印会对模块的性能产生极大的影响。如BPP的在每次接受到消息后都会打印消息结构体,将该日志注掉,性能在原有的基础上上升了600条/秒。
4、日志打印内容
4.1 不打印无用的日志
如现网的BossAgent将与PSS之间通信的心跳消息结构体打印出来,该日志不仅打印频繁,而且没有任何意义。
4.1 不打印不完全的日志
不打印不完全的日志,如BossAgent的消息队列积压的告警日志,只打印了消息队列满,但是没有打印是谁满了,也就是缺少主语,对于后续的定位产生了极大的阻碍。
4.3不打印重复的日志
如上BossAgent日志,将MM2消息结构体打印了多次,没有任何意义。
4.4不在循环里打印日志
如果代码的逻辑是一个无限循环或是循环的次数较多,这里的日志不应当打印太过频繁,使用尽量缩减日志量,并且将有用的信息打印出来。在循环打印日志或占用大量CPU时间,这里需要进行特殊的打印。就是采取间隔打印或是定时打印。
5、日志格式
日志格式统一使用主语+谓语+宾语+状语的格式,日志打印应该遵从人类的自然语言,任何没有开发经验或是外行人都能从你的日志中捕获到有用的信息,相信你的日志就打印的很成功了。
加入分隔符,使用分隔符使每个域都能够清晰识别,分隔符可以提高日志可分析性,也可以过滤空格。
如下日志:13722223310 register 200,没有采用域分隔符,这样都手机号码中出现异常数据如13722223310+空格,无法快速定位。加入域分隔符以后13722223310 |register|200|,可以清晰的看清楚手机号码后有多余的空格。
还有更多的有关日志打印的内容参照以下文章。
http://ju.outofmemory.cn/entry/72841
http://blog.csdn.net/mgoann/article/details/5681759
有关日志打印的几点经验相关推荐
- (填坑:SQL打印两次)mybatisplus+p6spy 日志打印
执行 SQL 分析打印 | MyBatis-Plus为简化开发而生https://mp.baomidou.com/guide/p6spy.html使用mybatisplus参考mybatisplus官 ...
- 增加内核的ceph模块的日志打印
本文主要是在梳理cephfs内核方式挂载的内核代码逻辑所做的准备 环境:Centos 7.5 内核源码版本:3.10.0-862.el7.x86_64 打开ceph模块的debug信息 单独编译cep ...
- 为何把日志打印到控制台很慢?
原文 在容器打印日志到控制台阻塞的排障的时候看到一个观点: 把日志打印到控制台要比打印到文件慢,而且是非常慢. log4j2和logback的两个issue官方也提到了这一点(见LOG4J2-2239 ...
- springboot filter and interceptor实战之mdc日志打印
1.1 mdc日志打印全局控制 1.1.1 logback配置 <property name="log.pattern" value="%d{yyyy-MM ...
- aop springboot 传入参数_java相关:springboot配置aop切面日志打印过程解析
java相关:springboot配置aop切面日志打印过程解析 发布于 2020-3-31| 复制链接 摘记: 这篇文章主要介绍了springboot配置aop切面日志打印过程解析,文中通过示例代码 ...
- logback不同业务的日志打印到不同文件
logback不同业务的日志打印到不同文件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/mggwct/article/details/777181 ...
- java占位符打印_java简单日志打印规范小记
个人认为,如果公司一些基础类库不做约束,很可能"埋坑",形成技术债务,最终为此付出代价.本文讲解一个最基本的日志打印规范. 1. 日志打印组件 日志组件有很多,日志门面的选择有:S ...
- python 日志打印
发现python里面扩展了日志打印功能.感觉比java自带的还好,和log4j很类似. 下面总结下其用法.先说一种不用配置文件的: <log.py> 1# -*- coding: gb2 ...
- vue中使用v-on绑定事件中,获取$event.currentTarget,日志打印为null
问题:vue中使用v-on绑定事件中,获取$event.currentTarget,日志打印为null dom结构: <li @click="clickEvent('hello',$e ...
最新文章
- pdb连接数_CDB与PDB的连接-阿里云开发者社区
- 第九章 字符串,字符和字节
- django【orm操作】
- mysql删除原则_MySQL入门-11:数据的增、删、改
- 资源放送丨《大规模 SQL 审核设计与实践》PPT视频
- html中加粗的字体如何改细,css怎么把字体变细?
- 3-3 银行业务队列简单模拟 (25 分)
- 什么是CMMI能力成熟度模型?企业为什么要做?
- linux下添加4g模块驱动程序,【经验】4G模块SLM750在Linux系统下增加USB串口的详细操作指南...
- ZOJ 3551 Bloodsucker(概率dp)
- 晚上兼职送外卖靠谱吗?
- flask爱家租房项目开发(一)
- cmake:pkg_check_modules
- mysql----where 1=1是什么意思
- JSONObject、JSONArray方法使用详解
- 真核生物 18S rRNA
- 李嘉诚,原一平的故事
- android根据url加载图片路径,初学Android——通过URL加载图片
- pdf两个技能,缩略图和更改标题
- 联想-win7系统电脑开机提示Error 1962:No operating解决步骤