学习日志的编写规范并且粗略总结一下,以便之后讨论使用
日志目的
- 打印调试:即可以用日志来记录变量或者某一段逻辑。记录程序运行的流程,即程序运行了哪些代码,方便排查逻辑问题。
- 问题定位:程序出异常或者出故障时快速的定位问题,方便后期解决问题。因为线上生产环境无法 debug,在测试环境去模拟一套生产环境,费时费力。所以依靠日志记录的信息定位问题,这点非常重要。
用户行为记录:记录用户的操作行为,用于大数据分析,比如监控、风控、推荐等等(当前项目中暂时不用)。
记录日志时机
-
启动和结束时:核心模块或者组件初始化过程中往往依赖一些关键配置,根据参数不同会提供不一样的服务。务必在这里记录 INFO 日志,打印出参数以及启动完成态服务表述。
-
发生异常时:捕获的异常是需要重点关注的报错,应当适当记录日志,根据实际结合业务的情况使用 WARN 或者 ERROR 级别。
-
系统核心动作:系统中核心业务逻辑,建议记录 INFO 级别日志,比如核心逻辑流程;微服务各服务节点交互;核心数据表增删改等,如果日志频度高或者打印量特别大,可以提炼关键点 INFO 记录,其余酌情考虑 DEBUG 。
-
第三方服务调用时:由于客户端系统中使用了微服务架构体系,因此建议在调用第三方微服务时打印请求与响应参数,以免发生问题后无法快速定位由于其他团队导致的问题。
-
修改(包括新增)操作必须打印日志 大部分问题都是修改导致的。数据修改必须有据可查。
-
条件分支必须打印条件值,重要参数必须打印 尤其是分支条件的参数,打印后就不用分析和猜测走那个分支了,很重要!如下面代码里面的userType,一定要打印值,因为他决定了代码走那个分支。
日志基本规范
日志时间
由于可能的调试需要,日志时间一般需要精确到毫秒
yyyy-MM-dd HH:mm:ss.SSS
日志级别
- DEBUG:主要用于调试阶段输出,此日志应尽可能详尽。DEBUG日志应该以调试人员满足调试需求为主,生产环境不应输出debug级别日志。
- INFO:主要用来反馈系统当前状态的输出,应视为系统产品最终呈现给用户的一部分,因此不可滥用。INFO级别通常用来进行日常运维以及错误回溯时查看上下文场景。通过INFO日志可以了解系统的运行情况,对系统进行监控。
- WARN:主要针对可预知,有解决预案的错误,如下单数量超过该用户所持总量的情况。WARN级别打印关键信息即可,事后用于分析错误原因。
- ERROR:主要针对不可预知的信息,比如异常和错误。ERROR级别通常指一些较为严重的异常发生,所以需要尽可能多的打印出详细信息,如方法的入参,执行过程产生数据等。
注意
ERROR日志意味着系统发生严重问题,如关键流程无法走通,逻辑出错等。因此ERROR级别日志应在系统内尽量少的出现,一旦出现需要立即人工干预解决。而非关键部分出现的错误应尽量使用WARN级别日志来输出,尤其是用户自身问题可能导致的错误,应用WARN日志记录,同时可以记下用户入参,避免出现问题时背锅。
日志内容
日志记录内容不应过多:
-
尽量减少异常数量,能够在一条日志中的信息不要放到多条日志中;
-
预期的到且能够进行处理,无需打印出无用的堆栈(一般通过WARN日志输出);
同时日志需要拥有足够需要信息:
- 通过日志能够确定后台任务是否按照希望的流程执行;
- 通过日志能够定位发生问题的位置,无需临时增加日志并重发请求来定位;
- 通过日志能够确定相关数据的内容;(给log带来上下文)
- 通过日志能够确定系统启动时配置是否正确加载;
日志需要记录时间信息。
日志的内容应尽量记录关键参数和报错原因。如:
[INFO] RequestID:b1946ac92492d2347c6235b4d2611184, ErrorCode:1426, Message: callback request (to http://example.com/callback) failed due to socket timeout
其他日志注意事项
- 输出Exceptions的全部Throwable信息
logger.error(Obj.toString + "Error happened" + "_" + e.getMessage(), e);
- 出于日志文件储存和性能的考虑,建议为可能会大量出现的低级别日志添加判断
if (logger.isDebugEnabled()) {
logger.debug("returning content: "+ content);
}
- 尽量使用占位符而不是拼接来打印日志,这样的可读性更高,而且只有打印时才会处理函数,提升效率
log.debug("order is paying with userId:[{}] and orderId : [{}]",userId, orderId);
-
尽量不要在日志中调用方法获取值,否则会因为日志而报出空指针异常。(日志不能打断业务逻辑)
-
上线后除了进行常规的测试外,应可以通过对日志进行观察来判断新功能是否工作正常。
-
对不同类型的日志进行分类输出,比如ERROR日志单独输出,防止日志数量过大时不利于分析错误信息。
-
日志文件一般保留周期为15天,防止以周为单位的错误出现,应设置定时任务删除过期日志(如15天前)。
参考资料
阿里巴巴Java开发手册1.4.0