1. 什么是日志?
在我们项目中,使用日志来记录整个系统的运行情况。可能但是不限于:
HTTP 请求数据
数据库 SQL 请求日志
Panic/Error 错误日志
请求第三方接口日志(发送短信、发送邮件等)
2. 日志的目的
记录日志的目的是什么?
方便调试,快速精准地帮我们定位问题。
3. 使用场景
本地开发: 本地开发时,虽然我们可以很方便的使用 Debuger 来调试程序,但是日志将会是我们最廉价、最便捷的错误定位工具。
线上环境: 日志是程序在生产环境下的健康监控。当程序出错时,或者某块业务逻辑出现问题,我们将依赖日志来知道具体哪一行代码出了问题。
4. 日志的等级
我们的日志系统,会划分四个等级:
日志等级 | 说明 |
---|---|
debug | 信息量大,一般调试时打开。系统模块详细运行的日志,例如 HTTP 请求、数据库请求、发送邮件、发送短信 |
info | 业务级别的运行日志,如用户登录、用户退出、订单撤销。 |
warn | 感兴趣、需要引起关注的信息。 例如,调试时候打印调试信息(命令行输出会有高亮)。 |
error | 记录错误信息。Panic 或者 Error。如数据库连接错误、HTTP 端口被占用等。一般生产环境使用的等级。 |
日志等级规则:
- 日志等级在两个地方使用;
- 配置信息(config/log.go)中可以配置日志等级;
- 代码中调用不同的方法(Debug()、Info()…)记录不同等级的日志。
- 日志等级具备过滤信息的属性;
- 配置信息里设置为高等级时,低于这个等级的信息将忽略。如日志等级设为 warn ,只有 Warn() 和 Error() 方法记录的日志会有效,Debug() 和 Info() 方法记录的日志会被忽略;
5. 小心日志过载
记录日志的行为完全掌控在开发者手上。日志等级的错误使用,会导致日志信息过载,有违『快速定位问题』的设计初衷。
所以记录日志时,参与项目的开发者之间需要做好约定,或者说规范。
功能模块的详细运行情况,使用 Debug() 方法,如 HTTP 请求日志、数据库 SQL 日志;
业务级别的运行日志,使用 Info(),如果信息量太大,例如说一个请求会记录十几条 Info() 日志,要改用 Debug();
控制好记录日志的量,切勿滥用,滥用会导致日志信息过载;
开发调试时,使用 Warn() ,调试完成后记得删除调试信息;
保持 warn 及以上日志级别的干净;
线上环境开启 error 等级,接到错误反馈时,再开启 debug 进行调试,调试完成后重新设置为 error 等级,保持线上日志的干净;
ERROR等级说明
系统运行出错,才能使用 Error() 记录,如数据库连接出错,或出现 500 错误。
切勿将 error 级别与 Go 语言的 error 类型画上等号
例如解析用户请求的 JSON 数据出错时,会返回 Go 的 error 类型:
func (c *Context) ShouldBind(obj interface{}) error
应当回馈给 API 422 状态码(无法处理请求),记录一条 warn 的日志,而不是 error 等级的错误日志。
另一个例子是 Gorm 查询数据库,未找到数据时会返回自定义的 Error ,此时应该记录为 warn 或者 info ,而不应该记录为 error 等级的错误日志。
6. 记录日志的方式
从日志的使用场景出发,有两种记录日志的方式:
使用环境 | 记录的载体 | 说明 |
---|---|---|
开发环境(local) | 命令行终端 | 高亮、打印调用堆栈 |
线上环境(production) | 记录到日志文件 | JSON 格式,方便导入专业的日志工具 |
7. 日志分割
日志可设置单文件或者按照日期划分日志文件。
单文件:
storage/logs/log.log
日期分隔:
storage/logs/2021-12-30.log
storage/logs/2021-12-31.log
storage/logs/2022-01-01.log
storage/logs/2022-01-02.log
storage/logs/2022-01-03.log
8. 滚动日志(rolling log)
滚动日志的目的是防止单个日志文件过大,以至于占满硬盘空间。
滚动日志的原理是通过设定的规则(最大文件、最多保存多少天),超过设定的值就删除较早的记录。
网友评论