欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go基于GORM 獲取當(dāng)前請求所執(zhí)行的 SQL 信息(思路詳解)

 更新時(shí)間:2021年01月18日 17:10:47   投稿:mrr  
這篇文章主要介紹了Go基于GORM 獲取當(dāng)前請求所執(zhí)行的 SQL 信息(思路詳解),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

前言

為了便于精準(zhǔn)排查問題,需要將當(dāng)前的請求信息與當(dāng)前執(zhí)行的 SQL 信息設(shè)置對應(yīng)關(guān)系記錄下來,記錄的 SQL 信息包括:

  • 執(zhí)行 SQL 的當(dāng)前時(shí)間;
  • 執(zhí)行 SQL 的文件地址和行號;
  • 執(zhí)行 SQL 的花費(fèi)時(shí)長;
  • 執(zhí)行 SQL 的影響行數(shù);
  • 執(zhí)行的 SQL 語句;

數(shù)據(jù)庫組件使用的是GORM。

思路

1、在執(zhí)行 SQL 前,設(shè)置開始執(zhí)行時(shí)間(計(jì)算執(zhí)行時(shí)長會用到);

2、在執(zhí)行 SQL 后,第一,獲取當(dāng)前請求的上下文,為什么獲取上下文,因?yàn)樾枰獜纳舷挛闹蝎@取本次請求信息,第二,獲取 SQL 執(zhí)行前的時(shí)間,用來計(jì)算執(zhí)行時(shí)長,第三,獲取執(zhí)行的 SQL 信息,然后將數(shù)據(jù)設(shè)置到Trace中,Trace是項(xiàng)目中鏈路包,后面文章會對其介紹;

上面需要用到GORM兩個 知識點(diǎn) CallbacksContext,這兩個是在GORM V2才有的,需要 import 的包為gorm.io/gorm。

演示代碼

Context的傳遞需要使用GORM V2提供的WithContext()方法。

func (u *userRepo) getUserByID(ctx core.Context, id uint) (*user_model.UserDemo, error) {
 data := new(user_model.UserDemo)
 err := u.db.GetDbR().WithContext(ctx).First(data, id).Error
 if err != nil {
 return nil, errors.Wrap(err, "[user_demo] get user data err")
 }
 return data, nil
}

編寫CallBacks插件代碼,GORM 的 Plugin 接口的編寫非常簡單,只需要實(shí)現(xiàn)兩個方法即可。

// Plugin GORM plugin interface
type Plugin interface {
 Name() string
 Initialize(*DB) error
}

下面是我寫的插件代碼:

type TracePlugin struct{}

func (op *TracePlugin) Name() string {
 return "tracePlugin"
}

func (op *TracePlugin) Initialize(db *gorm.DB) (err error) {
 // 開始前
 _ = db.Callback().Create().Before("gorm:before_create").Register(callBackBeforeName, before)
 _ = db.Callback().Query().Before("gorm:query").Register(callBackBeforeName, before)
 _ = db.Callback().Delete().Before("gorm:before_delete").Register(callBackBeforeName, before)
 _ = db.Callback().Update().Before("gorm:setup_reflect_value").Register(callBackBeforeName, before)
 _ = db.Callback().Row().Before("gorm:row").Register(callBackBeforeName, before)
 _ = db.Callback().Raw().Before("gorm:raw").Register(callBackBeforeName, before)

 // 結(jié)束后
 _ = db.Callback().Create().After("gorm:after_create").Register(callBackAfterName, after)
 _ = db.Callback().Query().After("gorm:after_query").Register(callBackAfterName, after)
 _ = db.Callback().Delete().After("gorm:after_delete").Register(callBackAfterName, after)
 _ = db.Callback().Update().After("gorm:after_update").Register(callBackAfterName, after)
 _ = db.Callback().Row().After("gorm:row").Register(callBackAfterName, after)
 _ = db.Callback().Raw().After("gorm:raw").Register(callBackAfterName, after)
 return
}

var _ gorm.Plugin = &TracePlugin{}

func before(db *gorm.DB) {
 db.InstanceSet(startTime, time.Now())
 return
}

func after(db *gorm.DB) {
 _ctx := db.Statement.Context
 ctx, ok := _ctx.(core.Context)
 if !ok {
 return
 }

 _ts, isExist := db.InstanceGet(startTime)
 if !isExist {
 return
 }

 ts, ok := _ts.(time.Time)
 if !ok {
 return
 }

 sql := db.Dialector.Explain(db.Statement.SQL.String(), db.Statement.Vars...)

 sqlInfo := new(trace.SQL)
 sqlInfo.Timestamp = time_parse.CSTLayoutString()
 sqlInfo.SQL = sql
 sqlInfo.Stack = utils.FileWithLineNum()
 sqlInfo.Rows = db.Statement.RowsAffected
 sqlInfo.CostSeconds = time.Since(ts).Seconds()
 ctx.Trace().AppendSQL(sqlInfo)

 return
}

最后,在 db 連接的時(shí)候使用這個插件:

