日志记录使用 `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)
**滚动日志的目的是防止单个日志文件过大,以至于占满硬盘空间。**
滚动日志的原理是通过设定的规则(最大文件、最多保存多少天),超过设定的值就删除较早的记录。
- 序言
- 基础
- 安装GoHub
- 目录结构
- 开发规范
- 部署项目
- 架构
- 架构总览
- 生命周期
- 配置
- 配置介绍
- 配置目录
- 配置格式
- 配置加载
- 读取配置
- 动态配置
- 环境变量配置
- 路由
- 路由模式
- 路由定义
- 路由参数
- 路由分组
- 路由限流
- 路由拆分
- 控制器
- 控制定义
- 控制器初始化
- 中间件
- Make创建控制器
- 请求
- 请求信息
- 数据库
- 连接数据库
- 基本使用
- Make创建模型
- 日志
- 介绍
- 日志驱动
- 日志写入
- HTTP日志
- 数据库请求日志
- 错误和调试
- Debuger调试器
- 验证
- 验证器
- 验证规则
- Make创建验证器
- 杂项
- 缓存
- 分页
- 验证码
- CURL请求
- 命令行
- 基础知识
- console 包
- Cobra 基础
- 命令行模式
- 附录
- 配置参考
- 第三方依赖库