From 1a6fea8d9eaa941d939e40efaaf1f599ce76bfde Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Mon, 1 May 2023 19:35:00 -0700 Subject: [PATCH] logrus --- Makefile | 4 +- cmd/main.go | 20 +++++ error/doc.go | 7 +- error/error.go | 4 +- go.mod | 10 +-- go.sum | 38 ++-------- logr/factory.go | 60 --------------- logr/logger.go | 189 ++++++++++++++++++++++-------------------------- test/main.go | 13 ---- 9 files changed, 121 insertions(+), 224 deletions(-) create mode 100644 cmd/main.go delete mode 100644 logr/factory.go delete mode 100644 test/main.go diff --git a/Makefile b/Makefile index a38ff50..9ec147f 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ PKG = ./error/... \ ./logr/... \ - ./test/... + ./cmd/... bin: fmt vet - go build -o bin/test github.com/jortel/go-utils/test + go build -o bin/cmd github.com/jortel/go-utils/cmd fmt: go fmt ${PKG} diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..5a9c542 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "errors" + liberr "github.com/jortel/go-utils/error" + "github.com/jortel/go-utils/logr" +) + +func main() { + log := logr.WithName("Test") + log.Info("HELLO", "name", "jeff") + err := liberr.New("This failed.", "name", "elmer") + log.Error(err, "Test this error message.") + err = liberr.Wrap(err, "This is bad.") + log.Error(err, "Test this error message (2).") + err = liberr.Wrap(err, "Wrapped again.") + log.Error(err, "Test this error message (3).") + err = errors.New("Plain error.") + log.Error(err, "") +} diff --git a/error/doc.go b/error/doc.go index 5e7255a..ed24c2a 100644 --- a/error/doc.go +++ b/error/doc.go @@ -1,5 +1,5 @@ /* -The error package provides practical wrap/unwrap features. +Package error package provides practical wrap/unwrap features. The Wrap() function will capture caller provided and the captured stack. The stack is captured only on the first call to Wrap(). Subsequent calls to Wrap() will augment the description and key/value @@ -18,10 +18,7 @@ c = Unwrap(b) // a == c // // Wrap with context. url := "http://host/..." -d := e1.Wrap( - a, "Web request failed." - "url", url) - +d := e1.Wrap("Web request failed.", "url", url) d.Error() // "Web request failed. caused by: 'No route to host'" d.Context() // []string{"url", "http://host/..."} */ diff --git a/error/error.go b/error/error.go index 563ec18..398a421 100644 --- a/error/error.go +++ b/error/error.go @@ -3,7 +3,6 @@ package error import ( "errors" "fmt" - "math" "runtime" "strings" ) @@ -127,8 +126,7 @@ func (e *Error) append(kvpair []interface{}) { if len(kvpair) == 0 { return } - fLen := float64(len(kvpair)) - odd := math.Mod(fLen, 2) != 0 + odd := len(kvpair)%2 != 0 if description, cast := kvpair[0].(string); odd && cast { kvpair = kvpair[1:] if len(e.description) > 0 { diff --git a/go.mod b/go.mod index df1a2ca..eb09ecc 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,17 @@ module github.com/jortel/go-utils go 1.18 require ( - github.com/go-logr/logr v1.2.4 - github.com/go-logr/zapr v1.2.3 github.com/onsi/gomega v1.27.6 - go.uber.org/zap v1.24.0 + github.com/sirupsen/logrus v1.9.0 ) require ( + github.com/go-logr/logr v1.2.4 // indirect github.com/google/go-cmp v0.5.9 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect + github.com/kr/pretty v0.1.0 // indirect golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9691f53..e64f326 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,8 @@ -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -20,47 +15,24 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -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= diff --git a/logr/factory.go b/logr/factory.go deleted file mode 100644 index f815286..0000000 --- a/logr/factory.go +++ /dev/null @@ -1,60 +0,0 @@ -package logr - -import ( - "github.com/go-logr/logr" - "github.com/go-logr/zapr" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "os" -) - -// -// Builder factory. -type Builder interface { - New() logr.Logger - V(int, logr.Logger) logr.LogSink -} - -// -// ZapBuilder factory. -type ZapBuilder struct { -} - -// -// New returns a new logger. -func (b *ZapBuilder) New() (logger logr.Logger) { - var encoder zapcore.Encoder - sinker := zapcore.AddSync(os.Stderr) - level := zap.NewAtomicLevelAt(zap.DebugLevel) - options := []zap.Option{ - zap.AddStacktrace(zap.ErrorLevel), - zap.ErrorOutput(sinker), - zap.AddCallerSkip(1), - } - if Settings.Development { - cfg := zap.NewDevelopmentEncoderConfig() - encoder = zapcore.NewConsoleEncoder(cfg) - options = append(options, zap.Development()) - } else { - cfg := zap.NewProductionEncoderConfig() - encoder = zapcore.NewJSONEncoder(cfg) - } - logger = zapr.NewLogger( - zap.New( - zapcore.NewCore( - encoder, - sinker, - level)).WithOptions(options...)) - return -} - -// -// V returns a logger with level. -func (b *ZapBuilder) V(level int, in logr.Logger) (out logr.LogSink) { - if Settings.atDebug(level) { - out = in.V(1).GetSink() - } else { - out = in.V(0).GetSink() - } - return -} diff --git a/logr/logger.go b/logr/logger.go index 64fea80..11925f9 100644 --- a/logr/logger.go +++ b/logr/logger.go @@ -1,66 +1,72 @@ package logr import ( + "fmt" "github.com/go-logr/logr" liberr "github.com/jortel/go-utils/error" + log "github.com/sirupsen/logrus" "os" "strconv" ) -const ( - Stack = "stacktrace" - Error = "error" - None = "" -) const ( EnvDevelopment = "LOG_DEVELOPMENT" + EnvJson = "LOG_JSON" EnvLevel = "LOG_LEVEL" ) -// -// Settings is sink settings. -var Settings _Settings - -func init() { - Settings.Load() -} - -// -// Factory is a factory. -var Factory Builder - -func init() { - Factory = &ZapBuilder{} -} - // // Sink -. type Sink struct { - Delegate logr.LogSink - name string + development bool + delegate *log.Logger + fields log.Fields + name string + json bool + level int } // // WithName returns a named logger. func WithName(name string, kvpair ...interface{}) logr.Logger { - d := Factory.New() - s := &Sink{ - Delegate: d.GetSink(), - name: name, - } - s.Delegate = s.Delegate.WithValues(kvpair...) - s.Delegate = s.Delegate.WithName(name) - return logr.New(s) + return logr.New(&Sink{name: name}) } -func (s *Sink) Init(info logr.RuntimeInfo) { - return +func (s *Sink) Init(_ logr.RuntimeInfo) { + s.delegate = log.New() + v := os.Getenv(EnvDevelopment) + b, _ := strconv.ParseBool(v) + s.development = b + if s.development { + fmt := new(log.TextFormatter) + fmt.TimestampFormat = "2006-01-02 15:04:05" + fmt.FullTimestamp = true + s.delegate.SetFormatter(fmt) + } else { + fmt := new(log.TextFormatter) + fmt.FullTimestamp = true + fmt.DisableColors = true + fmt.DisableQuote = true + s.delegate.SetFormatter(fmt) + } + v = os.Getenv(EnvJson) + s.json, _ = strconv.ParseBool(v) + if s.json { + fmt := new(log.JSONFormatter) + fmt.PrettyPrint = true + s.delegate.Formatter = fmt + } + v = os.Getenv(EnvLevel) + n, _ := strconv.Atoi(v) + s.level = n } // // Info logs at info. -func (s *Sink) Info(level int, message string, kvpair ...interface{}) { - s.Delegate.Info(level, message, kvpair...) +func (s *Sink) Info(_ int, message string, kvpair ...interface{}) { + fields := s.asFields(kvpair...) + entry := s.delegate.WithFields(fields) + entry.Info(s.named(message)) } // @@ -69,101 +75,78 @@ func (s *Sink) Error(err error, message string, kvpair ...interface{}) { if err == nil { return } - le, wrapped := err.(*liberr.Error) - if wrapped { - err = le.Unwrap() - if context := le.Context(); context != nil { + xErr, cast := err.(*liberr.Error) + if cast { + err = xErr.Unwrap() + if context := xErr.Context(); context != nil { context = append( context, kvpair...) kvpair = context } - kvpair = append( - kvpair, - Error, - le.Error(), - Stack, - le.Stack()) - - s.Delegate.Info(0, message, kvpair...) - return - } - if wErr, wrapped := err.(interface { - Unwrap() error - }); wrapped { - err = wErr.Unwrap() - } - if err == nil { - return + if s.json { + fields := s.asFields(kvpair...) + fields["error"] = xErr.Error() + fields["stack"] = xErr.Stack() + fields["logger"] = s.name + entry := s.delegate.WithFields(fields) + entry.Error(s.named(message)) + } else { + fields := s.asFields(kvpair...) + entry := s.delegate.WithFields(fields) + if message != "" { + entry.Error(s.named(message), "\n", xErr.Error(), xErr.Stack()) + } else { + entry.Error(s.named(xErr.Error()), xErr.Stack()) + } + } + } else { + if wErr, wrapped := err.(interface { + Unwrap() error + }); wrapped { + err = wErr.Unwrap() + } + err = liberr.Wrap(err) + s.Error(err, message, kvpair...) } - - s.Delegate.Error(err, message, kvpair...) -} - -// -// Trace logs an error without a description. -func (s *Sink) Trace(err error, kvpair ...interface{}) { - s.Error(err, None, kvpair...) } // // Enabled returns whether logger is enabled. func (s *Sink) Enabled(level int) bool { - return s.Delegate.Enabled(level) + return s.level >= level } // // WithName returns a logger with name. func (s *Sink) WithName(name string) logr.LogSink { - return &Sink{ - Delegate: s.Delegate.WithName(name), - name: name, - } + return &Sink{name: name} } // // WithValues returns a logger with values. func (s *Sink) WithValues(kvpair ...interface{}) logr.LogSink { return &Sink{ - Delegate: s.Delegate.WithValues(kvpair...), - name: s.name, + name: s.name, + fields: s.asFields(kvpair), } } -// -// Package settings. -type _Settings struct { - // Debug threshold. - // Level determines when the real - // debug logger is used. - DebugThreshold int - // Development configuration. - Development bool - // Info level threshold. - // Higher level increases verbosity. - Level int -} - -// -// Load determine development logger. -func (r *_Settings) Load() { - r.DebugThreshold = 4 - if s, found := os.LookupEnv(EnvDevelopment); found { - bv, err := strconv.ParseBool(s) - if err == nil { - r.Development = bv - } - } - if s, found := os.LookupEnv(EnvLevel); found { - n, err := strconv.ParseInt(s, 10, 8) - if err == nil { - r.Level = int(n) +func (s *Sink) asFields(kvpair ...interface{}) log.Fields { + fields := log.Fields{} + for i := range kvpair { + if i%2 != 0 { + key := fmt.Sprintf("%v", kvpair[i-1]) + fields[key] = kvpair[i] } } + return fields } -// -// The level is at or above the debug threshold. -func (r *_Settings) atDebug(level int) bool { - return level >= r.DebugThreshold +func (s *Sink) named(message string) (m string) { + if s.name != "" { + m = "[" + s.name + "] " + } + m = m + message + return } diff --git a/test/main.go b/test/main.go deleted file mode 100644 index 00033bd..0000000 --- a/test/main.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - liberr "github.com/jortel/go-utils/error" - "github.com/jortel/go-utils/logr" -) - -func main() { - var err error - err = liberr.Wrap(err) - log := logr.WithName("Test") - log.Info("Hello World") -}