业务系统日志记录规范总结

业务系统日志记录规范

注意

  1. 应用中应该充满了日志记录信息,日志甚至比逻辑代码还要多;
  2. 集成 seluth ,开启消息链路;不开启日志上传,不集成 zipkin;
  3. 应该避免日志记录过程中出现异常,比如 log.debug(requst.getid) ,这条日志记录之前一定要判断 request 是否为空;日志记录中使用的信息一定时稳定的,提前准备好的,最好不是专门为此次日志记录专门准备的;
  4. 日志应只记录标识性信息,具体信息从具体存储里取;
  5. 日志应该同时支持人和计算机都可以读;人可读的意思的,要成句子;计算机可读的意思是要有明确的分割符,可以支持正则等工具抽取其中有意义的信息;
  6. service 或 manager 层内有 if…else 或者 switch 这样的分支时,要在分支的首行打印日志,用来确定进入了哪个分支;
  7. 对于 trace / debug / info 级别的日志输出,必须进行日志级别的开关判断。warn 和 error 不用开关判断;

日志级别 trace 和 debug

测试环境要实现的目标是,不需要重新完整的调试程序,可以直接定位到出问题的 service 内的逻辑分支,最多在进行一次小范围的测试;
要实现这个目标,需要记录 service 入参出参,debug级别的日志,只在非生产环境中使用;

日志级别 info

  1. info级别的日志只在 service 层和 manager 层存在,体现业务逻辑运行的路径,工具类等的不要记录;
  2. Service 方法中对于系统/业务状态的变更处记录
  3. 主要逻辑中的分步骤记录

日志级别 warn

  1. 有容错机制的时候出现的错误情况,有异常,但是你有 Plan B;
  2. 业务异常的记录,比如:当接口抛出业务异常时,应该记录此异常;
  3. warn 日志级别来记录用户输入参数错误的情况,避免用户投诉时,可以追溯信息;

日志级别 error

error 级别只记录系统逻辑出错、异常或者重要的错误信息。
异常在程序中,一般会沿着调用链路,层层上抛,直到service层,在最终处理异常的地方记录log.error(e);log.error和往外抛异常,不应该同时出现;

错误异常

错误异常分为程序异常(系统异常)和业务异常;

程序异常会导致程序不能正常执行;业务异常不会,业务异常的处理属于业务逻辑的一部分;
ERROR 级别的日志,一出,意味着开发运维人员要介入了,要操作确认一下东西,要维修一些东西了;

业务系统开发过程中,不需要 log.error 记录异常,让框架和容器(Tomcat等)来做;
业务异常的需要开发者开发对应的异常处理逻辑,业务异常不是程序异常;比如用户登陆失败;
业务异常的处理属于正常的业务逻辑,不应该log.error,不重要的可以不log,重要的可以使用log.warn记录,避免用户投诉时,可以追溯信息;

数据库或者kafka在应用启动时连不上是如何处理的,在应用运行过程中是如何处理的?启动时,依赖的插件有问题,应用直接启动不起来;如果应用已经启动起来了,触发到跟其交互时,抛出异常,程序还是正常执行;

ExceptionHandler的默认的处理逻辑

ExceptionHandler的默认的处理逻辑不要吃掉所有的异常,log.error打印出来,这个逻辑主要用来处理程序异常,业务异常都应有对应的处理逻辑;

@ExceptionHandler(Throwable.class)
@ResponseBody
public String handle(Throwable e) {
	log.error(e.getMessage(),e);
	//构造返回信息
	return e.getMessage();
}

程序异常

各个组件的异常信息可以各自处理;比如SQLExcption,需要如果SQL 出异常,异常的信息中会有SQL相关的信息,如果直接返回给前端,会造成安全问题,前端对此异常也不关心,而后端开发者关心的信息应该都记录在日志中,以方便分析问题;

@ExceptionHandler(SQLException.class)
@ResponseBody
public String handle(SQLException e) {
	log.error(e.getMessage(),e);
	//构造返回信息,记得脱敏
	return e.getMessage();
}

各个组件的SDK一般都会有自己的异常体系;可以根据情况直接对顶级异常类,或者典型的异常子类进行处理;
接入外部组件时,首先分析其SDK的异常体系,编写对应的ExceptionHandler

org.apache.kafka.common.KafkaException
org.springframework.kafka.KafkaException
java.sql.SQLException

链路追踪

多个进程间的日志联动
集中式日志存储系统的存在,让在一个入口处理业务系统的日志成为了可能,产生了高级的用法,链路追踪;
用户的一个动作触发的在各个系统的所有的执行逻辑,使用一个标识将其联系起来,开发人员分析的时候,可以根据此标识查询所有相关的日志,哪里出问题,一目了然;

远程调用

远程调用的plan b,就是熔断降级里面的Plan B;
外部接口部分,客户端请求参数(REST/WS),调用第三方时的调用参数和调用结果使用info

如果出异常,调用过程异常或者返回错误码,根据情况选择抛出异常或者启用Plan B;
抛出异常意味着程序正常流程执行结束,需要处理这个异常,warn记录此异常,然后返回用户结果;
Plan B意味着程序还可以正常执行下去,warn记录发生了此事件,出现异常转入Plan B;

远程调用过程中出异常,意味着需要开发人员介入,应该记录 error 级别的异常;
如果是返回的错误码是非成功执行的错误码,这时候应该根据错误码的级别抛出不同的异常,处理异常的地方根据远程调用的接口的重要程度评估使用不同的日志级别。

验证日志

提交代码前,确定通过日志可以看到一个功能的整个执行流程,可以通过日志进行问题定位程序执行的路径;

参考

用JAVA日志来写诗
JAVA - 优雅的记录日志(log4j实战篇)
Alibaba Java Coding Guidelines
小白学习如何打日志
正确的打日志姿势
Java常用日志框架介绍

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章