当前位置:网站首页>Go - get the SQL information of the current request based on Gorm

Go - get the SQL information of the current request based on Gorm

2021-01-23 16:58:29 Xinliang

Preface

In order to facilitate accurate troubleshooting , You need to compare the current request information with the currently executed SQL Record the correspondence of information settings , Records of the SQL The information includes :

  • perform SQL The current time of ;
  • perform SQL File address and line number of ;
  • perform SQL How long does it take ;
  • perform SQL The number of rows affected by ;
  • Executive SQL sentence ;

The database component uses GORM.

Ideas

  • 1、 In execution SQL front , Set the start execution time ( Calculating execution time will use );
  • 2、 In execution SQL after , First of all , Gets the context of the current request , Why get context , Because you need to get this request information from the context , second , obtain SQL Time before execution , Used to calculate execution time , Third , Get the executed SQL Information , Then set the data to Trace in ,Trace It's the link package in the project , It will be introduced in the following article ;

You need to use GORM Two Knowledge point Callbacks and Context, These two are in GORM V2 Only some , need import My bag is gorm.io/gorm.

Demo code

Context You need to use GORM V2 Provided WithContext() Method .

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
}

To write CallBacks Plug-in code ,GORM Of Plugin The interface is very simple , Just implement two methods .

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

Here is my plug-in code :

type TracePlugin struct{}

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

func (op *TracePlugin) Initialize(db *gorm.DB) (err error) {
    //  Prior to the start 
    _ = 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)

    //  After the end 
    _ = 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
}

Last , stay db Use this plug-in when connecting :

//  The use of plug-in 
db.Use(&TracePlugin{})

effect

mysql.png

Summary

This is written trace Part of the package , This package can record this information :

  • Support settings trace_id
  • Support settings request Information
  • Support settings response Information
  • Support settings third_party_requests Three parties request information
  • Support settings debugs Print debug information
  • Support settings sqls perform SQL Information
  • Recordable cost_seconds The execution time

The above code is go-gin-api In the project , Address :https://github.com/xinliangno...

版权声明
本文为[Xinliang]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/01/20210123165713244f.html