Preface
In order to facilitate accurate troubleshooting, it is necessary to record the corresponding relationship between the current request information and the currently executed SQL information. The recorded SQL information includes:
The current time of SQL execution;
File address and line number for executing SQL;
The time it takes to execute SQL;
The number of rows affected by SQL execution;
SQL statement executed;
The database component is used GORM.
Ideas
Before executing SQL, set the start execution time (it will be used to calculate the execution time);
After executing SQL, first, get the context of the current request, why get the context, because you need to get the request information from the context, second, get the time before SQL execution, to calculate the execution time, third, Getting SQL execution information, and then set the data Tracein Tracea project link packet, it will be introduced later in the article;
Above the need to use GORM two knowledge points Callbacks and Context these two are GORM V2 only the need to import the package gorm.io/gorm.
Demo code
Context The transfer requires GORM V2 provided With Context() a 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
}
Write CallBacks plug-in code, written in GORM Plugin interface is very simple, you only need to implement two methods can be.
// Plugin GORM plugin interface
type Plugin interface {
Name() string
Initialize(*DB) error
}
Below is the plug-in code I wrote:
type TracePlugin struct{}
func (op *TracePlugin) Name() string {
return "tracePlugin"
}
func (op *TracePlugin) Initialize(db *gorm.DB) (err error) {
// Before starting
_ = 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
}
Finally, use this plug-in when db is connected:
// Use plugin
db.Use(&TracePlugin{})
summary
It is written in trace part of the package, this package can record information (JSON format):
Support setting trace_id
Support setting request information
Support setting response information
Support setting third_party_requests to request information
Support setting debugs to print debugging information
Support setting sqls to execute SQL information
Can record cost_seconds execution time
The above code is in the go-gin-api project, address:
github.com/xinliangnote/go-gin-api
See more Gorm tutorial
Top comments (0)