From 063546bab08bd3cf2cc45a9c673d9a4114aa771f Mon Sep 17 00:00:00 2001 From: thanatos Date: Mon, 3 Nov 2025 17:18:18 +0800 Subject: [PATCH] fix caller ignore lxutils --- lxDb/db.go | 3 +- lxlog/lxgorm.go | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 lxlog/lxgorm.go diff --git a/lxDb/db.go b/lxDb/db.go index 31fe504..c7cc31e 100644 --- a/lxDb/db.go +++ b/lxDb/db.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "os" + "git.listensoft.net/tool/lxutils/lxlog" "git.listensoft.net/tool/lxutils/lxzap" "github.com/gin-gonic/gin" "github.com/go-sql-driver/mysql" @@ -117,7 +118,7 @@ func InitDB(env string, conf DbConfig) { } if env == "dev" { db, err := gorm.Open(gormMysql.Open(dsn), &gorm.Config{ - Logger: logger.Default.LogMode(logger.Info), + Logger: lxlog.Default.LogMode(logger.Info), NamingStrategy: schema.NamingStrategy{ SingularTable: true, // 使用单数表名,启用该选项,此时,`User` 的表名应该是 `user` }, diff --git a/lxlog/lxgorm.go b/lxlog/lxgorm.go new file mode 100644 index 0000000..4c41c33 --- /dev/null +++ b/lxlog/lxgorm.go @@ -0,0 +1,146 @@ +package lxlog + +import ( + "context" + "errors" + "fmt" + "log" + "os" + "runtime" + "strconv" + "strings" + "time" + + "gorm.io/gorm/logger" + "gorm.io/gorm/utils" +) + +var ( + Default = NewDevLogger(log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ + SlowThreshold: 200 * time.Millisecond, + LogLevel: logger.Warn, + IgnoreRecordNotFoundError: false, + Colorful: true, + }) +) + +// NewDevLogger initialize logger +func NewDevLogger(writer logger.Writer, config logger.Config) logger.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 = logger.Green + "%s\n" + logger.Reset + logger.Green + "[info] " + logger.Reset + warnStr = logger.BlueBold + "%s\n" + logger.Reset + logger.Magenta + "[warn] " + logger.Reset + errStr = logger.Magenta + "%s\n" + logger.Reset + logger.Red + "[error] " + logger.Reset + traceStr = logger.Green + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s" + traceWarnStr = logger.Green + "%s " + logger.Yellow + "%s\n" + logger.Reset + logger.RedBold + "[%.3fms] " + logger.Yellow + "[rows:%v]" + logger.Magenta + " %s" + logger.Reset + traceErrStr = logger.RedBold + "%s " + logger.MagentaBold + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s" + } + + return &DevLogger{ + Writer: writer, + Config: config, + infoStr: infoStr, + warnStr: warnStr, + errStr: errStr, + traceStr: traceStr, + traceWarnStr: traceWarnStr, + traceErrStr: traceErrStr, + } +} + +type DevLogger struct { + logger.Writer + logger.Config + infoStr, warnStr, errStr string + traceStr, traceErrStr, traceWarnStr string +} + +// LogMode log mode +func (l *DevLogger) LogMode(level logger.LogLevel) logger.Interface { + newlogger := *l + newlogger.LogLevel = level + return &newlogger +} + +// Info print info +func (l *DevLogger) Info(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= logger.Info { + l.Printf(l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + } +} + +// Warn print warn messages +func (l *DevLogger) Warn(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= logger.Warn { + l.Printf(l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + } +} + +// Error print error messages +func (l *DevLogger) Error(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= logger.Error { + l.Printf(l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + } +} + +// Trace print sql message +// +//nolint:cyclop +func (l *DevLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { + if l.LogLevel <= logger.Silent { + return + } + + elapsed := time.Since(begin) + switch { + case err != nil && l.LogLevel >= logger.Error && (!errors.Is(err, logger.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError): + sql, rows := fc() + if rows == -1 { + l.Printf(l.traceErrStr, l.getCaller(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + l.Printf(l.traceErrStr, l.getCaller(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= logger.Warn: + sql, rows := fc() + slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold) + if rows == -1 { + l.Printf(l.traceWarnStr, l.getCaller(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + l.Printf(l.traceWarnStr, l.getCaller(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + case l.LogLevel == logger.Info: + sql, rows := fc() + if rows == -1 { + l.Printf(l.traceStr, l.getCaller(), float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + l.Printf(l.traceStr, l.getCaller(), float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + } +} + +// 获取调用者信息 +func (l *DevLogger) getCaller() string { + pcs := [15]uintptr{} + // the third caller usually from gorm internal + len := runtime.Callers(3, pcs[:]) + frames := runtime.CallersFrames(pcs[:len]) + for i := 0; i < len; i++ { + // second return value is "more", not "ok" + frame, _ := frames.Next() + + // 排序 gorm.io tool/lxutils 这个三种类型的 数据库调用 + if ((!strings.Contains(frame.File, "gorm.io/") && !strings.Contains(frame.File, "tool/lxutils")) || + strings.HasSuffix(frame.File, "_test.go")) && !strings.HasSuffix(frame.File, ".gen.go") { + return string(strconv.AppendInt(append([]byte(frame.File), ':'), int64(frame.Line), 10)) + } + } + return "unknown" +}