日志规范
1. 日志分类
日志:用来准确、恰当、适量地记录用户操作、系统运行状态等,是一个系统的重要组成部分
日志从功能划分,可分为诊断日志、统计日志、审计日志:
- 诊断日志
- 请求的入口和出口
- 外部服务调用及返回
- 资源消耗操作: 打开文件等
- 容错行为,譬如云硬盘的副本修复操作
- 程序异常,譬如数据库无法连接
- 后台操作,清理程序
- 启动、关闭、配置加载
- 抛出异常时,不记录日志
- 统计日志
- 用户访问统计
- 计费日志(如记录用户使用的网络资源或磁盘占用,格式较为严格,便于统计)
- 审计日志
- 管理操作
2. 日志规范重要性
只有在程序出问题以后才会知道打一个好的日志有多么重要
低效日志将导致开发/测试/运维人员:
- 对系统的运行状态一知半解,甚至一无所知
- 系统出现问题无法定位,或需耗费大量时间和精力
- 无法发现系统瓶颈,不知优化从何做起
- 无法基于日志对系统运行过程中的错误和潜在风险进行监控和报警
- 对挖掘用户行为和提升产品价值毫无帮助
优质日志将帮助开发/测试/运维人员:
- 准确知晓线上系统的运行状态
- 快速定位线上问题,高效排障
- 发现系统瓶颈
- 预警系统潜在风险
- 挖掘产品最大价值
3. 日志规范总则
减少日志中无用信息,防止淹没重要信息
要尽可能使日志信息准确全面,以便快速精确定位问题
要统一日志格式规范,以方便后续排障和分析
要不断优化完善日志,以提升问题定位效率
要明确不同功能日志的用途,使日志内容符合对应功能日志的要求
开发过程中记录日志应思考:
- 该行日志真的有人看么?
- 该条日志能够传递什么信息?
- 这条日志能对排障带来什么帮助?
4. 日志规范
4.1. 日志级别的选择规约
如何针对不同场景,选择恰当的日志级别?
- Emergency:
- 发生导致系统不可用的事故时
- 一个进程的生命周期里最多记录一次 Emergency 级别日志(慎用)
- Alert:
- 发生核心功能不可用的紧急事件时
- 紧急程度仅次于 Emergency,此时系统虽仍可用,但已严重影响了功能的完整性与可用性
- 必须马上处理
- Critical:
- 发生程序组件不可用的危急事件时
- 需要马上处理
- Error:
- 程序运行中出现错误,但不影响整个系统的逻辑运行时
- 一般不需要立即修复,但必须及时记录并做检测
- Warning:
- 发生若不及时处理可能引发/导致程序出错的征兆事件时
- 虽暂时未发生程序错误,但也需要提醒并及时查看和处理
- Notice:
- 发生不影响程序功能,但需要引起注意的事件时
- Informational:
- 记录系统正常运行的一般信息,侧重对正常运行的主要流程的记录
- 辅助更高级别错误日志的定位分析,譬如排除掉Error错误前已打Info日志的正常流程,缩小排障范围
- Debug:
- 帮助开发/测试/运维人员,对系统进行诊断的更丰富和细致的信息
日志级别选择流程:
4.2. 日志格式规约
如何利用正确的日志格式规范所输出的日志内容?
4.2.1. 日志格式总体要求
- 统一字段命名:对于不同请求中的同一含义的字段,只能有一个名字
- 统一字段风格:譬如字段一律使用 xxx_yyy 的下划线命名风格
- 统一字段顺序:譬如统一使用 请求ID/服务名/请求参数/响应数据/响应时间 作为日志字段顺序
4.2.2. 格式规则
- 避免字符串拼接,使用‘{‘和’}’作为消息正文中参数的占位符
- 避免重复记录,同样的日志内容理论上只需要记录一次,否则会造成磁盘空间浪费,过多冗余日志也会对查找问题产生干扰
- 日志一定要有显示Level呈现,一眼就知道日志属性
- 重要日志信息脱敏,如用’*’号代替
4.2.3. 日志格式
即日志的字段结构,包含哪些字段,字段顺序等
示例日志格式
1 | 2021-08-31 20:35:01.713966 host <local2.notice> NOTICE client[38] zread_hello(): client 29 says hello and bids fair. |
日志结构中各字段 | 对应日志内容 |
---|---|
日志时间 | 2021-08-31 20:35:01.713966 |
主机名 | host |
日志属性<模块类别.日志级别> | <local2.notice> |
日志级别 | NOTICE |
所属进程/线程 | client[38] |
类名/方法名 | zread_hello(): |
日志正文 | client 29 says hello and bids fair. |
4.3. 日志内容规约
什么场景下打日志,日志输出什么内容?
4.3.1. 推荐记录的日志内容
1. 系统启动或初始化时,重要的系统初始化参数、配置加载【Info】
2. 系统运行过程中的重要信息
- 所有错误信息:
- 程序崩溃事故【Emergency】
- 核心功能不可用紧急事件【Alert】
- 程序组件不可用危急事件【Critical】
- 程序运行错误【Error】
- 所有警告信息【Warning】:
- 暂未但不及时处理可能将会导致错误的事件
- 流程中正常的请求出错
- 关键流程信息【Info】:
- 主要模块间的请求与响应
- 重要事件的发生与结束
- 重要状态变化
- 持久化数据时修改前后的记录变化
- 长期执行任务的执行进度
- 后台定期执行任务【Info】:
- 定期缓存更新任务的启停时间
- 异常处理逻辑【Notice】:
- 请求资源首次未成功后,后续尝试再次请求的行为记录
3. 有助于排障运维的信息【Debug】
- 重要事件函数的启停,返回值信息等
- 核心变量的变化
- 内存数据结构的状态
4.3.2. 避免记录的日志内容
- 文件内容或者一大段消息的内容
- 良性“错误”,有时候尽管出现了错误,然而错误处理的流程可以正确解决这种情况
- 预期会发生且能够被正常处理的异常,否则将打印出一堆无用的堆栈信息
- 开发者为方便调试临时加入的非必要状态信息
- 输出机密信息
参考文档
相关文章