日志記錄使用 `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 基礎
- 命令行模式
- 附錄
- 配置參考
- 第三方依賴庫