企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
日志记录使用 `Uber` 开源的日志工具([zap](https://github.com/uber-go/zap)) 来作为底层库。 > [logrus](https://github.com/sirupsen/logrus)是另一个知名的日志库,比 `zap` 更容易使用,且具备友好的终端输出,功能更强大。在性能无关的项目中,例如开发一个命令行工具,可以考虑使用 logrus。 [lumberjack](https://github.com/natefinch/lumberjack)是一套滚动日志的实现方案,帮助我们管理日志文件。 ## 什么是日志? 在我们项目中,使用日志来记录整个系统的运行情况。可能但是不限于: - HTTP 请求数据 - 数据库 SQL 请求日志 - Panic/Error 错误日志 - 请求第三方接口日志(发送短信、发送邮件等) ## 日志的目的 方便调试,快速精准地帮我们定位问题。 ## 使用场景 #### 本地开发 本地开发时,虽然我们可以很方便的使用 `Debuger 来调试程序`,但是日志将会是我们最廉价、最便捷的错误定位工具。 #### 线上环境 日志是程序在生产环境下的健康监控。当程序出错时,或者某块业务逻辑出现问题,我们将依赖日志来知道具体哪一行代码出了问题。 ## 日志的等级 我们的日志系统,会划分四个等级: | 日志等级 | 说明 | | --- | --- | | **debug** | 信息量大,一般调试时打开。**系统模块详细运行的日志**,例如 HTTP 请求、数据库请求、发送邮件、发送短信 | | **info** | **业务级别的运行日志**,如用户登录、用户退出、订单撤销。 | | **warn** | **感兴趣、需要引起关注的信息。**例如,调试时候打印调试信息(命令行输出会有高亮)。 | | **error** | **记录错误信息**。Panic 或者 Error。如数据库连接错误、HTTP 端口被占用等。一般生产环境使用的等级。 | **日志等级规则:** * 日志等级在两个地方使用; * 配置信息(config/log.go)中可以配置日志等级; * 代码中调用不同的方法(`Debug()`、`Info()`…)记录不同等级的日志。 * 日志等级具备**过滤信息**的属性; * 配置信息里设置为高等级时,低于这个等级的信息将忽略。如日志等级设为**warn**,只有`Warn()`和`Error()`方法记录的日志会有效,`Debug()`和`Info()`方法记录的日志会被忽略; ## 小心日志过载 记录日志的行为完全掌控在开发者手上。日志等级的错误使用,会导致**日志信息过载**,有违『快速定位问题』的设计初衷。 所以记录日志时,参与项目的开发者之间需要做好约定,或者说**规范**。 * 功能模块的详细运行情况,使用`Debug()`方法,如 HTTP 请求日志、数据库 SQL 日志; * 业务级别的运行日志,使用`Info()`,如果信息量太大,例如说一个请求会记录十几条`Info()`日志,要改用`Debug()`; * 控制好记录日志的量,切勿滥用,滥用会导致日志信息过载; * 开发调试时,使用`Warn()`,调试完成后记得删除调试信息; * 保持 warn 及以上日志级别的干净; * 线上环境开启 error 等级,接到错误反馈时,再开启 debug 进行调试,调试完成后重新设置为 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` 等级的错误日志。 ## 记录日志的方式 从日志的使用场景出发,有两种记录日志的方式: | 使用环境 | 记录的载体 | 说明 | | --- | --- | --- | | 开发环境(local) | 命令行终端 | 高亮、打印调用堆栈 | | 线上环境(production) | 记录到日志文件 | JSON 格式,方便导入专业的日志工具 | ## 日志分割 日志可设置单文件或者按照日期划分日志文件。 单文件: ~~~go storage/logs/log.log ~~~ 日期分隔: ~~~go 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 ~~~ ## 滚动日志(rolling log) **滚动日志的目的是防止单个日志文件过大,以至于占满硬盘空间。** 滚动日志的原理是通过设定的规则(最大文件、最多保存多少天),超过设定的值就删除较早的记录。