日志规范.md 5.5 KB

日志规范

前言概述

编写稳定优雅的代码固然重要,而写好日志亦非常重要,无论是何种编程语言,日志信息输出几乎无处不在, 日志是属于系统一个重要的组件模块,正确的日志输出,可以帮助我们开发时的调试 与 减轻程序后期的维护压力。

在实际开发中,很多开发者输出日志都是因为程序调试而输出,并没有一个程序全局日志规范输出的习惯,也就是说程序还有很多代码片段需要输出日志的。程序在开发联调的时候,假设程序运行出现异常或者报错,我们第一件事就是查看当时的日志输出,因为日志涵盖了程序运行时的情况信息,可以快速定位到问题的根本原因,生产环境亦是一样。作为开发人员,我们应该重视日志,认识到日志在系统中的地位,更要养成良好日志输出的习惯。

功能完成开发后,在review 自己的代码的时候、务必合理地安排时间将日志填充

日志输出原则

  • 不能影响程序的正常运行

  • 不允许输出涉及安全 与 隐私的数据

  • 输出有意义的日志信息,同时确保日志的可读性

  • 避免日志泛滥

日志的重要性

  • 记载用户行为的审计日志

  • 可快速定位问题的根源,日志是排查问题的重要手段之一

  • 方便开发调试

  • 监控报警

  • 查询历史 与 统计分析

认识日志级别

日志级别通常有如下几种:

  • verbose

此级别输出任意级别的日志,不推荐使用

  • debug

此级别一般用于项目开发调试或测试使用,生产环境不允许出现 debug 级别

  • info

此级别用于记录一般行为数据,比如用户行为、SQL语句、参数等

  • notice

此级别记录程序重要的参数

  • warning

此级别记录非错误性的异常 或 非期望的结果

  • error

此级别用于记录程序运行时的错误信息,比如程序异常捕获信息

  • critical

此级别用于记录程序组件不可用的异常,属于紧急级别,比如某一个微服务通讯失败

  • alert

此级别记录程序依赖组建或服务异常,比如redisMySQL通讯异常

  • emergency

当系统不可用,那就使用此日志级别记录

实际开发中,常用的是 debug, info, warningerror 这几种,必须要掌握它们使用的原则

优雅日志示范

2022-03-12 23:36:37.310839 INFO: push cash {"user_id":9510,"cash":"52.00"}

2022-03-12 23:36:37.311712 DEBUG: source data come from cache

2022-03-12 23:36:37.311935 WARNING: logout failed {"user_id":8888}

2022-03-15 13:38:22.175 [grpc-default-executor-2985] ERROR com.ywt.rpc.impl.UserServiceImpl - getUserInfoByOpenId(21, oXqGisxBk08MtJBVFDSZc2UpTbQk): UNAVAILABLE: all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial tcp ***.**.**.***:****: getsockopt: connection refused"
io.grpc.StatusRuntimeException: UNAVAILABLE: all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial tcp ***.**.**.***:****: getsockopt: connection refused"
        at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:210)
        at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:191)
        at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:124)

日志输出规范要求

日志结构体

日志输出的信息结构体必须涵盖日期时间日志级别代码位置日志内容等信息。

日志内容

日志内容输出规范相当重要,因为日志是给人阅读的,日志内容词语必须是业务相关的专业术语,可以顾名思义,即可以让人一看就清楚知道什么业务的日志,执行到了哪一步,执行的结果是什么,最禁忌的是使用意义不明的自费作为日志信息,如:==========—————111111111111111

禁止输出敏感信息,比如账号密码等。

日志时效性

顾名思义就是日志文件时间的有效性,中小型的项目保留时间一般设定为7~30天。有时候出现了问题 或 异常,我们并不能及时发现,这时我们就需要追溯到之前的历史日志,因而需要将日志保存一定的时长以便于日志追溯。

日志聚合

目前我们的架构使用 ELK 技术栈,Elasticsearch + FileBeat + Kibana 三大组件,提供分布式搜索引擎、数据收集处理引擎以及数据缓冲队列,实现全文搜索和分析引擎、提供搜集、分析和存储数据三大功能。

日志性能

首先明确一点,无论是将日志写于文件还是记录于数据库,都是需要消耗 IO 资源,IO 操作必然会带来 CPU 的抢占与消耗,因而打印日志并不是越多越好,适当合理才是最好的,也就是需要合理地输出日志才有利于提高程序的性能。

注意事项:

  • 尽量避免在循环体做日志输出,大量日志输出会降低系统性能

  • 禁止输出日志内容体日志,比如 base64 的图片、Excel 表格内容数据等

  • 生产上不允许执行调试级别的日志

  • 禁止输出没有意义性的日志

  • 开发调试过程中的 debug 日志,如无必要,提交代码前请注释掉

对日志的思考

正确看待日志的重要性,养成合理打印日志信息习惯,请务必对自己的编码 review检查日志是否满足规范