package mysql import ( "context" "errors" "fmt" "git.hlsq.asia/alex/service-common/log" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.uber.org/zap" "gorm.io/gorm" "gorm.io/gorm/logger" "time" ) // Colors const ( Reset = "\033[0m" Blue = "\033[34m" ) type GormLogger struct { logLevel logger.LogLevel logger *zap.SugaredLogger } func NewGormLogger(level logger.LogLevel) *GormLogger { return &GormLogger{ logLevel: level, logger: log.GetLogger(). WithOptions(zap.AddCallerSkip(5)). Named("GORM"), } } func (l *GormLogger) LogMode(level logger.LogLevel) logger.Interface { newLogger := *l newLogger.logLevel = level return &newLogger } func (l *GormLogger) Info(ctx context.Context, msg string, data ...interface{}) { if l.logLevel >= logger.Info { l.logger.Infof(Blue+msg+Reset, data...) } } func (l *GormLogger) Warn(ctx context.Context, msg string, data ...interface{}) { if l.logLevel >= logger.Warn { l.logger.Warnf(Blue+msg+Reset, data...) } } func (l *GormLogger) Error(ctx context.Context, msg string, data ...interface{}) { if l.logLevel >= logger.Error { l.logger.Errorf(Blue+msg+Reset, data...) } } func (l *GormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) { if l.logLevel <= logger.Silent { return } elapsed := time.Since(begin) sql, rows := fc() if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { l.logger.Errorf(Blue+"[SLOW SQL] [%v] [rows:%v] [error: %v] %v"+Reset, elapsed, rows, err.Error(), sql) l.SlowLog(ctx, elapsed, sql) } else if elapsed > 50*time.Millisecond { l.logger.Warnf(Blue+"[SLOW SQL] [%v] [rows:%v] %v"+Reset, elapsed, rows, sql) l.SlowLog(ctx, elapsed, sql) } else { l.logger.Infof(Blue+"[%v] [rows:%v] %v"+Reset, elapsed, rows, sql) } } func (l *GormLogger) SlowLog(ctx context.Context, elapsed time.Duration, sql string) { _, span := otel.Tracer("common.db.mysql").Start(ctx, "mysql.slow") defer span.End() span.SetAttributes(attribute.String("elapsed", fmt.Sprintf("%v", elapsed))) span.SetAttributes(attribute.String("sql", sql)) }