package dagapm
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"gorm.io/gorm"
"time"
)
type GormDBWrapper struct {
}
const (
gormTranceName = "gorm_trance"
callBackBeforeName = "opentracing:before"
callBackAfterName = "opentracing:after"
)
func (g *GormDBWrapper) Name() string {
return "GormDB"
}
func varsToString(vars []interface{}) []string {
res := make([]string, 0, len(vars))
for _, value := range vars {
res = append(res, value.(string))
}
return res
}
func gormBefore(db *gorm.DB) {
trance := otel.Tracer(gormTranceName)
beginTime := time.Now()
_, span := trance.Start(context.Background(), "gormtrance")
if span != nil {
span.SetAttributes(
attribute.String("sql.query", db.Statement.SQL.String()),
attribute.StringSlice("sql.args", varsToString(db.Statement.Vars)),
)
}
db.InstanceSet("begin_time", beginTime)
db.InstanceSet("otel_span", span)
}
func gormAfter(db *gorm.DB) {
span := trace.SpanFromContext(db.Statement.Context)
defer span.End()
beginTime, isExit := db.InstanceGet("begin_time")
if !isExit {
return
}
now := time.Now()
if now.Sub(beginTime.(time.Time)) > time.Second {
span.SetAttributes(
attribute.Bool("slowsql", true))
}
}
func (g *GormDBWrapper) Initialize(db *gorm.DB) error {
err := db.Callback().Create().Before("gorm_create").Register(callBackBeforeName, gormBefore)
if err != nil {
return err
}
err = db.Callback().Delete().Before("gorm_delete").Register(callBackBeforeName, gormBefore)
if err != nil {
return err
}
err = db.Callback().Query().Before("gorm_query").Register(callBackBeforeName, gormBefore)
if err != nil {
return err
}
err = db.Callback().Row().Before("gorm_row").Register(callBackBeforeName, gormBefore)
if err != nil {
return err
}
err = db.Callback().Raw().Before("gorm_raw").Register(callBackBeforeName, gormBefore)
if err != nil {
return err
}
err = db.Callback().Update().Before("gorm_update").Register(callBackBeforeName, gormBefore)
if err != nil {
return err
}
err = db.Callback().Row().After("gorm_row").Register(callBackBeforeName, gormAfter)
if err != nil {
return err
}
err = db.Callback().Create().After("gorm_create").Register(callBackAfterName, gormAfter)
if err != nil {
return err
}
err = db.Callback().Delete().After("gorm_delete").Register(callBackAfterName, gormAfter)
if err != nil {
return err
}
err = db.Callback().Update().After("gorm_update").Register(callBackAfterName, gormAfter)
if err != nil {
return err
}
err = db.Callback().Raw().After("gorm_raw").Register(callBackAfterName, gormAfter)
if err != nil {
return err
}
err = db.Callback().Query().After("gorm_query").Register(callBackAfterName, gormAfter)
if err != nil {
return err
}
return err
}