• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

聊聊gorm的logger

互联网 diligentman 1周前 (01-10) 8次浏览

本文主要研究一下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      = "%sn[info] "
		warnStr      = "%sn[warn] "
		errStr       = "%sn[error] "
		traceStr     = "%sn[%.3fms] [rows:%v] %s"
		traceWarnStr = "%s %sn[%.3fms] [rows:%v] %s"
		traceErrStr  = "%s %sn[%.3fms] [rows:%v] %s"
	)

	if config.Colorful {
		infoStr = Green + "%sn" + Reset + Green + "[info] " + Reset
		warnStr = BlueBold + "%sn" + Reset + Magenta + "[warn] " + Reset
		errStr = Magenta + "%sn" + Reset + Red + "[error] " + Reset
		traceStr = Green + "%sn" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
		traceWarnStr = Green + "%s " + Yellow + "%sn" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset
		traceErrStr = RedBold + "%s " + MagentaBold + "%sn" + 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 interface
type 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 mode
func (l *logger) LogMode(level LogLevel) Interface {
	newlogger := *l
	newlogger.LogLevel = level
	return &newlogger
}

// Info print info
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...)...)
	}
}

// Warn print warn messages
func (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 messages
func (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 message
func (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 %vn", 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 %vn", 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, "rn", 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: 6
2021/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
{{o.name}}


{{m.name}}


程序员灯塔
转载请注明原文链接:https://www.wangt.cc/2021/01/%e8%81%8a%e8%81%8agorm%e7%9a%84logger/
喜欢 (0)