// 使用插件
db.Use(&TracePlugin{})

效果

小結(jié)

這是編寫的trace包的一部分,這個包可以記錄這些信息(JSON 格式):

  • 支持設(shè)置 trace_id
  • 支持設(shè)置 request 信息
  • 支持設(shè)置 response 信息
  • 支持設(shè)置 third_party_requests 三方請求信息
  • 支持設(shè)置 debugs 打印調(diào)試信息
  • 支持設(shè)置 sqls 執(zhí)行 SQL 信息
  • 可記錄 cost_seconds 執(zhí)行時(shí)長

以上代碼在 go-gin-api 項(xiàng)目中,地址:

github.com/xinliangnote/go-gin-api

到此這篇關(guān)于Go基于GORM 獲取當(dāng)前請求所執(zhí)行的 SQL 信息的文章就介紹到這了,更多相關(guān)Go 獲取當(dāng)前請求所執(zhí)行的 SQL 信息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go channel如何批量讀取數(shù)據(jù)

    Go channel如何批量讀取數(shù)據(jù)

    本文將展示一個從 Go channel 中批量讀取數(shù)據(jù),并批量發(fā)送到 Kafka 和批量寫入網(wǎng)絡(luò)數(shù)據(jù)的示例,文中的示例代碼講解詳細(xì),有需要的可以參考下
    2024-10-10
  • Go+Redis實(shí)現(xiàn)延遲隊(duì)列實(shí)操

    Go+Redis實(shí)現(xiàn)延遲隊(duì)列實(shí)操

    這篇文章主要介紹了Go+Redis實(shí)現(xiàn)延遲隊(duì)列實(shí)操,延遲隊(duì)列是一種非常使用的數(shù)據(jù)結(jié)構(gòu),我們經(jīng)常有需要延遲推送處理消息的場景,比如延遲60秒發(fā)送短信,延遲30分鐘關(guān)閉訂單,消息消費(fèi)失敗延遲重試等
    2022-09-09
  • Go函數(shù)全景從基礎(chǔ)到高階深度剖析

    Go函數(shù)全景從基礎(chǔ)到高階深度剖析

    本文深入探索Go語言中的函數(shù)特性,從基礎(chǔ)函數(shù)定義到特殊函數(shù)類型,再到高階函數(shù)的使用和函數(shù)調(diào)用優(yōu)化,通過詳細(xì)的代碼示例和專業(yè)解析,讀者不僅可以掌握函數(shù)的核心概念,還能了解如何在實(shí)踐中有效利用這些特性來提高代碼質(zhì)量和性能
    2023-10-10
  • Go?gRPC進(jìn)階教程gRPC轉(zhuǎn)換HTTP

    Go?gRPC進(jìn)階教程gRPC轉(zhuǎn)換HTTP

    這篇文章主要為大家介紹了Go?gRPC進(jìn)階教程gRPC轉(zhuǎn)換HTTP教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Mac GoLand打不開(閃退)也不報(bào)錯的解決方案

    Mac GoLand打不開(閃退)也不報(bào)錯的解決方案

    這篇文章主要介紹了Mac GoLand打不開(閃退)也不報(bào)錯的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • go語言map字典刪除操作的方法

    go語言map字典刪除操作的方法

    這篇文章主要介紹了go語言map字典刪除操作的方法,實(shí)例分析了map字典操作的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Golang?pprof監(jiān)控之cpu占用率統(tǒng)計(jì)原理詳解

    Golang?pprof監(jiān)控之cpu占用率統(tǒng)計(jì)原理詳解

    經(jīng)過前面的幾節(jié)對pprof的介紹,對pprof統(tǒng)計(jì)的原理算是掌握了七八十了,但唯獨(dú)還沒有分析pprof?工具是如何統(tǒng)計(jì)cpu使用情況的,今天我們來分析下這部分
    2023-04-04
  • GO語言實(shí)現(xiàn)批量壓縮圖片和水印

    GO語言實(shí)現(xiàn)批量壓縮圖片和水印

    這篇文章主要介紹了GO語言實(shí)現(xiàn)批量壓縮圖片和水印,主要用到了github.com/nfnt/resize這個第三方庫,僅僅支持JPG圖片格式,有相同需求的小伙伴參考下吧。
    2015-03-03
  • 解決golang post文件時(shí)Content-Type出現(xiàn)的問題

    解決golang post文件時(shí)Content-Type出現(xiàn)的問題

    這篇文章主要介紹了解決golang post文件時(shí)Content-Type出現(xiàn)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Go并發(fā)控制Channel使用場景分析

    Go并發(fā)控制Channel使用場景分析

    使用channel來控制子協(xié)程的優(yōu)點(diǎn)是實(shí)現(xiàn)簡單,缺點(diǎn)是當(dāng)需要大量創(chuàng)建協(xié)程時(shí)就需要有相同數(shù)量的channel,而且對于子協(xié)程繼續(xù)派生出來的協(xié)程不方便控制
    2021-07-07

最新評論