package mysql import ( "context" "errors" "time" "go.uber.org/zap" "gorm.io/gorm" gormlogger "gorm.io/gorm/logger" "spark-server/internal/infrastructure/logger" "spark-server/internal/pkg/reqctx" ) type gormZap struct { base *zap.Logger level gormlogger.LogLevel slow time.Duration } func newGormLogger(base *zap.Logger, slow time.Duration, level gormlogger.LogLevel) *gormZap { if base == nil { base = zap.NewNop() } if slow <= 0 { slow = 200 * time.Millisecond } if level == 0 { level = gormlogger.Warn } return &gormZap{base: base.Named("gorm"), level: level, slow: slow} } func (l *gormZap) LogMode(level gormlogger.LogLevel) gormlogger.Interface { cp := *l cp.level = level return &cp } func (l *gormZap) Info(ctx context.Context, msg string, data ...interface{}) { if l.level < gormlogger.Info { return } l.zap(ctx).Sugar().Infof(msg, data...) } func (l *gormZap) Warn(ctx context.Context, msg string, data ...interface{}) { if l.level < gormlogger.Warn { return } l.zap(ctx).Sugar().Warnf(msg, data...) } func (l *gormZap) Error(ctx context.Context, msg string, data ...interface{}) { if l.level < gormlogger.Error { return } l.zap(ctx).Sugar().Errorf(msg, data...) } func (l *gormZap) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { if l.level <= gormlogger.Silent { return } elapsed := time.Since(begin) sql, rows := fc() log := l.zap(ctx) switch { case err != nil && !errors.Is(err, gorm.ErrRecordNotFound) && l.level >= gormlogger.Error: log.Error("sql", zap.Error(err), zap.String("sql", sql), zap.Duration("elapsed", elapsed), zap.Int64("rows", rows)) case elapsed >= l.slow && l.level >= gormlogger.Warn: log.Warn("sql_slow", zap.String("sql", sql), zap.Duration("elapsed", elapsed), zap.Int64("rows", rows)) case l.level >= gormlogger.Info: log.Info("sql", zap.String("sql", sql), zap.Duration("elapsed", elapsed), zap.Int64("rows", rows)) } } func (l *gormZap) zap(ctx context.Context) *zap.Logger { if reqctx.From(ctx) != nil { return logger.From(ctx).Named("gorm") } return l.base } func parseGormLevel(s, zapLevel string) gormlogger.LogLevel { switch s { case "silent": return gormlogger.Silent case "error": return gormlogger.Error case "warn", "warning": return gormlogger.Warn case "info": return gormlogger.Info default: if zapLevel == "debug" { return gormlogger.Info } return gormlogger.Warn } }