自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Gorm慢查詢、SQL日志與Go項(xiàng)目日志的整合與串聯(lián)

開發(fā) 項(xiàng)目管理
我們同樣會(huì)為GORM日志注入追蹤ID,把它們歸因到關(guān)聯(lián)的請(qǐng)求上下文中去。這樣一旦發(fā)生數(shù)據(jù)庫相關(guān)的錯(cuò)誤,我們可以通過監(jiān)控主動(dòng)發(fā)現(xiàn)、使用錯(cuò)誤日志中的追蹤ID還能把整個(gè)請(qǐng)求相關(guān)的日志都檢索出來,查問題也會(huì)輕松很多。

如果僅集成到這個(gè)程度,功能開發(fā)完全沒有問題,但如果你還要長(zhǎng)期維護(hù)項(xiàng)目的話,那么問題可大了去了。

原因是,GORM產(chǎn)生的SQL記錄、慢查詢、以及數(shù)據(jù)庫錯(cuò)誤都是通過GORM自身的GormLogger寫到日志的,而且GormLogger默認(rèn)是寫到標(biāo)準(zhǔn)輸出的。。。而不是項(xiàng)目本身的日志文件里,這樣一來如果真的是SQL錯(cuò)誤、慢查詢等導(dǎo)致的Bug,你只能知道發(fā)生Error了,但是在項(xiàng)目日志里卻找不到Error的明細(xì),那你解決BUG就只能靠猜和試?yán)病?/p>

圖片圖片

所以這節(jié)內(nèi)容我們介紹怎么把GORM日志和項(xiàng)目日志整合到一起,讓你擁有下面這樣的SQL詳細(xì)信息

{
    "level": "debug",
    "ts": "2024-10-09T17:09:07.603+0800",
    "msg": "SQL DEBUG",
    "sql": "INSERT INTO `orders` (`user_id`,`bill_money`,`order_no`,`state`,`is_del`,`created_at`,`updated_at`) VALUES (123453453,20,'20240627596615375920904456',1,0,'2024-10-09 17:09:07.586','2024-10-09 17:09:07.586')",
    "rows": 1,
    "dur(ms)": 53,
    "traceid": "19d822280c64c5ed",
    "spanid": "450ccc402492ed45",
    "pspanid": "",
    "file": "gormlog.go",
    "line": 49
}

支持慢查詢、SQL錯(cuò)誤的詳細(xì)記錄,在開發(fā)環(huán)境還會(huì)增加SQL DEBUG輸出把執(zhí)行的SQL語句輸出到日志文件和控制臺(tái),方便在開發(fā)階段進(jìn)行調(diào)試和驗(yàn)證。

我們同樣會(huì)為GORM日志注入追蹤ID,把它們歸因到關(guān)聯(lián)的請(qǐng)求上下文中去。這樣一旦發(fā)生數(shù)據(jù)庫相關(guān)的錯(cuò)誤,我們可以通過監(jiān)控主動(dòng)發(fā)現(xiàn)、使用錯(cuò)誤日志中的追蹤ID還能把整個(gè)請(qǐng)求相關(guān)的日志都檢索出來,查問題也會(huì)輕松很多。

加入項(xiàng)目后訪問https://github.com/go-study-lab/go-mall/compare/c6...c7 能查看我們?cè)陧?xiàng)目中定制化GORM的整個(gè)過程

圖片圖片

Gorm Logger Interface

GORM 允許我們自定義Logger把它執(zhí)行的數(shù)據(jù)庫記錄、產(chǎn)生的錯(cuò)誤等都記錄到項(xiàng)目自身的日志文件中去,

V1版本的GROM的 logger 接口長(zhǎng)這個(gè)樣子,僅僅提供了一個(gè)Print方法,Print方法的參數(shù)都是 create、updates、query 這些方法的回調(diào)中傳遞過去的,我們并沒有辦法傳遞Context。

type logger interface {
 Print(v ...interface{})
}

所以前幾年的項(xiàng)目流行使用GLS -- Goroutine Local Storage,因?yàn)楣俜讲煌扑]也不認(rèn)可GLS這個(gè)概念,GLS的實(shí)現(xiàn)都是第三方庫,前幾年我之前公司項(xiàng)目自己封裝的Logger里就大量使用 jtolio/gls 這個(gè)庫實(shí)現(xiàn)的GLS。

后來做新項(xiàng)目時(shí)我曾經(jīng)還想偷懶直接使用之前公司的Logger,結(jié)果發(fā)現(xiàn)Go 1.19 版本以上 jtolio/gls 這個(gè)庫就不能用了。

jtolio/gls 倉(cāng)庫地址: https://github.com/jtolio/gls

好在GORM在V2 版本的Logger 中增加了Context 回調(diào)的能力,這樣就能把執(zhí)行SQL時(shí)的上下文信息也記錄到日志中來,這點(diǎn)在V1 版本是做不到的。

在GORM V2 中它新增了以下Logger 接口 logger.Interface:

