diff --git a/config.go b/config.go index 4dcf8af..19d7a5d 100644 --- a/config.go +++ b/config.go @@ -8,8 +8,9 @@ type Config struct { } type Logger struct { - Encoder string `yaml:"encoder"` - Level string `yaml:"level"` + Encoder string `yaml:"encoder"` + Level string `yaml:"level"` + StackLevel string `yaml:"stack_level"` } type File struct { diff --git a/default_logger.yaml b/default_logger.yaml index 10d4320..b634fe5 100644 --- a/default_logger.yaml +++ b/default_logger.yaml @@ -4,6 +4,7 @@ logger: encoder: json # 日志级别 level: info + stack_level: panic # 文件形式 file: diff --git a/go.mod b/go.mod index ea33271..326b51f 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,8 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/grafana/loki/pkg/push v0.0.0-20240912152814-63e84b476a9a // indirect github.com/grafana/regexp v0.0.0-20220304095617-2e8d9baf4ac2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect @@ -50,4 +52,5 @@ require ( google.golang.org/grpc v1.56.3 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gorm.io/gorm v1.31.0 // indirect ) diff --git a/go.sum b/go.sum index 2435614..e7f8ddf 100644 --- a/go.sum +++ b/go.sum @@ -694,6 +694,10 @@ github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9 github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -1822,6 +1826,8 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY= +gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= diff --git a/gorm.go b/gorm.go new file mode 100644 index 0000000..1bea7c1 --- /dev/null +++ b/gorm.go @@ -0,0 +1,68 @@ +package zap_logger + +import ( + "context" + "errors" + "fmt" + "time" + + "code.mrx.ltd/pkg/logger/log" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +type gormLogger struct{ logger.Config } + +func NewGormLogger(gl logger.Config) *gormLogger { + return &gormLogger{gl} +} + +func (g *gormLogger) LogMode(level logger.LogLevel) logger.Interface { + g.LogLevel = level + return g +} + +func (g *gormLogger) Info(ctx context.Context, msg string, args ...interface{}) { + if g.LogLevel >= logger.Info { + log.Infof(msg, args...) + } +} + +func (g *gormLogger) Warn(ctx context.Context, msg string, args ...interface{}) { + if g.LogLevel >= logger.Warn { + log.Warnf(msg, args...) + } +} + +func (g *gormLogger) Error(ctx context.Context, msg string, args ...interface{}) { + if g.LogLevel >= logger.Error { + log.Errorf(msg, args...) + } +} + +func (g *gormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) { + if g.LogLevel <= logger.Silent { + return + } + + sql, rows := fc() + elapsed := time.Since(begin) + msg := fmt.Sprintf("[%v] [rows:%v] %s", elapsed, rows, sql) + if rows == -1 { + msg = fmt.Sprintf("[%v] [rows:%v] %s", elapsed, "-", sql) + } + if elapsed > g.SlowThreshold && g.SlowThreshold != 0 && g.LogLevel >= logger.Warn { + msg = fmt.Sprintf("[SLOW SQL] [%v] [rows:%v] %s", elapsed, rows, sql) + } + + switch { + case err != nil && g.LogLevel >= logger.Error && (!errors.Is(err, gorm.ErrRecordNotFound) || !g.IgnoreRecordNotFoundError): + msg = fmt.Sprintf("%s -> %s", err.Error(), msg) + g.Error(ctx, msg) + case elapsed > g.SlowThreshold && g.SlowThreshold != 0 && g.LogLevel >= logger.Warn: + msg = fmt.Sprintf("SLOW SQL -> %s", msg) + g.Warn(ctx, msg) + case g.LogLevel == logger.Info: + g.Info(ctx, msg) + } +} diff --git a/logger.go b/logger.go index 74414d6..05f8450 100644 --- a/logger.go +++ b/logger.go @@ -3,6 +3,7 @@ package zap_logger import ( "errors" "os" + "strings" _ "embed" @@ -68,11 +69,27 @@ func NewZapLogger(filePath string, opts ...Option) error { cores = append(cores, newConsoleLogger(config.Console).Init()) } + var stackLevel zapcore.Level + switch strings.ToLower(config.Logger.StackLevel) { + case "info": + stackLevel = zap.InfoLevel + case "warn": + stackLevel = zap.WarnLevel + case "error": + stackLevel = zap.ErrorLevel + case "panic": + stackLevel = zap.DPanicLevel + case "fatal": + stackLevel = zap.FatalLevel + default: + stackLevel = zap.DPanicLevel + } + logger := zap.New( - zapcore.NewTee(cores...), // 开启的日志核心 - zap.AddCaller(), // 启用调用者信息 - zap.AddCallerSkip(1), // 调用者信息跳过 - zap.AddStacktrace(zap.ErrorLevel), // 开启panic日志错误堆栈收集 + zapcore.NewTee(cores...), // 开启的日志核心 + zap.AddCaller(), // 启用调用者信息 + zap.AddCallerSkip(1), // 调用者信息跳过 + zap.AddStacktrace(stackLevel), // 开启panic日志错误堆栈收集 ) zap.ReplaceGlobals(logger) return nil