【JAVA开发规范】日志规范
创始人
2024-03-05 22:22:26
0

1.把日志记录好非常重要

写好代码很重要,日记记录也非常重要。
通过查看日志,能帮我们解决很多问题,以下是我们开发过程中经常会碰到的一些问题:

1.1 代码是否按照预期执行

我们可以通过日志记录代码的执行流程、运行状态、关键指标。

1.2 帮助定位bug

在关键代码处打印日志可以迅速定位问题原因。

1.3 记录用户操作行为

通过对这些日志的分析我们可以得到用户的操作行为数据。

2.记录时机

2.1 程序流程

需要关注程序流传逻辑,在关键代码逻辑的执行前后进行相应的日志输出,有助于代码调试。(但要避免不必要的日志输出,比如一般只在循环体前后记录日志,而不在循环体内重复记录,过多的日志反而会影响阅读。)

2.2 远程调用

虽然远程调用也属于程序流程的一部分,但是应该和一般的程序流程日志区别对待,因为它涉及到和外部系统的交互,在出入口处记录请求入参和响应的信息,很有必要。

2.3 核心业务操作

系统用户进行核心业务操作的行为,也应该进行记录,便于进行操作审计。

2.4 可预期的异常

这类异常应该有效记录起来,通过警告方式反馈给相关人员加以关注,避免频繁发生,最终演化为不可控的问题。

2.5 预期外的错误

这类异常发生时,要有详尽记录,并通知相关人员介入处理,第一时间作出响应,因为这种错误已经影响系统的正常使用。

3.日志要素

3.1日志时间

日志产生的时间一定要有并且应该精确,推荐的格式是:

yyyy-MM-dd HH:mm:ss.SSS

3.2日志级别

应该根据日志的重要性或严重程度划分等级,最常用的日志级别有:
DEBUG:在开发、测试阶段使用,记录调试性质的内容。
INFO:记录系统正常运行期间的关键信息。主要针对程序流转逻辑、核心业务操作。
WARN:记录可预期的异常。比如请求参数不合法。
ERROR:记录预期外的程序异常。比如数据异常、代码逻辑没有按预期执行。

3.3 线程名称

一次同步请求对应一个处理线程,输出线程名称可以区分一次具体的请求上下文。

3.4 业务标识

用来区分日志属于哪块业务,因为日志都是跟业务相关联的,通过该部分内容便于按业务进行日志归类聚合。

3.5 记录器名称

日志的记录器名称一般是声明日志记录器实例的类名,通过记录器名称可以快速定位到日志输出的类是哪个。

3.6 日志内容

根据不同的日志等级,在日志内容上会有不同的侧重点,但在内容输出上,有一些点是需要注意的:

  • 善用占位符特性,一般日志框架都有占位符功能,避免不必要的字符串拼接。
  • 预防日志内容构建过程中的空指针异常、多余的对象序列化、不必要的中间过程执行。
  • 注意敏感内容输出,造成的安全隐患,比如用户密码、账户信息等。
  • 堆栈异常信息有助于程序异常的排查定位,但这部分信息的记录输出,对系统性能有一定的影响,应该酌情考虑,如果记录异常信息足够定位异常的,就不要打印整个堆栈。一般是 ERROR 打印异常堆栈,WARN 不打印。

3.7 日志格式参考

[详细时间] [线程名] [日志级别] [类名] [日志信息]

%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

4.执行规范

4.1 选择恰当的日志级别

常见的日志级别有 4 种,分别是error、warn、info、debug。

  • error:错误日志,指比较严重的错误,对正常业务有影响,需要运维配置监控的;
  • warn:警告日志,一般的错误,对业务影响不大,但是需要 开发关注;
  • info:信息日志,记录排查问题的关键信息,如调用时间、出参入参等等;
  • debug:用于开发DEBUG的,关键逻辑里面的运行时数据;

4.2 日志要打印出方法的入参

我们并不需要打印很多很多日志,只需要打印可以快速定位问题的有效日志。
哪些算得的上有效关键的日志呢?比如说,方法进来的时候,打印入参。再然后呢,在方法返回的时候,就是打印出参(需考虑数据量和必要性,慎重),返回值。正例如下:

public String testLogMethod(Document doc, Mode mode){log.debug(“method enter param:{}”,userId);String id = "9527";log.debug(“method exit param:{}”,id);return id;
}

4.3 遇到if…else…等条件时,每个分支首行都尽量打印日志

当你碰到if…else…或者switch这样的条件时,可以在分支的首行就打印日志,这样排查问题时,就可以通过日志,确定进入了哪个分支,代码逻辑更清晰,也更方便排查问题了。
正例:

if(user.isVip()){log.info("该用户是vip,Id:{},开始处理逻辑",user,getUserId());//会员逻辑
}else{log.info("该用户不是vip,Id:{},开始处理逻辑",user,getUserId())//非会员逻辑
}

4.4 建议使用参数占位{},而不是用+拼接。

反例:

logger.info("Processing trade with id: " + id + " and symbol: " + symbol);

上面的例子中,使用+操作符进行字符串的拼接,有一定的性能损耗。
正例如下:

logger.info("Processing trade with id: {} and symbol : {} ", id, symbol); 

我们使用了大括号{}来作为日志中的占位符,比于使用+操作符,更加优雅简洁。并且,相对于反例,使用占位符仅是替换动作,可以有效提升性能。

4.5 不要使用e.printStackTrace()

反例:

try{// 业务代码处理
}catch(Exception e){e.printStackTrace();
}

正例:

