Gorm 自定义logger 实现

1. 创建一个自定义的 Logger

首先,你需要创建一个实现 GORM Logger 接口的结构体。GORM 的 Logger 接口定义在 gorm.io/gorm/logger 包中。

package main

import (
	"context"
	"fmt"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/utils"
)

// CustomLogger 是自定义的 Logger 结构体
type CustomLogger struct {
	logger.Config
}

// LogMode 设置日志级别
func (c *CustomLogger) LogMode(level logger.LogLevel) logger.Interface {
	newlogger := *c
	newlogger.LogLevel = level
	return &newlogger
}

// Info 打印 info 级别日志
func (c *CustomLogger) Info(ctx context.Context, msg string, data ...interface{}) {
	if c.LogLevel >= logger.Info {
		fmt.Printf("[INFO] "+msg+"\n", data...)
	}
}

// Warn 打印 warning 级别日志
func (c *CustomLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
	if c.LogLevel >= logger.Warn {
		fmt.Printf("[WARN] "+msg+"\n", data...)
	}
}

// Error 打印 error 级别日志
func (c *CustomLogger) Error(ctx context.Context, msg string, data ...interface{}) {
	if c.LogLevel >= logger.Error {
		fmt.Printf("[ERROR] "+msg+"\n", data...)
	}
}

// Trace 打印 trace 级别日志
func (c *CustomLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
	if c.LogLevel <= 0 {
		return
	}

	elapsed := time.Since(begin)
	switch {
	case err != nil && c.LogLevel >= logger.Error:
		sql, rows := fc()
		if rows == -1 {
			fmt.Printf("[ERROR] %s [%.3fms] [rows:%v] %s\n", err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
		} else {
			fmt.Printf("[ERROR] %s [%.3fms] [rows:%v] %s\n", err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
		}
	case elapsed > c.SlowThreshold && c.SlowThreshold != 0 && c.LogLevel >= logger.Warn:
		sql, rows := fc()
		slowLog := fmt.Sprintf("SLOW SQL >= %v", c.SlowThreshold)
		if rows == -1 {
			fmt.Printf("[WARN] %s [%.3fms] [rows:%v] %s\n", slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)
		} else {
			fmt.Printf("[WARN] %s [%.3fms] [rows:%v] %s\n", slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
		}
	case c.LogLevel >= logger.Info:
		sql, rows := fc()
		if rows == -1 {
			fmt.Printf("[INFO] [%.3fms] [rows:%v] %s\n", float64(elapsed.Nanoseconds())/1e6, "-", sql)
		} else {
			fmt.Printf("[INFO] [%.3fms] [rows:%v] %s\n", float64(elapsed.Nanoseconds())/1e6, rows, sql)
		}
	}
}

func main() {
	// 使用自定义 Logger 初始化 GORM
	db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
		Logger: &CustomLogger{
			Config: logger.Config{
				SlowThreshold:             time.Second,
				LogLevel:                  logger.Info,
				IgnoreRecordNotFoundError: true,
				Colorful:                  true,
			},
		},
	})
	if err != nil {
		panic("failed to connect database")
	}

	// 示例数据库操作
	var result interface{}
	db.First(&result)
}

2. 配置 GORM 使用自定义 Logger

在上面的代码中,CustomLogger 实现了 GORM 的 Logger 接口,并在 gorm.Open 函数中作为配置传递给 GORM。你可以根据需要调整 CustomLogger 的实现,以满足你的日志记录需求。

通过这种方式,你可以完全控制 GORM 的日志输出格式和内容,便于调试和监控数据库操作。