使用logrus记录gorm sql

时间:2021-7-3 作者:qvyue

gorm可以方便的输出执行的sql或慢查询。logrus是常用的日志组件,如何将gorm输出的sql通过logrus记录到日志中呢?

1. 代码实现

我们先看代码。

思路:使用logrus,实现gorm/logger.Writer接口

var DB *gorm.DB

//定义自己的Writer
type MyWriter struct {
    mlog *logrus.Logger
}

//实现gorm/logger.Writer接口 
func (m *MyWriter)Printf(format string , v ...interface{}){
    logstr  := fmt.Sprintf(format, v...)
    //利用loggus记录日志
    m.mlog.Info(logstr)
}

func NewMyWriter() *MyWriter{
    log := logrus.New()
    //配置logrus
    log.SetFormatter(&logrus.JSONFormatter{
        TimestampFormat:"2006-01-02 15:04:05",  
    })

    return &MyWriter{mlog:log}
}

//DB初始化
func Init() error {
    var err error
    dsn := "root:user237@tcp(10.160.75.237:3306)/mydb?charset=utf8&parseTime=true&loc=Local"

    slowLogger := logger.New(
        //设置Logger
        NewMyWriter(),
        logger.Config{
             //慢SQL阈值
            SlowThreshold: time.Millisecond,
            //设置日志级别,只有Warn以上才会打印sql
            LogLevel:      logger.Warn,
        },
    )

    DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
        Logger:slowLogger,
    })

    return err
}

... ...

func main(){
    //初始化
    _ = Init()

    d := User{
        Name:"ball",
        Age:0,
        IsAdmin:true,
        IsValid:false,
        LoginTime:time.Now(),
    }

    DB.Create(&d)
}

输出

{"level":"info","msg":"/home/ballqiu/go/gorm/main.go:90 SLOW SQL u003e= 1msn[4.333ms] [rows:1] INSERT INTO `User` (`name`,`age`,`is_admin`,`is_valid`,`login_time`) VALUES ('ball',0,true,false,'2021-05-14 18:58:17.857')","time":"2021-05-14 18:58:17"}

如果你将logrus配置输出至文件,日志就会写入文件中。

2. 代码解读

在作详细说明之前,先来看下上述代码使用到的interface和struct之间的关系。

使用logrus记录gorm sql
image
  • gorm.Open()的第二参数为Option接口,因为gorm.Config实现了该接口,因此可以作为参数传入。
/*gorm.go*/

func Open(dialector Dialector, opts ...Option) (db *DB, err error)
  • gorm.Config包含Logger成员,该成员为logger.Interface类型。logger.New()返回的是一个struct logger实例,它实现了Interface接口,因此可以赋值给gorm.Config.Logger。
    slowLogger := logger.New()
    DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
        Logger:slowLogger,
    })
  • logger.New的第一参数为logger.Writer接口,我们的MyWriter实现了该接口,因此可以传入。
/*gorm/logger/logger.go*/

func New(writer Writer, config Config) Interface {
    ...
    
    //
    return &logger{
        //传入的writer在此处赋给了logger
        Writer:       writer,
        Config:       config,
        infoStr:      infoStr,
        warnStr:      warnStr,
        errStr:       errStr,
        traceStr:     traceStr,
        traceWarnStr: traceWarnStr,
        traceErrStr:  traceErrStr,
    }
}

type Writer interface {
    Printf(string, ...interface{})
}
  • logger.** 在输出时调用了Printf(Writer接口),也就是我们自己的MyWriter.Printf,因此日志得以写入logrus
/*gorm/logger/logger.go*/
func (l logger) Info(ctx context.Context, msg string, data ...interface{}) {
    if l.LogLevel >= Info {
        l.Printf(l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
    }
}
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。