package mysql import ( "time" "bindbox-game/internal/pkg/core" "bindbox-game/internal/pkg/timeutil" "bindbox-game/internal/pkg/trace" "gorm.io/gorm" "gorm.io/gorm/utils" ) const ( callBackBeforeName = "core:before" callBackAfterName = "core:after" startTime = "_start_time" ) 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().Query().Before("gorm:query").Register("soft_delete:filter", softDeleteFilter) _ = 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) // 结束后 _ = 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.StdContext) 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.Time = timeutil.CSTLayoutString() sqlInfo.SQL = sql sqlInfo.Stack = utils.FileWithLineNum() sqlInfo.Rows = db.Statement.RowsAffected sqlInfo.CostSeconds = time.Since(ts).Seconds() if ctx.Trace != nil { ctx.Trace.AppendSQL(sqlInfo) } return } const softDeleteIgnoreKey = "soft_delete_ignore" var softDeleteTables = map[string]struct{}{ "activities": {}, "activity_issues": {}, "activity_reward_settings": {}, "products": {}, "product_categories": {}, "banner": {}, "guild": {}, "system_titles": {}, "system_title_effects": {}, "system_item_cards": {}, "system_coupons": {}, "menus": {}, "menu_actions": {}, "roles": {}, "role_users": {}, } func softDeleteFilter(db *gorm.DB) { v, ok := db.InstanceGet(softDeleteIgnoreKey) if ok { b, _ := v.(bool) if b { return } } tbl := db.Statement.Table if tbl == "" { return } if _, ok := softDeleteTables[tbl]; !ok { return } db.Where("deleted_at IS NULL") }