本文次要钻研一下gorm的logger

logger

gorm.io/gorm@v1.20.10/logger/logger.go

type logger struct {    Writer    Config    infoStr, warnStr, errStr            string    traceStr, traceErrStr, traceWarnStr string}type Writer interface {    Printf(string, ...interface{})}type Config struct {    SlowThreshold time.Duration    Colorful      bool    LogLevel      LogLevel}
logger内嵌了Writer、Config、定义了info、warn、err、trace、traceErr、traceWarn属性

logger.New

gorm.io/gorm@v1.20.10/logger/logger.go

func New(writer Writer, config Config) Interface {    var (        infoStr      = "%s\n[info] "        warnStr      = "%s\n[warn] "        errStr       = "%s\n[error] "        traceStr     = "%s\n[%.3fms] [rows:%v] %s"        traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s"        traceErrStr  = "%s %s\n[%.3fms] [rows:%v] %s"    )    if config.Colorful {        infoStr = Green + "%s\n" + Reset + Green + "[info] " + Reset        warnStr = BlueBold + "%s\n" + Reset + Magenta + "[warn] " + Reset        errStr = Magenta + "%s\n" + Reset + Red + "[error] " + Reset        traceStr = Green + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"        traceWarnStr = Green + "%s " + Yellow + "%s\n" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset        traceErrStr = RedBold + "%s " + MagentaBold + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"    }    return &logger{        Writer:       writer,        Config:       config,        infoStr:      infoStr,        warnStr:      warnStr,        errStr:       errStr,        traceStr:     traceStr,        traceWarnStr: traceWarnStr,        traceErrStr:  traceErrStr,    }}
logger.New依据config来创立logger

Interface

// Interface logger interfacetype Interface interface {    LogMode(LogLevel) Interface    Info(context.Context, string, ...interface{})    Warn(context.Context, string, ...interface{})    Error(context.Context, string, ...interface{})    Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error)}
logger.Interface接口定义了LogMode、Info、Warn、Error、Trace办法

LogMode

// LogMode log modefunc (l *logger) LogMode(level LogLevel) Interface {    newlogger := *l    newlogger.LogLevel = level    return &newlogger}// Info print infofunc (l logger) Info(ctx context.Context, msg string, data ...interface{}) {    if l.LogLevel >= Info {        l.Printf(l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)    }}// Warn print warn messagesfunc (l logger) Warn(ctx context.Context, msg string, data ...interface{}) {    if l.LogLevel >= Warn {        l.Printf(l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)    }}// Error print error messagesfunc (l logger) Error(ctx context.Context, msg string, data ...interface{}) {    if l.LogLevel >= Error {        l.Printf(l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)    }}// Trace print sql messagefunc (l logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {    if l.LogLevel > Silent {        elapsed := time.Since(begin)        switch {        case err != nil && l.LogLevel >= Error:            sql, rows := fc()            if rows == -1 {                l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)            } else {                l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)            }        case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= Warn:            sql, rows := fc()            slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold)            if rows == -1 {                l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)            } else {                l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)            }        default:            sql, rows := fc()            if rows == -1 {                l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)            } else {                l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)            }        }    }}
logger实现了logger.Interface接口定义的LogMode、Info、Warn、Error、Trace办法

Session.Logger

gorm.io/gorm@v1.20.10/gorm.go

type Session struct {    DryRun                   bool    PrepareStmt              bool    NewDB                    bool    SkipHooks                bool    SkipDefaultTransaction   bool    DisableNestedTransaction bool    AllowGlobalUpdate        bool    FullSaveAssociations     bool    QueryFields              bool    Context                  context.Context    Logger                   logger.Interface    NowFunc                  func() time.Time    CreateBatchSize          int}
Logger定义了Logger属性,最初设置到DB.Logger

callback

gorm.io/gorm@v1.20.10/callbacks.go

func (c *callback) Remove(name string) error {    c.processor.db.Logger.Warn(context.Background(), "removing callback `%v` from %v\n", name, utils.FileWithLineNum())    c.name = name    c.remove = true    c.processor.callbacks = append(c.processor.callbacks, c)    return c.processor.compile()}func (c *callback) Replace(name string, fn func(*DB)) error {    c.processor.db.Logger.Info(context.Background(), "replacing callback `%v` from %v\n", name, utils.FileWithLineNum())    c.name = name    c.handler = fn    c.replace = true    c.processor.callbacks = append(c.processor.callbacks, c)    return c.processor.compile()}
callback的Remove、Replace等办法会应用db.Logger进行打印

实例

func loggerDemo() {    newLogger := logger.New(        log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer        logger.Config{            SlowThreshold: time.Second,   // 慢 SQL 阈值            LogLevel:      logger.Silent, // Log level            Colorful:      true,          // 黑白打印        },    )    // 全局模式    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{        Logger: newLogger,    })    if err != nil {        panic(err)    }    if err := db.AutoMigrate(&User{}); err != nil {        panic(err)    }    // 新建会话模式    tx := db.Session(&gorm.Session{Logger: newLogger})    user := User{Name: "Tom", Age: 18, Birthday: time.Now()}    result := db.Create(&user) // pass pointer of data to Create    log.Println("userId:", user.ID)    log.Println("result.RowsAffected:", result.RowsAffected, "result.Error:", result.Error)    tx.First(&user)    log.Printf("%+v", user)    tx.Model(&user).Update("Age", 18)}

输入

2021/01/10 23:32:42 userId: 62021/01/10 23:32:42 result.RowsAffected: 1 result.Error: <nil>2021/01/10 23:32:42 {ID:6 Name:Tom Age:18 Birthday:2021-01-10 23:32:42.818057 +0800 +0800 DeletedAt:<nil> CreatedAt:2021-01-10 23:32:42.818107 +0800 +0800 UpdatedAt:2021-01-10 23:32:42.818107 +0800 +0800}

小结

gorm的logger提供了Interface接口,能够本人实现并全局设置或者在session级别设置;gorm默认的logger实现了logger.Interface接口定义的LogMode、Info、Warn、Error、Trace办法。

doc

  • gorm