type Interface interface {  
   LogMode(LogLevel) Interface  
   Info(context.Context, string, ...interface{})  
   Warn(context.Context, string, ...interface{})  
   Error(context.Context, string, ...interface{})  
   Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error)  
}

每個(gè)方法都有應(yīng)用的上下文Context參數(shù)傳遞進(jìn)來,還專門提供了Trace方法讓我們實(shí)現(xiàn),供我們實(shí)現(xiàn)查詢的SQL語句和消耗時(shí)間的記錄。

接下來我們開始自定義GORM Logger,其中使用上我們前面已經(jīng)封裝好的項(xiàng)目的日志門面,通過日志門面實(shí)現(xiàn)把GORM日志和項(xiàng)目日志記錄到同一個(gè)地方。

實(shí)現(xiàn)GormLogger 把GORM日志整合到項(xiàng)目日志

現(xiàn)在我們?cè)陧?xiàng)目的 dal/dao 目錄下新建gormlog.go 文件,并添加以下代碼。

type GormLogger struct {
 SlowThreshold time.Duration
}

func NewGormLogger() *GormLogger {
 return &GormLogger{
  SlowThreshold: 500 * time.Millisecond,
}

新建GormLogger類型,在類型中的字段 SlowThreshold 用于設(shè)置慢查詢的門檻,我們?cè)谶@里設(shè)置超過500ms 就是慢查詢,如果需要按環(huán)境定制化, 就把這個(gè)做成配置項(xiàng)放到配置文件中去。

接下來用GormLogger 實(shí)現(xiàn)上面GORM的logger.Interface 中定義的所有方法:

func (l *GormLogger) LogMode(lev gormLogger.LogLevel) gormLogger.Interface {
 return &GormLogger{}
}
func (l *GormLogger) Info(ctx context.Context, msg string, data ...interface{}) {
 logger.New(ctx).Info(msg, "data", data)
}
func (l *GormLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
 logger.New(ctx).Error(msg, "data", data)
}
func (l *GormLogger) Error(ctx context.Context, msg string, data ...interface{}) {
 logger.New(ctx).Error(msg, "data", data)
}
func (l *GormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
 // 獲取運(yùn)行時(shí)間
 duration := time.Since(begin).Milliseconds()
 // 獲取 SQL 語句和返回條數(shù)
 sql, rows := fc()
 // Gorm 錯(cuò)誤時(shí)記錄錯(cuò)誤日志
 if err != nil {
  logger.New(ctx).Error("SQL ERROR", "sql", sql, "rows", rows, "dur(ms)", duration)
 }
 // 慢查詢?nèi)罩? if duration > l.SlowThreshold.Milliseconds() {
  logger.New(ctx).Warn("SQL SLOW", "sql", sql, "rows", rows, "dur(ms)", duration)
 } else {
  logger.New(ctx).Debug("SQL DEBUG", "sql", sql, "rows", rows, "dur(ms)", duration)
 }
}

注意因?yàn)镚ORM的logger包跟我們自己的日志門面 logger 包名稱沖突了,所以在導(dǎo)入包的時(shí)候要給它設(shè)置gormLogger這個(gè)別名。

上面的實(shí)現(xiàn)主要的邏輯是對(duì)Trace方法的重寫,GORM在執(zhí)行SQL回調(diào)Trace方法時(shí),會(huì)把執(zhí)行開始的時(shí)間、執(zhí)行的SQL、返回的函數(shù)以及執(zhí)行中的錯(cuò)誤告訴我們。如果執(zhí)行中發(fā)生錯(cuò)誤就記錄錯(cuò)誤日志,如果消耗時(shí)間超過我們約定的500ms就記一條Warn級(jí)別的日志。

責(zé)任編輯:武曉燕 來源: 網(wǎng)管叨bi叨
相關(guān)推薦

2017-04-01 19:00:25

MySQL慢查詢

2018-10-12 16:45:10

MySQL查詢?nèi)罩?/a>數(shù)據(jù)庫

2023-11-17 12:11:26

GORMGo Web

2010-11-25 16:29:26

MySQL慢日志查詢

2011-06-28 08:32:40

MySQL慢查詢?nèi)罩?/a>

2023-09-01 07:31:24

2024-03-25 07:30:03

MySQL數(shù)據(jù)庫SQL日志

2017-09-18 15:20:02

MySQL慢查詢?nèi)罩?/a>配置

2010-11-26 14:17:11

SQL

2022-05-17 08:24:58

查詢?nèi)罩?/a>MySQL

2017-05-23 16:26:26

MySQL優(yōu)化處理

2022-07-14 14:46:51

數(shù)據(jù)庫SQL系統(tǒng)設(shè)計(jì)

2022-12-26 00:48:38

2010-06-29 09:56:00

SQL Server查

2021-03-25 16:15:24

SQL工具慢查詢

2018-08-02 16:10:50

MySQL數(shù)據(jù)庫清理

2025-01-15 09:21:01

2023-05-26 08:21:59

Lock_TimeMySQL

2023-11-28 08:52:48

Go日志庫

2021-05-14 11:05:38

MySQL慢日志數(shù)據(jù)庫
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)