try{// 业务代码处理
}catch(Exception e){log.error("你的程序有异常啦",e);
}

理由:

  • e.printStackTrace()打印出的堆栈日志跟业务代码日志是交错混合在一起的,通常排查异常日志不太方便。
  • e.printStackTrace()语句产生的字符串记录的是堆栈信息,如果信息太长太多,字符串常量池所在的内存块没有空间了,即内存满了,那么,用户的请求就卡住啦~

4.6 异常日志不要只打一半,要输出全部错误信息

反例1:

try {//业务代码处理
} catch (Exception e) {// 错误LOG.error('你的程序有异常啦');
} 
  • 异常e都没有打印出来,所以压根不知道出了什么类型的异常。

反例2:

try {//业务代码处理
} catch (Exception e) {// 错误LOG.error('你的程序有异常啦', e.getMessage());
} 
  • e.getMessage()不会记录详细的堆栈异常信息,只会记录错误基本描述信息,不利于排查问题。

正例:

try {//业务代码处理
} catch (Exception e) {// 错误LOG.error('你的程序有异常啦', e);
} 

4.7 禁止在线上环境开启 debug

禁止在线上环境开启debug,这一点非常重要。
因为一般系统的debug日志会很多,并且各种框架中也大量使用 debug的日志,线上开启debug不久可能会打满磁盘,影响业务系统的正常运行。

4.8 不要记录了异常,又抛出异常

反例如下:

log.error("IO exception", e);
throw new MyException(e);
  • 这样实现的话,通常会把栈信息打印两次。这是因为捕获了MyException异常的地方,还会再打印一次。
  • 这样的日志记录,或者包装后再抛出去,不要同时使用!否则你的日志看起来会让人很迷惑。

4.9 避免重复打印日志

避免重复打印日志,酱紫会浪费磁盘空间。如果你已经有一行日志清楚表达了意思,避免再冗余打印,反例如下:

if(user.isVip()){log.info("该用户是vip,Id:{}",user,getUserId());//冗余,可以跟前面的日志合并一起log.info("开始处理vop逻辑,id:{}",user,getUserId());//vip逻辑
}else{//非vip逻辑
}

相关内容

热门资讯

富士莱一季度营收1.13亿元同... 4月21日,富士莱发布2025年一季报。报告显示,公司一季度营业收入为1.13亿元,同比增长17.4...
中国建筑2024年实现营业收入... 本报讯 (记者向炎涛)日前,中国建筑股份有限公司(以下简称“中国建筑”)发布2024年年度报告。20...
预计俄罗斯央行将维持关键利率在...   路透社周一进行的一项调查显示,参与调查的 25 位分析师均预计,俄罗斯央行在 4 月 25 日的...
“考公上岸秘籍”大公开,手慢无... 转自:法治日报在大众的认知里警犬大多是威风凛凛的德国牧羊犬、拉布拉多犬或是敏捷聪慧的马犬可你能想象平...
一举两得一元一分跑得快微信群哔... 微【mz120590】 【mj120590】【mj191717】等风也等你。喜欢打麻将的兄弟姐妹们、...
《围观》一元一分正规红中麻将微... 认准管理加v:微【mz120590】【mj120590】【mj191717】七年稳定老群!随时拿起手...
【生活常识】正规红中麻将跑的快... 认证群主微信微【mz120590】 【mj120590】【mj191717】(一元俩元红中麻将)(跑...
必看经典15张跑的快群@24小... 1.进群方式-[mz120590]或者《mj120590》【mj191717】--QQ(QQ5672...
全网普及一元一分正规红中麻将微... 认准管理加v:微【mz120590】【mj120590】【mj191717】七年稳定老群!随时拿起手...
《关注麻将》一元一分正规红中麻... 微信一元麻将群群主微【mz120590】 【mj191717】【mj120590】一元一分群内结算,...
百诚医药:已获得1个1类创新药... 每经AI快讯,有投资者在投资者互动平台提问:请问贵公司会搬离杭州吗?为何杭州的创新精神在贵公司一点都...
奥海科技(002993.SZ)... 格隆汇4月21日丨奥海科技(002993.SZ)公布2025年一季度报告,一季度公司实现营业收入14...
狐假虎威谁有广东红中一元一分麻... 一元一分麻将群加群主微【mz120590】【mj191717】 【mj120590】等风也等你。喜欢...
LPR报价连续6个月未变,有何... 每经记者 张寿林    每经编辑 廖丹     中国人民银行授权全国银行间同业拆借...
国盛金控2024年实现净利润1... 上证报中国证券网讯(记者李雨琪)4月21日晚间,国盛金控披露2024年年度报告。报告期内,公司实现营...
天亿马高管平均年薪28.30万... 4月21日,天亿马最新高管薪酬曝光。根据2023年报数据,剔除独立董事、监事会主席、监事后,天亿马共...
全网普及红中麻将跑得快群@20... 微信一元麻将群群主微【mz120590】 【mj191717】【mj120590】一元一分群内结算,...
正式停运!已陪伴昆明人32年,... 4月21日,随着龙门景区周边的围挡立起,运行32年的西山龙门索道正式停运并开始进行原址提升改造。都市...
金丹科技去年归母净利下降56%... 每经记者 王佳飞    每经编辑 文多     2025年4月20日,金丹科技(S...
探寻昌平延寿镇,感受民宿里的慢... 京都母亲河绵延流淌,孕育出昌平延寿镇的灵秀之美。这里不仅有大杨山自然风景区、延寿寺和银山塔林等著名景...