package logger import ( "context" "errors" "time" "go.uber.org/zap" "gorm.io/gorm" gormlogger "gorm.io/gorm/logger" "gorm.io/gorm/utils" ) // GormZapLogger adalah custom logger GORM yang menggunakan Zap type GormZapLogger struct { ZapLogger *zap.Logger LogLevel gormlogger.LogLevel SlowThreshold time.Duration } // NewGormZapLogger menginisialisasi logger baru func NewGormZapLogger(zapLog *zap.Logger, slowThreshold time.Duration) *GormZapLogger { return &GormZapLogger{ ZapLogger: zapLog, LogLevel: gormlogger.Info, // Atur default ke Info, bisa disesuaikan SlowThreshold: slowThreshold, // Waktu batas query dianggap lambat (misal 200ms) } } // LogMode mengubah level log GORM func (l *GormZapLogger) LogMode(level gormlogger.LogLevel) gormlogger.Interface { newLogger := *l newLogger.LogLevel = level return &newLogger } // Info mencetak log informasi biasa func (l *GormZapLogger) Info(ctx context.Context, msg string, data ...interface{}) { if l.LogLevel >= gormlogger.Info { l.ZapLogger.Sugar().Infof(msg, data...) } } // Warn mencetak log peringatan func (l *GormZapLogger) Warn(ctx context.Context, msg string, data ...interface{}) { if l.LogLevel >= gormlogger.Warn { l.ZapLogger.Sugar().Warnf(msg, data...) } } // Error mencetak log kesalahan func (l *GormZapLogger) Error(ctx context.Context, msg string, data ...interface{}) { if l.LogLevel >= gormlogger.Error { l.ZapLogger.Sugar().Errorf(msg, data...) } } // Trace mencetak log internal query SQL dari GORM func (l *GormZapLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { if l.LogLevel <= gormlogger.Silent { return } elapsed := time.Since(begin) sql, rows := fc() // Ambil lokasi file baris kode Go yang mengeksekusi query ini line := utils.FileWithLineNum() // Siapkan fields bawaan Zap agar log terstruktur dengan baik fields := []zap.Field{ zap.String("line", line), zap.Duration("elapsed", elapsed), zap.Int64("rows", rows), zap.String("sql", sql), } switch { // Kasus 1: Terjadi Error dan Error tersebut BUKAN Record NotFound case err != nil && l.LogLevel >= gormlogger.Error && !errors.Is(err, gorm.ErrRecordNotFound): fields = append(fields, zap.Error(err)) l.ZapLogger.Error("[GORM] query error", fields...) // Kasus 2: Query berjalan lambat melewati batas SlowThreshold case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= gormlogger.Warn: l.ZapLogger.Warn("[GORM] slow query warning", fields...) // Kasus 3: Log info query normal case l.LogLevel >= gormlogger.Info: l.ZapLogger.Info("[GORM] query execution", fields...) } }