From 6f5a075eb91d73f2e7760c3c29ce6d71c9c64e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 10 Jul 2024 20:30:38 +0200 Subject: [PATCH 01/31] initial implementation of zerolog intergration --- go.mod | 3 +++ go.sum | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/go.mod b/go.mod index 14f6134b0..dde7da70a 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,8 @@ require ( golang.org/x/text v0.14.0 ) +require github.com/buger/jsonparser v1.1.1 // indirect + require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect @@ -70,6 +72,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/rs/zerolog v1.33.0 github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect diff --git a/go.sum b/go.sum index 1ac759933..379eaf169 100644 --- a/go.sum +++ b/go.sum @@ -16,9 +16,12 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1 github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -53,6 +56,7 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo= github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -119,6 +123,7 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -153,6 +158,9 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= @@ -257,6 +265,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From 833e318bb5fb950cc48abd2729b1114e30b1b7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 10 Jul 2024 20:30:45 +0200 Subject: [PATCH 02/31] initial implementation of zerolog intergration --- zerolog/zerolog.go | 294 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 zerolog/zerolog.go diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go new file mode 100644 index 000000000..61645b5d4 --- /dev/null +++ b/zerolog/zerolog.go @@ -0,0 +1,294 @@ +// Package sentryzerolog provides a simple Zerolog hook for Sentry. +package sentryzerolog + +import ( + "encoding/json" + "errors" + "io" + "net/http" + "time" + "unsafe" + + "github.com/buger/jsonparser" + sentry "github.com/getsentry/sentry-go" + "github.com/rs/zerolog" +) + +// A good portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer.go + +var ErrFlushTimeout = errors.New("sentryzerolog flush timeout") + +var levels = map[zerolog.Level]sentry.Level{ + zerolog.TraceLevel: sentry.LevelDebug, + zerolog.DebugLevel: sentry.LevelDebug, + zerolog.InfoLevel: sentry.LevelInfo, + zerolog.WarnLevel: sentry.LevelWarning, + zerolog.ErrorLevel: sentry.LevelError, + zerolog.FatalLevel: sentry.LevelFatal, + zerolog.PanicLevel: sentry.LevelFatal, +} + +var _ = io.WriteCloser(new(Writer)) + +var now = time.Now + +// The identifier of the Zerolog SDK. +const sdkIdentifier = "sentry.go.zerolog" + +// These default log field keys are used to pass specific metadata in a way that +// Sentry understands. If they are found in the log fields, and the value is of +// the expected datatype, it will be converted from a generic field, into Sentry +// metadata. +// +// These keys may be overridden by calling SetKey on the hook object. +const ( + // FieldRequest holds an *http.Request. + FieldRequest = "request" + // FieldUser holds a User or *User value. + FieldUser = "user" + // FieldTransaction holds a transaction ID as a string. + FieldTransaction = "transaction" + // FieldFingerprint holds a string slice ([]string), used to dictate the + // grouping of this event. + FieldFingerprint = "fingerprint" + + // These fields are simply omitted, as they are duplicated by the Sentry SDK. + FieldGoVersion = "go_version" + FieldMaxProcs = "go_maxprocs" +) + +// Writer is a sentry events writer with std io.Writer interface. +type Writer struct { + hub *sentry.Hub + + levels map[zerolog.Level]struct{} + flushTimeout time.Duration + withBreadcrumbs bool +} + +// addBreadcrumb adds event as a breadcrumb +func (w *Writer) addBreadcrumb(event *sentry.Event) { + if !w.withBreadcrumbs { + return + } + + category, _ := event.Extra["category"].(string) + + w.hub.AddBreadcrumb(&sentry.Breadcrumb{ + Category: category, + Message: event.Message, + Level: event.Level, + Data: event.Extra, + }, nil) +} + +// Write handles zerolog's json and sends events to sentry. +func (w *Writer) Write(data []byte) (n int, err error) { + n = len(data) + + lvl, err := w.parseLogLevel(data) + if err != nil { + return n, nil + } + + event, ok := w.parseLogEvent(data) + if !ok { + return + } + event.Level, ok = levels[lvl] + if !ok { + return + } + + if _, enabled := w.levels[lvl]; !enabled { + // if the level is not enabled, add event as a breadcrumb + w.addBreadcrumb(event) + return + } + + w.hub.CaptureEvent(event) + // should flush before os.Exit + if event.Level == sentry.LevelFatal { + w.hub.Flush(w.flushTimeout) + } + + return +} + +// implements zerolog.LevelWriter +func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) { + n = len(p) + + event, ok := w.parseLogEvent(p) + if !ok { + return + } + event.Level, ok = levels[level] + if !ok { + return + } + + if _, enabled := w.levels[level]; !enabled { + // if the level is not enabled, add event as a breadcrumb + w.addBreadcrumb(event) + return + } + + w.hub.CaptureEvent(event) + // should flush before os.Exit + if event.Level == sentry.LevelFatal { + w.hub.Flush(w.flushTimeout) + } + return +} + +// Close forces client to flush all pending events. +// Can be useful before application exits. +func (w *Writer) Close() error { + if ok := w.hub.Flush(w.flushTimeout); !ok { + return ErrFlushTimeout + } + return nil +} + +// parses the log level from the encoded log +func (w *Writer) parseLogLevel(data []byte) (zerolog.Level, error) { + level, err := jsonparser.GetUnsafeString(data, zerolog.LevelFieldName) + if err != nil { + return zerolog.Disabled, nil + } + + return zerolog.ParseLevel(level) +} + +const logger = "zerolog" + +// parses the event except the log level +func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) { + + event := sentry.Event{ + Timestamp: now(), + Logger: logger, + Extra: map[string]any{}, + } + + err := jsonparser.ObjectEach(data, func(key, value []byte, _ jsonparser.ValueType, _ int) error { + k := string(key) + switch k { + case zerolog.MessageFieldName: + event.Message = bytesToStrUnsafe(value) + case zerolog.ErrorFieldName: + event.Exception = append(event.Exception, sentry.Exception{ + Value: bytesToStrUnsafe(value), + Stacktrace: sentry.NewStacktrace(sentry.EventOptions{ + SkipFrames: 0, + }), + }) + case zerolog.LevelFieldName, zerolog.TimestampFieldName: + case FieldRequest: + var req *http.Request + err := json.Unmarshal(value, &req) + if err != nil { + event.Extra[k] = bytesToStrUnsafe(value) + } else { + event.Request = sentry.NewRequest(req) + } + case FieldUser: + var user sentry.User + err := json.Unmarshal(value, &user) + if err != nil { + event.Extra[k] = bytesToStrUnsafe(value) + } else { + event.User = user + } + case FieldTransaction: + event.Transaction = bytesToStrUnsafe(value) + case FieldFingerprint: + var fp []string + err := json.Unmarshal(value, &fp) + if err != nil { + event.Extra[k] = bytesToStrUnsafe(value) + } else { + event.Fingerprint = fp + } + default: + event.Extra[k] = bytesToStrUnsafe(value) + } + return nil + }) + return &event, err == nil +} + +func bytesToStrUnsafe(data []byte) string { + return *(*string)(unsafe.Pointer(&data)) +} + +type Config struct { + sentry.ClientOptions + Options +} + +type Options struct { + Levels []zerolog.Level + WithBreadcrumbs bool + FlushTimeout time.Duration +} + +func (o *Options) SetDefaults() { + if len(o.Levels) == 0 { + o.Levels = []zerolog.Level{ + zerolog.ErrorLevel, + zerolog.FatalLevel, + zerolog.PanicLevel, + } + } + + if o.FlushTimeout == 0 { + o.FlushTimeout = 3 * time.Second + } +} + +// New creates writer with provided DSN and options. +func New(cfg Config) (*Writer, error) { + client, err := sentry.NewClient(cfg.ClientOptions) + if err != nil { + return nil, err + } + + client.SetSDKIdentifier(sdkIdentifier) + + cfg.Options.SetDefaults() + + levels := make(map[zerolog.Level]struct{}, len(cfg.Levels)) + for _, lvl := range cfg.Levels { + levels[lvl] = struct{}{} + } + + return &Writer{ + hub: sentry.NewHub(client, sentry.NewScope()), + levels: levels, + flushTimeout: cfg.FlushTimeout, + withBreadcrumbs: cfg.WithBreadcrumbs, + }, nil +} + +// NewWithHub creates a writer using an existing sentry Hub and options. +func NewWithHub(hub *sentry.Hub, opts Options) (*Writer, error) { + if hub == nil { + return nil, errors.New("hub cannot be nil") + } + + opts.SetDefaults() + + levels := make(map[zerolog.Level]struct{}, len(opts.Levels)) + for _, lvl := range opts.Levels { + levels[lvl] = struct{}{} + } + + return &Writer{ + hub: hub, + levels: levels, + flushTimeout: opts.FlushTimeout, + withBreadcrumbs: opts.WithBreadcrumbs, + }, nil +} From 6aab5ccd2a1b61bc492893f92d3c74e718c0a3a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 10 Jul 2024 20:32:19 +0200 Subject: [PATCH 03/31] skip goversion and maxproxs --- zerolog/zerolog.go | 1 + 1 file changed, 1 insertion(+) diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index 61645b5d4..e2b62fe54 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -211,6 +211,7 @@ func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) { } else { event.Fingerprint = fp } + case FieldGoVersion, FieldMaxProcs: default: event.Extra[k] = bytesToStrUnsafe(value) } From a088e3fd4905e66d6d45a963d15a830451595353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 10 Jul 2024 20:36:21 +0200 Subject: [PATCH 04/31] linter fix --- zerolog/zerolog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index e2b62fe54..2d311dec6 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -66,7 +66,7 @@ type Writer struct { withBreadcrumbs bool } -// addBreadcrumb adds event as a breadcrumb +// addBreadcrumb adds event as a breadcrumb. func (w *Writer) addBreadcrumb(event *sentry.Event) { if !w.withBreadcrumbs { return From 6fa0f48bf6c5cceb0857f808feee28d4b178f8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Thu, 11 Jul 2024 01:01:17 +0200 Subject: [PATCH 05/31] add tests --- zerolog/zerolog.go | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index 2d311dec6..020fadd29 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" "io" - "net/http" "time" "unsafe" @@ -86,12 +85,12 @@ func (w *Writer) addBreadcrumb(event *sentry.Event) { func (w *Writer) Write(data []byte) (n int, err error) { n = len(data) - lvl, err := w.parseLogLevel(data) + lvl, err := parseLogLevel(data) if err != nil { return n, nil } - event, ok := w.parseLogEvent(data) + event, ok := parseLogEvent(data) if !ok { return } @@ -115,11 +114,11 @@ func (w *Writer) Write(data []byte) (n int, err error) { return } -// implements zerolog.LevelWriter +// implements zerolog.LevelWriter. func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) { n = len(p) - event, ok := w.parseLogEvent(p) + event, ok := parseLogEvent(p) if !ok { return } @@ -151,8 +150,7 @@ func (w *Writer) Close() error { return nil } -// parses the log level from the encoded log -func (w *Writer) parseLogLevel(data []byte) (zerolog.Level, error) { +func parseLogLevel(data []byte) (zerolog.Level, error) { level, err := jsonparser.GetUnsafeString(data, zerolog.LevelFieldName) if err != nil { return zerolog.Disabled, nil @@ -163,9 +161,8 @@ func (w *Writer) parseLogLevel(data []byte) (zerolog.Level, error) { const logger = "zerolog" -// parses the event except the log level -func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) { - +// parses the event except the log level. +func parseLogEvent(data []byte) (*sentry.Event, bool) { event := sentry.Event{ Timestamp: now(), Logger: logger, @@ -185,14 +182,6 @@ func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) { }), }) case zerolog.LevelFieldName, zerolog.TimestampFieldName: - case FieldRequest: - var req *http.Request - err := json.Unmarshal(value, &req) - if err != nil { - event.Extra[k] = bytesToStrUnsafe(value) - } else { - event.Request = sentry.NewRequest(req) - } case FieldUser: var user sentry.User err := json.Unmarshal(value, &user) From 1493be2dca4ba700ec3ed484d4ee8205e2f00736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Thu, 11 Jul 2024 01:01:27 +0200 Subject: [PATCH 06/31] add tests --- zerolog/zerolog_test.go | 241 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 zerolog/zerolog_test.go diff --git a/zerolog/zerolog_test.go b/zerolog/zerolog_test.go new file mode 100644 index 000000000..6f65f633c --- /dev/null +++ b/zerolog/zerolog_test.go @@ -0,0 +1,241 @@ +package sentryzerolog + +import ( + "errors" + "io" + "testing" + "time" + + "github.com/getsentry/sentry-go" + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// A good portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer_test.go + +var logEventJSON = []byte(`{"level":"error","requestId":"bee07485-2485-4f64-99e1-d10165884ca7","error":"dial timeout","time":"2020-06-25T17:19:00+03:00","message":"test message"}`) + +func TestParseLogEvent(t *testing.T) { + ts := time.Now() + + now = func() time.Time { return ts } + + _, err := New(Config{}) + require.Nil(t, err) + + ev, ok := parseLogEvent(logEventJSON) + require.True(t, ok) + zLevel, err := parseLogLevel(logEventJSON) + assert.Nil(t, err) + ev.Level = levels[zLevel] + + assert.Equal(t, ts, ev.Timestamp) + assert.Equal(t, sentry.LevelError, ev.Level) + assert.Equal(t, "zerolog", ev.Logger) + assert.Equal(t, "test message", ev.Message) + + require.Len(t, ev.Exception, 1) + assert.Equal(t, "dial timeout", ev.Exception[0].Value) + + require.Len(t, ev.Extra, 1) + assert.Equal(t, "bee07485-2485-4f64-99e1-d10165884ca7", ev.Extra["requestId"]) +} + +func TestParseLogLevel(t *testing.T) { + _, err := New(Config{}) + require.Nil(t, err) + + level, err := parseLogLevel(logEventJSON) + require.Nil(t, err) + assert.Equal(t, zerolog.ErrorLevel, level) +} + +func TestWrite(t *testing.T) { + var beforeSendCalled bool + cfg := Config{ + ClientOptions: sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + assert.Equal(t, sentry.LevelError, event.Level) + assert.Equal(t, "test message", event.Message) + require.Len(t, event.Exception, 1) + assert.Equal(t, "dial timeout", event.Exception[0].Value) + assert.True(t, time.Since(event.Timestamp).Minutes() < 1) + assert.Equal(t, "bee07485-2485-4f64-99e1-d10165884ca7", event.Extra["requestId"]) + beforeSendCalled = true + return event + }, + }, + } + writer, err := New(cfg) + require.Nil(t, err) + + var zerologError error + zerolog.ErrorHandler = func(err error) { + zerologError = err + } + + // use io.MultiWriter to enforce using the Write() method + log := zerolog.New(io.MultiWriter(writer)).With().Timestamp(). + Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Logger() + log.Err(errors.New("dial timeout")). + Msg("test message") + + require.Nil(t, zerologError) + require.True(t, beforeSendCalled) +} + +func TestWrite_TraceDoesNotPanic(t *testing.T) { + var beforeSendCalled bool + cfg := Config{ + ClientOptions: sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + beforeSendCalled = true + return event + }, + }, + } + writer, err := New(cfg) + require.Nil(t, err) + + var zerologError error + zerolog.ErrorHandler = func(err error) { + zerologError = err + } + + // use io.MultiWriter to enforce using the Write() method + log := zerolog.New(io.MultiWriter(writer)).With().Timestamp(). + Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Logger() + log.Trace().Msg("test message") + + require.Nil(t, zerologError) + require.False(t, beforeSendCalled) +} + +func TestWriteLevel(t *testing.T) { + var beforeSendCalled bool + cfg := Config{ + ClientOptions: sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + assert.Equal(t, sentry.LevelError, event.Level) + assert.Equal(t, "test message", event.Message) + require.Len(t, event.Exception, 1) + assert.Equal(t, "dial timeout", event.Exception[0].Value) + assert.True(t, time.Since(event.Timestamp).Minutes() < 1) + assert.Equal(t, "bee07485-2485-4f64-99e1-d10165884ca7", event.Extra["requestId"]) + assert.Equal(t, "GET", event.Request.Method) + beforeSendCalled = true + return event + }, + }, + } + writer, err := New(cfg) + require.Nil(t, err) + + var zerologError error + zerolog.ErrorHandler = func(err error) { zerologError = err } + + log := zerolog.New(writer).With().Timestamp(). + Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Logger() + log.Err(errors.New("dial timeout")). + Msg("test message") + + require.Nil(t, zerologError) + require.True(t, beforeSendCalled) +} + +func TestWrite_Disabled(t *testing.T) { + var beforeSendCalled bool + cfg := Config{ + ClientOptions: sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + beforeSendCalled = true + return event + }, + }, + Options: Options{ + Levels: []zerolog.Level{zerolog.FatalLevel}, + }, + } + + writer, err := New(cfg) + + require.Nil(t, err) + + var zerologError error + zerolog.ErrorHandler = func(err error) { + zerologError = err + } + + // use io.MultiWriter to enforce using the Write() method + log := zerolog.New(io.MultiWriter(writer)).With().Timestamp(). + Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Logger() + log.Err(errors.New("dial timeout")). + Msg("test message") + + require.Nil(t, zerologError) + require.False(t, beforeSendCalled) +} + +func TestWriteLevel_Disabled(t *testing.T) { + var beforeSendCalled bool + cfg := Config{ + ClientOptions: sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + beforeSendCalled = true + return event + }, + }, + Options: Options{ + Levels: []zerolog.Level{zerolog.FatalLevel}, + }, + } + writer, err := New(cfg) + require.Nil(t, err) + + var zerologError error + zerolog.ErrorHandler = func(err error) { + zerologError = err + } + + log := zerolog.New(writer).With().Timestamp(). + Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Logger() + log.Err(errors.New("dial timeout")). + Msg("test message") + + require.Nil(t, zerologError) + require.False(t, beforeSendCalled) +} + +func BenchmarkParseLogEvent(b *testing.B) { + for i := 0; i < b.N; i++ { + parseLogEvent(logEventJSON) + } +} + +func BenchmarkWriteLogEvent(b *testing.B) { + w, err := New(Config{}) + if err != nil { + b.Errorf("failed to create writer: %v", err) + } + + for i := 0; i < b.N; i++ { + _, _ = w.Write(logEventJSON) + } +} + +func BenchmarkWriteLogLevelEvent(b *testing.B) { + w, err := New(Config{}) + if err != nil { + b.Errorf("failed to create writer: %v", err) + } + + for i := 0; i < b.N; i++ { + _, _ = w.WriteLevel(zerolog.ErrorLevel, logEventJSON) + } +} From 95972febe036c69c6a470ca427fb02758e25894c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Thu, 11 Jul 2024 01:03:58 +0200 Subject: [PATCH 07/31] remove comment --- zerolog/zerolog.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index 020fadd29..a5600c305 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -1,4 +1,3 @@ -// Package sentryzerolog provides a simple Zerolog hook for Sentry. package sentryzerolog import ( @@ -38,8 +37,6 @@ const sdkIdentifier = "sentry.go.zerolog" // Sentry understands. If they are found in the log fields, and the value is of // the expected datatype, it will be converted from a generic field, into Sentry // metadata. -// -// These keys may be overridden by calling SetKey on the hook object. const ( // FieldRequest holds an *http.Request. FieldRequest = "request" @@ -157,6 +154,7 @@ func parseLogLevel(data []byte) (zerolog.Level, error) { } return zerolog.ParseLevel(level) + zerolog.Hook } const logger = "zerolog" From 564854ed4252a946205b1053d0a7ef22232278f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sat, 20 Jul 2024 14:39:39 +0200 Subject: [PATCH 08/31] add example --- _examples/zerolog/main.go | 47 +++++++++ zerolog/zerolog.go | 211 ++++++++++++++++++++------------------ 2 files changed, 159 insertions(+), 99 deletions(-) create mode 100644 _examples/zerolog/main.go diff --git a/_examples/zerolog/main.go b/_examples/zerolog/main.go new file mode 100644 index 000000000..1219b363b --- /dev/null +++ b/_examples/zerolog/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "github.com/getsentry/sentry-go" + sentryzerolog "github.com/getsentry/sentry-go/zerolog" + "github.com/rs/zerolog" + "os" + "time" +) + +func main() { + w, err := sentryzerolog.New(sentryzerolog.Config{ + Options: sentryzerolog.Options{ + Levels: []zerolog.Level{ + zerolog.DebugLevel, + zerolog.ErrorLevel, + zerolog.FatalLevel, + zerolog.PanicLevel, + }, + WithBreadcrumbs: true, + FlushTimeout: 5 * time.Second, + }, + ClientOptions: sentry.ClientOptions{ + Dsn: "", + Environment: "development", + Release: "1.0", + }, + }) + + if err != nil { + panic(err) + } + + defer func() { + err = w.Close() + if err != nil { + panic(err) + } + }() + + m := zerolog.MultiLevelWriter(os.Stdout, w) + logger := zerolog.New(m).With().Timestamp().Logger() + + logger.Debug().Msg("Application has started") + logger.Error().Msg("oh no!") + logger.Fatal().Msg("can't continue...") +} diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index a5600c305..f9792ad7a 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -3,32 +3,35 @@ package sentryzerolog import ( "encoding/json" "errors" + "fmt" "io" "time" - "unsafe" "github.com/buger/jsonparser" sentry "github.com/getsentry/sentry-go" "github.com/rs/zerolog" ) -// A good portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer.go - -var ErrFlushTimeout = errors.New("sentryzerolog flush timeout") - -var levels = map[zerolog.Level]sentry.Level{ - zerolog.TraceLevel: sentry.LevelDebug, - zerolog.DebugLevel: sentry.LevelDebug, - zerolog.InfoLevel: sentry.LevelInfo, - zerolog.WarnLevel: sentry.LevelWarning, - zerolog.ErrorLevel: sentry.LevelError, - zerolog.FatalLevel: sentry.LevelFatal, - zerolog.PanicLevel: sentry.LevelFatal, -} +var ( + // ErrFlushTimeout is returned when the flush operation times out. + ErrFlushTimeout = errors.New("sentryzerolog flush timeout") + + // levels maps zerolog levels to sentry levels. + levels = map[zerolog.Level]sentry.Level{ + zerolog.TraceLevel: sentry.LevelDebug, + zerolog.DebugLevel: sentry.LevelDebug, + zerolog.InfoLevel: sentry.LevelInfo, + zerolog.WarnLevel: sentry.LevelWarning, + zerolog.ErrorLevel: sentry.LevelError, + zerolog.FatalLevel: sentry.LevelFatal, + zerolog.PanicLevel: sentry.LevelFatal, + } -var _ = io.WriteCloser(new(Writer)) + // Ensure that the Writer implements the io.WriteCloser interface. + _ = io.WriteCloser(new(Writer)) -var now = time.Now + now = time.Now +) // The identifier of the Zerolog SDK. const sdkIdentifier = "sentry.go.zerolog" @@ -53,10 +56,81 @@ const ( FieldMaxProcs = "go_maxprocs" ) +// A good portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer.go + +type Config struct { + sentry.ClientOptions + Options +} + +type Options struct { + Levels []zerolog.Level + WithBreadcrumbs bool + FlushTimeout time.Duration +} + +func (o *Options) SetDefaults() { + if len(o.Levels) == 0 { + o.Levels = []zerolog.Level{ + zerolog.ErrorLevel, + zerolog.FatalLevel, + zerolog.PanicLevel, + } + } + + if o.FlushTimeout == 0 { + o.FlushTimeout = 3 * time.Second + } +} + +// New creates writer with provided DSN and options. +func New(cfg Config) (*Writer, error) { + client, err := sentry.NewClient(cfg.ClientOptions) + if err != nil { + return nil, err + } + + client.SetSDKIdentifier(sdkIdentifier) + + cfg.Options.SetDefaults() + + levels := make(map[zerolog.Level]struct{}, len(cfg.Levels)) + for _, lvl := range cfg.Levels { + levels[lvl] = struct{}{} + } + + return &Writer{ + hub: sentry.NewHub(client, sentry.NewScope()), + levels: levels, + flushTimeout: cfg.FlushTimeout, + withBreadcrumbs: cfg.WithBreadcrumbs, + }, nil +} + +// NewWithHub creates a writer using an existing sentry Hub and options. +func NewWithHub(hub *sentry.Hub, opts Options) (*Writer, error) { + if hub == nil { + return nil, errors.New("hub cannot be nil") + } + + opts.SetDefaults() + + levels := make(map[zerolog.Level]struct{}, len(opts.Levels)) + for _, lvl := range opts.Levels { + levels[lvl] = struct{}{} + } + + return &Writer{ + hub: hub, + levels: levels, + flushTimeout: opts.FlushTimeout, + withBreadcrumbs: opts.WithBreadcrumbs, + }, nil +} + // Writer is a sentry events writer with std io.Writer interface. type Writer struct { - hub *sentry.Hub - + hub *sentry.Hub levels map[zerolog.Level]struct{} flushTimeout time.Duration withBreadcrumbs bool @@ -68,9 +142,16 @@ func (w *Writer) addBreadcrumb(event *sentry.Event) { return } + breadcrumbType := "default" + switch event.Level { + case sentry.LevelFatal, sentry.LevelError: + breadcrumbType = "error" + } + category, _ := event.Extra["category"].(string) w.hub.AddBreadcrumb(&sentry.Breadcrumb{ + Type: breadcrumbType, Category: category, Message: event.Message, Level: event.Level, @@ -80,19 +161,24 @@ func (w *Writer) addBreadcrumb(event *sentry.Event) { // Write handles zerolog's json and sends events to sentry. func (w *Writer) Write(data []byte) (n int, err error) { + fmt.Println("data", string(data)) + n = len(data) lvl, err := parseLogLevel(data) if err != nil { + fmt.Println("parseLogLevel", err) return n, nil } event, ok := parseLogEvent(data) if !ok { + fmt.Println("parseLogEvent", ok) return } event.Level, ok = levels[lvl] if !ok { + fmt.Println("levels", ok) return } @@ -103,6 +189,7 @@ func (w *Writer) Write(data []byte) (n int, err error) { } w.hub.CaptureEvent(event) + fmt.Println("event", event) // should flush before os.Exit if event.Level == sentry.LevelFatal { w.hub.Flush(w.flushTimeout) @@ -119,6 +206,7 @@ func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) { if !ok { return } + event.Level, ok = levels[level] if !ok { return @@ -154,7 +242,6 @@ func parseLogLevel(data []byte) (zerolog.Level, error) { } return zerolog.ParseLevel(level) - zerolog.Hook } const logger = "zerolog" @@ -171,10 +258,10 @@ func parseLogEvent(data []byte) (*sentry.Event, bool) { k := string(key) switch k { case zerolog.MessageFieldName: - event.Message = bytesToStrUnsafe(value) + event.Message = string(value) case zerolog.ErrorFieldName: event.Exception = append(event.Exception, sentry.Exception{ - Value: bytesToStrUnsafe(value), + Value: string(value), Stacktrace: sentry.NewStacktrace(sentry.EventOptions{ SkipFrames: 0, }), @@ -184,99 +271,25 @@ func parseLogEvent(data []byte) (*sentry.Event, bool) { var user sentry.User err := json.Unmarshal(value, &user) if err != nil { - event.Extra[k] = bytesToStrUnsafe(value) + event.Extra[k] = string(value) } else { event.User = user } case FieldTransaction: - event.Transaction = bytesToStrUnsafe(value) + event.Transaction = string(value) case FieldFingerprint: var fp []string err := json.Unmarshal(value, &fp) if err != nil { - event.Extra[k] = bytesToStrUnsafe(value) + event.Extra[k] = string(value) } else { event.Fingerprint = fp } case FieldGoVersion, FieldMaxProcs: default: - event.Extra[k] = bytesToStrUnsafe(value) + event.Extra[k] = string(value) } return nil }) return &event, err == nil } - -func bytesToStrUnsafe(data []byte) string { - return *(*string)(unsafe.Pointer(&data)) -} - -type Config struct { - sentry.ClientOptions - Options -} - -type Options struct { - Levels []zerolog.Level - WithBreadcrumbs bool - FlushTimeout time.Duration -} - -func (o *Options) SetDefaults() { - if len(o.Levels) == 0 { - o.Levels = []zerolog.Level{ - zerolog.ErrorLevel, - zerolog.FatalLevel, - zerolog.PanicLevel, - } - } - - if o.FlushTimeout == 0 { - o.FlushTimeout = 3 * time.Second - } -} - -// New creates writer with provided DSN and options. -func New(cfg Config) (*Writer, error) { - client, err := sentry.NewClient(cfg.ClientOptions) - if err != nil { - return nil, err - } - - client.SetSDKIdentifier(sdkIdentifier) - - cfg.Options.SetDefaults() - - levels := make(map[zerolog.Level]struct{}, len(cfg.Levels)) - for _, lvl := range cfg.Levels { - levels[lvl] = struct{}{} - } - - return &Writer{ - hub: sentry.NewHub(client, sentry.NewScope()), - levels: levels, - flushTimeout: cfg.FlushTimeout, - withBreadcrumbs: cfg.WithBreadcrumbs, - }, nil -} - -// NewWithHub creates a writer using an existing sentry Hub and options. -func NewWithHub(hub *sentry.Hub, opts Options) (*Writer, error) { - if hub == nil { - return nil, errors.New("hub cannot be nil") - } - - opts.SetDefaults() - - levels := make(map[zerolog.Level]struct{}, len(opts.Levels)) - for _, lvl := range opts.Levels { - levels[lvl] = struct{}{} - } - - return &Writer{ - hub: hub, - levels: levels, - flushTimeout: opts.FlushTimeout, - withBreadcrumbs: opts.WithBreadcrumbs, - }, nil -} From a7527a907b4537352488e7b2c0ded6402b3c26c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sat, 20 Jul 2024 16:25:06 +0200 Subject: [PATCH 09/31] update changelog --- CHANGELOG.md | 1 + _examples/zerolog/main.go | 12 +++++++----- zerolog/zerolog.go | 6 ------ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 987d015bc..3ba8d8580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Add trace origin to span data ([#849](https://github.com/getsentry/sentry-go/pull/849)) - Add ability to skip frames in stacktrace ([#852](https://github.com/getsentry/sentry-go/pull/852)) +- Add Zerolog integration ([#857](https://github.com/getsentry/sentry-go/pull/857)) ## 0.28.1 diff --git a/_examples/zerolog/main.go b/_examples/zerolog/main.go index 1219b363b..c91dbce3d 100644 --- a/_examples/zerolog/main.go +++ b/_examples/zerolog/main.go @@ -21,9 +21,11 @@ func main() { FlushTimeout: 5 * time.Second, }, ClientOptions: sentry.ClientOptions{ - Dsn: "", - Environment: "development", - Release: "1.0", + Dsn: "", + Environment: "development", + Release: "1.0", + Debug: true, + AttachStacktrace: true, }, }) @@ -42,6 +44,6 @@ func main() { logger := zerolog.New(m).With().Timestamp().Logger() logger.Debug().Msg("Application has started") - logger.Error().Msg("oh no!") - logger.Fatal().Msg("can't continue...") + logger.Error().Msg("Oh no!") + logger.Fatal().Msg("Can't continue...") } diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index f9792ad7a..9196bfd53 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -3,7 +3,6 @@ package sentryzerolog import ( "encoding/json" "errors" - "fmt" "io" "time" @@ -161,24 +160,20 @@ func (w *Writer) addBreadcrumb(event *sentry.Event) { // Write handles zerolog's json and sends events to sentry. func (w *Writer) Write(data []byte) (n int, err error) { - fmt.Println("data", string(data)) n = len(data) lvl, err := parseLogLevel(data) if err != nil { - fmt.Println("parseLogLevel", err) return n, nil } event, ok := parseLogEvent(data) if !ok { - fmt.Println("parseLogEvent", ok) return } event.Level, ok = levels[lvl] if !ok { - fmt.Println("levels", ok) return } @@ -189,7 +184,6 @@ func (w *Writer) Write(data []byte) (n int, err error) { } w.hub.CaptureEvent(event) - fmt.Println("event", event) // should flush before os.Exit if event.Level == sentry.LevelFatal { w.hub.Flush(w.flushTimeout) From 7f0ffdeda5b57d23d1df72c78f1c26f9980ea174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sat, 20 Jul 2024 16:26:22 +0200 Subject: [PATCH 10/31] fix linter --- zerolog/zerolog.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index 9196bfd53..dceb1ffd5 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -160,7 +160,6 @@ func (w *Writer) addBreadcrumb(event *sentry.Event) { // Write handles zerolog's json and sends events to sentry. func (w *Writer) Write(data []byte) (n int, err error) { - n = len(data) lvl, err := parseLogLevel(data) @@ -192,7 +191,6 @@ func (w *Writer) Write(data []byte) (n int, err error) { return } -// implements zerolog.LevelWriter. func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) { n = len(p) From ccfba2f9b97a4749aa37e8c9b948c0afef873e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sat, 20 Jul 2024 16:30:02 +0200 Subject: [PATCH 11/31] restructure --- zerolog/zerolog.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zerolog/zerolog.go b/zerolog/zerolog.go index dceb1ffd5..ee3478f5a 100644 --- a/zerolog/zerolog.go +++ b/zerolog/zerolog.go @@ -53,6 +53,7 @@ const ( // These fields are simply omitted, as they are duplicated by the Sentry SDK. FieldGoVersion = "go_version" FieldMaxProcs = "go_maxprocs" + logger = "zerolog" ) // A good portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer.go @@ -236,9 +237,6 @@ func parseLogLevel(data []byte) (zerolog.Level, error) { return zerolog.ParseLevel(level) } -const logger = "zerolog" - -// parses the event except the log level. func parseLogEvent(data []byte) (*sentry.Event, bool) { event := sentry.Event{ Timestamp: now(), From d7b9af1cd0446e319db096eeb401b870fc3f293b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sat, 20 Jul 2024 16:39:36 +0200 Subject: [PATCH 12/31] fix tests --- zerolog/{zerolog.go => sentryzerolog.go} | 3 +++ zerolog/{zerolog_test.go => sentryzerolog_test.go} | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) rename zerolog/{zerolog.go => sentryzerolog.go} (99%) rename zerolog/{zerolog_test.go => sentryzerolog_test.go} (99%) diff --git a/zerolog/zerolog.go b/zerolog/sentryzerolog.go similarity index 99% rename from zerolog/zerolog.go rename to zerolog/sentryzerolog.go index ee3478f5a..26a102480 100644 --- a/zerolog/zerolog.go +++ b/zerolog/sentryzerolog.go @@ -3,6 +3,7 @@ package sentryzerolog import ( "encoding/json" "errors" + "fmt" "io" "time" @@ -265,6 +266,8 @@ func parseLogEvent(data []byte) (*sentry.Event, bool) { } else { event.User = user } + case FieldRequest: + fmt.Println("request") case FieldTransaction: event.Transaction = string(value) case FieldFingerprint: diff --git a/zerolog/zerolog_test.go b/zerolog/sentryzerolog_test.go similarity index 99% rename from zerolog/zerolog_test.go rename to zerolog/sentryzerolog_test.go index 6f65f633c..3237ce205 100644 --- a/zerolog/zerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -125,7 +125,6 @@ func TestWriteLevel(t *testing.T) { assert.Equal(t, "dial timeout", event.Exception[0].Value) assert.True(t, time.Since(event.Timestamp).Minutes() < 1) assert.Equal(t, "bee07485-2485-4f64-99e1-d10165884ca7", event.Extra["requestId"]) - assert.Equal(t, "GET", event.Request.Method) beforeSendCalled = true return event }, From 0a79ba0f0186a7f79b134cb746903bd5cac75af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sun, 21 Jul 2024 11:41:18 +0200 Subject: [PATCH 13/31] improve test coverage --- zerolog/sentryzerolog.go | 3 --- zerolog/sentryzerolog_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/zerolog/sentryzerolog.go b/zerolog/sentryzerolog.go index 26a102480..ee3478f5a 100644 --- a/zerolog/sentryzerolog.go +++ b/zerolog/sentryzerolog.go @@ -3,7 +3,6 @@ package sentryzerolog import ( "encoding/json" "errors" - "fmt" "io" "time" @@ -266,8 +265,6 @@ func parseLogEvent(data []byte) (*sentry.Event, bool) { } else { event.User = user } - case FieldRequest: - fmt.Println("request") case FieldTransaction: event.Transaction = string(value) case FieldFingerprint: diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index 3237ce205..17fd4dbb0 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -42,6 +42,24 @@ func TestParseLogEvent(t *testing.T) { assert.Equal(t, "bee07485-2485-4f64-99e1-d10165884ca7", ev.Extra["requestId"]) } +func TestFailedClientCreation(t *testing.T) { + _, err := New(Config{ClientOptions: sentry.ClientOptions{Dsn: "invalid"}}) + require.NotNil(t, err) +} + +func TestNewWithHub(t *testing.T) { + hub := sentry.CurrentHub() + require.NotNil(t, hub) + + _, err := NewWithHub(hub, Options{ + Levels: []zerolog.Level{zerolog.ErrorLevel}, + }) + require.Nil(t, err) + + _, err = NewWithHub(nil, Options{}) + require.NotNil(t, err) +} + func TestParseLogLevel(t *testing.T) { _, err := New(Config{}) require.Nil(t, err) @@ -66,6 +84,9 @@ func TestWrite(t *testing.T) { return event }, }, + Options: Options{ + WithBreadcrumbs: true, + }, } writer, err := New(cfg) require.Nil(t, err) @@ -78,6 +99,8 @@ func TestWrite(t *testing.T) { // use io.MultiWriter to enforce using the Write() method log := zerolog.New(io.MultiWriter(writer)).With().Timestamp(). Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Interface("user", sentry.User{ID: "1", Email: "testuser@sentry.io"}). + Strs("fingerprint", []string{"test"}). Logger() log.Err(errors.New("dial timeout")). Msg("test message") @@ -86,6 +109,15 @@ func TestWrite(t *testing.T) { require.True(t, beforeSendCalled) } +func TestClose(t *testing.T) { + cfg := Config{} + writer, err := New(cfg) + require.Nil(t, err) + + err = writer.Close() + require.Nil(t, err) +} + func TestWrite_TraceDoesNotPanic(t *testing.T) { var beforeSendCalled bool cfg := Config{ @@ -107,6 +139,9 @@ func TestWrite_TraceDoesNotPanic(t *testing.T) { // use io.MultiWriter to enforce using the Write() method log := zerolog.New(io.MultiWriter(writer)).With().Timestamp(). Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Str("user", "1"). + Str("transaction", "test"). + Str("fingerprint", "test"). Logger() log.Trace().Msg("test message") From d1c086121119adb694d85a30c7b2d6215ec15f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sun, 21 Jul 2024 11:48:11 +0200 Subject: [PATCH 14/31] more tests --- zerolog/sentryzerolog_test.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index 17fd4dbb0..02d1a4d34 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -127,6 +127,9 @@ func TestWrite_TraceDoesNotPanic(t *testing.T) { return event }, }, + Options: Options{ + WithBreadcrumbs: true, + }, } writer, err := New(cfg) require.Nil(t, err) @@ -164,6 +167,9 @@ func TestWriteLevel(t *testing.T) { return event }, }, + Options: Options{ + WithBreadcrumbs: true, + }, } writer, err := New(cfg) require.Nil(t, err) @@ -191,7 +197,8 @@ func TestWrite_Disabled(t *testing.T) { }, }, Options: Options{ - Levels: []zerolog.Level{zerolog.FatalLevel}, + Levels: []zerolog.Level{zerolog.FatalLevel}, + WithBreadcrumbs: true, }, } @@ -225,7 +232,8 @@ func TestWriteLevel_Disabled(t *testing.T) { }, }, Options: Options{ - Levels: []zerolog.Level{zerolog.FatalLevel}, + Levels: []zerolog.Level{zerolog.FatalLevel}, + WithBreadcrumbs: true, }, } writer, err := New(cfg) From 198dac6dcb96fd2ea5875308417be7663c8d34d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 31 Jul 2024 17:58:10 +0200 Subject: [PATCH 15/31] more tests --- zerolog/sentryzerolog_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index 02d1a4d34..e3a669ecc 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -187,6 +187,33 @@ func TestWriteLevel(t *testing.T) { require.True(t, beforeSendCalled) } +func TestWriteInvalidLevel(t *testing.T) { + cfg := Config{ + ClientOptions: sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + assert.Equal(t, sentry.LevelError, event.Level) + assert.Equal(t, "test message", event.Message) + require.Len(t, event.Exception, 1) + assert.Equal(t, "dial timeout", event.Exception[0].Value) + assert.True(t, time.Since(event.Timestamp).Minutes() < 1) + assert.Equal(t, "bee07485-2485-4f64-99e1-d10165884ca7", event.Extra["requestId"]) + return event + }, + }, + Options: Options{ + WithBreadcrumbs: true, + }, + } + writer, err := New(cfg) + require.Nil(t, err) + + log := zerolog.New(writer).With().Timestamp(). + Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Logger() + log.Log().Str("level", "invalid").Msg("test message") + +} + func TestWrite_Disabled(t *testing.T) { var beforeSendCalled bool cfg := Config{ From 9022dcf0b5bb5278a5cf76455dddd5c6d028388b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 31 Jul 2024 18:06:57 +0200 Subject: [PATCH 16/31] linter fix --- zerolog/sentryzerolog_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index e3a669ecc..8e91e4178 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -211,7 +211,6 @@ func TestWriteInvalidLevel(t *testing.T) { Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). Logger() log.Log().Str("level", "invalid").Msg("test message") - } func TestWrite_Disabled(t *testing.T) { From 1c45a3213565ead3aea561b81e2ca9447ef3f16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sun, 4 Aug 2024 12:21:41 +0200 Subject: [PATCH 17/31] add comment for options --- zerolog/sentryzerolog.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zerolog/sentryzerolog.go b/zerolog/sentryzerolog.go index ee3478f5a..9a977ebab 100644 --- a/zerolog/sentryzerolog.go +++ b/zerolog/sentryzerolog.go @@ -64,9 +64,12 @@ type Config struct { } type Options struct { - Levels []zerolog.Level + // The log levels to send to Sentry. Default levels are Error, Fatal, and Panic. + Levels []zerolog.Level + // Enable to add log entries as breadcrumbs in Sentry. WithBreadcrumbs bool - FlushTimeout time.Duration + // The timeout duration for flushing events to Sentry. + FlushTimeout time.Duration } func (o *Options) SetDefaults() { From 47621538ef17224dffe20f58c620a3063179525a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sun, 4 Aug 2024 16:16:48 +0200 Subject: [PATCH 18/31] update options comments --- zerolog/sentryzerolog.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/zerolog/sentryzerolog.go b/zerolog/sentryzerolog.go index 9a977ebab..83aed86c4 100644 --- a/zerolog/sentryzerolog.go +++ b/zerolog/sentryzerolog.go @@ -53,7 +53,9 @@ const ( // These fields are simply omitted, as they are duplicated by the Sentry SDK. FieldGoVersion = "go_version" FieldMaxProcs = "go_maxprocs" - logger = "zerolog" + + // Name of the logger used by the Sentry SDK. + logger = "zerolog" ) // A good portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer.go @@ -64,11 +66,20 @@ type Config struct { } type Options struct { - // The log levels to send to Sentry. Default levels are Error, Fatal, and Panic. + // Levels specifies the log levels that will trigger event sending to Sentry. + // Only log messages at these levels will be sent. By default, the levels are + // Error, Fatal, and Panic, which capture critical issues. Levels []zerolog.Level - // Enable to add log entries as breadcrumbs in Sentry. + + // WithBreadcrumbs, when enabled, adds log entries as breadcrumbs in Sentry. + // Breadcrumbs provide a trail of events leading up to an error, which can + // be invaluable for understanding the context of issues. WithBreadcrumbs bool - // The timeout duration for flushing events to Sentry. + + // FlushTimeout sets the maximum duration allowed for flushing events to Sentry. + // This is the time limit within which all pending events must be sent to Sentry + // before the application exits. A typical use is ensuring all logs are sent before + // application shutdown. The default timeout is usually 3 seconds. FlushTimeout time.Duration } From fb1076337d6d42ddbaa64772d602e5e19ffb17e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Sun, 4 Aug 2024 16:16:57 +0200 Subject: [PATCH 19/31] update options comments --- zerolog/sentryzerolog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zerolog/sentryzerolog.go b/zerolog/sentryzerolog.go index 83aed86c4..c32a3db5a 100644 --- a/zerolog/sentryzerolog.go +++ b/zerolog/sentryzerolog.go @@ -68,7 +68,7 @@ type Config struct { type Options struct { // Levels specifies the log levels that will trigger event sending to Sentry. // Only log messages at these levels will be sent. By default, the levels are - // Error, Fatal, and Panic, which capture critical issues. + // Error, Fatal, and Panic. Levels []zerolog.Level // WithBreadcrumbs, when enabled, adds log entries as breadcrumbs in Sentry. From 6a657a117863b0d2d0321393823883682466ad64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Tue, 15 Oct 2024 18:26:03 +0200 Subject: [PATCH 20/31] fix tests --- zerolog/sentryzerolog_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index 8e91e4178..2f7f838fb 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -28,7 +28,7 @@ func TestParseLogEvent(t *testing.T) { require.True(t, ok) zLevel, err := parseLogLevel(logEventJSON) assert.Nil(t, err) - ev.Level = levels[zLevel] + ev.Level = levelsMapping[zLevel] assert.Equal(t, ts, ev.Timestamp) assert.Equal(t, sentry.LevelError, ev.Level) From 39635149b64d89b3c106370e2fd70472046bafd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Tue, 15 Oct 2024 18:26:09 +0200 Subject: [PATCH 21/31] fix tests --- zerolog/sentryzerolog_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index 2f7f838fb..f5e4cd177 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" ) -// A good portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer_test.go +// A large portion of this implementation has been taken from https://github.com/archdx/zerolog-sentry/blob/master/writer_test.go var logEventJSON = []byte(`{"level":"error","requestId":"bee07485-2485-4f64-99e1-d10165884ca7","error":"dial timeout","time":"2020-06-25T17:19:00+03:00","message":"test message"}`) From 3706e4527a185b4deb611ae6320fd4df7f7f0266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Tue, 15 Oct 2024 18:31:37 +0200 Subject: [PATCH 22/31] linter fix --- zerolog/sentryzerolog.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/zerolog/sentryzerolog.go b/zerolog/sentryzerolog.go index 1d292541f..fca846b52 100644 --- a/zerolog/sentryzerolog.go +++ b/zerolog/sentryzerolog.go @@ -174,8 +174,8 @@ func (w *Writer) addBreadcrumb(event *sentry.Event) { } // Write handles zerolog's json and sends events to sentry. -func (w *Writer) Write(data []byte) (n int, err error) { - n = len(data) +func (w *Writer) Write(data []byte) (int, error) { + n := len(data) lvl, err := parseLogLevel(data) if err != nil { @@ -184,24 +184,24 @@ func (w *Writer) Write(data []byte) (n int, err error) { event, ok := parseLogEvent(data) if !ok { - return + return n, nil } if _, enabled := w.levels[lvl]; !enabled { // if the level is not enabled, add event as a breadcrumb w.addBreadcrumb(event) - return + return n, nil } event.Level, ok = levelsMapping[lvl] if !ok { - return + return n, nil } if _, enabled := w.levels[lvl]; !enabled { // if the level is not enabled, add event as a breadcrumb w.addBreadcrumb(event) - return + return n, nil } w.hub.CaptureEvent(event) @@ -210,26 +210,26 @@ func (w *Writer) Write(data []byte) (n int, err error) { w.hub.Flush(w.flushTimeout) } - return + return n, nil } -func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) { - n = len(p) +func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (int, error) { + n := len(p) event, ok := parseLogEvent(p) if !ok { - return + return n, nil } event.Level, ok = levelsMapping[level] if !ok { - return + return n, nil } if _, enabled := w.levels[level]; !enabled { // if the level is not enabled, add event as a breadcrumb w.addBreadcrumb(event) - return + return n, nil } w.hub.CaptureEvent(event) @@ -237,7 +237,8 @@ func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) { if event.Level == sentry.LevelFatal { w.hub.Flush(w.flushTimeout) } - return + + return n, nil } // Close forces client to flush all pending events. From 8f6af7ecd6f3445dea5864085383e11430ade526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Fri, 25 Oct 2024 17:15:29 +0200 Subject: [PATCH 23/31] add more tests --- zerolog/sentryzerolog_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index f5e4cd177..ea0241596 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -128,7 +128,7 @@ func TestWrite_TraceDoesNotPanic(t *testing.T) { }, }, Options: Options{ - WithBreadcrumbs: true, + WithBreadcrumbs: false, }, } writer, err := New(cfg) @@ -272,6 +272,7 @@ func TestWriteLevel_Disabled(t *testing.T) { log := zerolog.New(writer).With().Timestamp(). Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Str("go_version", "1.14").Str("go_max_procs", "4"). Logger() log.Err(errors.New("dial timeout")). Msg("test message") From 5c2946fe9c0c5b818252f473c8d253626e004eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Fri, 25 Oct 2024 17:23:07 +0200 Subject: [PATCH 24/31] add fatal --- zerolog/sentryzerolog_test.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/zerolog/sentryzerolog_test.go b/zerolog/sentryzerolog_test.go index ea0241596..b347f5727 100644 --- a/zerolog/sentryzerolog_test.go +++ b/zerolog/sentryzerolog_test.go @@ -281,6 +281,38 @@ func TestWriteLevel_Disabled(t *testing.T) { require.False(t, beforeSendCalled) } +func TestWriteLevelFatal(t *testing.T) { + var beforeSendCalled bool + cfg := Config{ + ClientOptions: sentry.ClientOptions{ + BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + beforeSendCalled = true + return event + }, + }, + Options: Options{ + Levels: []zerolog.Level{zerolog.FatalLevel}, + WithBreadcrumbs: true, + }, + } + writer, err := New(cfg) + require.Nil(t, err) + + var zerologError error + zerolog.ErrorHandler = func(err error) { + zerologError = err + } + + logger := zerolog.New(writer).With().Timestamp(). + Str("requestId", "bee07485-2485-4f64-99e1-d10165884ca7"). + Str("go_version", "1.14").Str("go_max_procs", "4").Str("error", "dial timeout").Str("level", "fatal").Logger() + + logger.Log().Msg("test message") + + require.Nil(t, zerologError) + require.False(t, beforeSendCalled) +} + func BenchmarkParseLogEvent(b *testing.B) { for i := 0; i < b.N; i++ { parseLogEvent(logEventJSON) From 38f9fb3ebec484e13adf42c1da99a40f5b70eef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Fri, 25 Oct 2024 17:29:32 +0200 Subject: [PATCH 25/31] remove duplicate code --- zerolog/sentryzerolog.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/zerolog/sentryzerolog.go b/zerolog/sentryzerolog.go index fca846b52..11bd2453c 100644 --- a/zerolog/sentryzerolog.go +++ b/zerolog/sentryzerolog.go @@ -187,12 +187,6 @@ func (w *Writer) Write(data []byte) (int, error) { return n, nil } - if _, enabled := w.levels[lvl]; !enabled { - // if the level is not enabled, add event as a breadcrumb - w.addBreadcrumb(event) - return n, nil - } - event.Level, ok = levelsMapping[lvl] if !ok { return n, nil From fa33c3d80b8828da08eb3fa275e29cce0db1ea59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Tue, 5 Nov 2024 14:39:40 +0100 Subject: [PATCH 26/31] make zerolog integration a module --- .craft.yml | 3 +++ go.mod | 3 --- go.sum | 9 --------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.craft.yml b/.craft.yml index 238288e45..b5a1796b5 100644 --- a/.craft.yml +++ b/.craft.yml @@ -8,6 +8,9 @@ targets: - name: github tagPrefix: otel/v tagOnly: true + - name: github + tagPrefix: zerolog/v + tagOnly: true - name: registry sdks: github:getsentry/sentry-go: diff --git a/go.mod b/go.mod index 57f0f9074..7c7a31eaa 100644 --- a/go.mod +++ b/go.mod @@ -19,8 +19,6 @@ require ( golang.org/x/text v0.14.0 ) -require github.com/buger/jsonparser v1.1.1 - require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect @@ -70,7 +68,6 @@ require ( github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/rs/zerolog v1.33.0 github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect diff --git a/go.sum b/go.sum index bce3f282c..2144722a8 100644 --- a/go.sum +++ b/go.sum @@ -16,10 +16,7 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1 github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,7 +49,6 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo= github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -117,7 +113,6 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -152,9 +147,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= @@ -259,7 +251,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From 115792f6926b19988d446d92647c42dc2028190c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Tue, 5 Nov 2024 14:39:43 +0100 Subject: [PATCH 27/31] make zerolog integration a module --- zerolog/go.mod | 20 ++++++++++++++++++++ zerolog/go.sum | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 zerolog/go.mod create mode 100644 zerolog/go.sum diff --git a/zerolog/go.mod b/zerolog/go.mod new file mode 100644 index 000000000..5d0770d00 --- /dev/null +++ b/zerolog/go.mod @@ -0,0 +1,20 @@ +module github.com/getsentry/sentry-go/zerolog + +go 1.23.2 + +require ( + github.com/buger/jsonparser v1.1.1 + github.com/getsentry/sentry-go v0.29.1 + github.com/rs/zerolog v1.33.0 + github.com/stretchr/testify v1.9.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/zerolog/go.sum b/zerolog/go.sum new file mode 100644 index 000000000..667206108 --- /dev/null +++ b/zerolog/go.sum @@ -0,0 +1,40 @@ +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +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/getsentry/sentry-go v0.29.1 h1:DyZuChN8Hz3ARxGVV8ePaNXh1dQ7d76AiB117xcREwA= +github.com/getsentry/sentry-go v0.29.1/go.mod h1:x3AtIzN01d6SiWkderzaH28Tm0lgkafpJ5Bm3li39O0= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From e1db73ecfce6be2e81a484148d0e45104bc814ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 6 Nov 2024 00:08:39 +0100 Subject: [PATCH 28/31] update go vet script --- Makefile | 3 +-- zerolog/go.mod | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 89523ac0c..322a1d774 100644 --- a/Makefile +++ b/Makefile @@ -68,9 +68,8 @@ mod-tidy: ## Check go.mod tidiness vet: ## Run "go vet" set -e ; \ for dir in $(ALL_GO_MOD_DIRS); do \ - cd "$${dir}"; \ echo ">>> Running 'go vet' for module: $${dir}"; \ - go vet ./...; \ + (cd "$${dir}" && go vet ./...); \ done; .PHONY: vet diff --git a/zerolog/go.mod b/zerolog/go.mod index 5d0770d00..e8058e7a6 100644 --- a/zerolog/go.mod +++ b/zerolog/go.mod @@ -1,6 +1,6 @@ module github.com/getsentry/sentry-go/zerolog -go 1.23.2 +go 1.18 require ( github.com/buger/jsonparser v1.1.1 From 556bfbf18a71eb832254c1018c7f44fb48574ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 6 Nov 2024 00:49:12 +0100 Subject: [PATCH 29/31] update go.sum --- Makefile | 3 +-- zerolog/go.sum | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 322a1d774..6810c6905 100644 --- a/Makefile +++ b/Makefile @@ -58,9 +58,8 @@ test-coverage: $(COVERAGE_REPORT_DIR) clean-report-dir ## Test with coverage en mod-tidy: ## Check go.mod tidiness set -e ; \ for dir in $(ALL_GO_MOD_DIRS); do \ - cd "$${dir}"; \ echo ">>> Running 'go mod tidy' for module: $${dir}"; \ - go mod tidy -go=1.18 -compat=1.18; \ + (cd "$${dir}" && go mod tidy -go=1.18 -compat=1.18); \ done; \ git diff --exit-code; .PHONY: mod-tidy diff --git a/zerolog/go.sum b/zerolog/go.sum index 667206108..25c816ecb 100644 --- a/zerolog/go.sum +++ b/zerolog/go.sum @@ -6,10 +6,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/getsentry/sentry-go v0.29.1 h1:DyZuChN8Hz3ARxGVV8ePaNXh1dQ7d76AiB117xcREwA= github.com/getsentry/sentry-go v0.29.1/go.mod h1:x3AtIzN01d6SiWkderzaH28Tm0lgkafpJ5Bm3li39O0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -17,7 +15,6 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= 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= From 3cce39fbed724c4d0e9976da93d94f5cc9cae12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emir=20Ribi=C4=87?= Date: Wed, 13 Nov 2024 23:38:21 +0100 Subject: [PATCH 30/31] bump go version to 1.21 in zerolog: --- zerolog/go.mod | 2 +- zerolog/go.sum | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/zerolog/go.mod b/zerolog/go.mod index e8058e7a6..7af0778b3 100644 --- a/zerolog/go.mod +++ b/zerolog/go.mod @@ -1,6 +1,6 @@ module github.com/getsentry/sentry-go/zerolog -go 1.18 +go 1.21 require ( github.com/buger/jsonparser v1.1.1 diff --git a/zerolog/go.sum b/zerolog/go.sum index 25c816ecb..667206108 100644 --- a/zerolog/go.sum +++ b/zerolog/go.sum @@ -6,8 +6,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/getsentry/sentry-go v0.29.1 h1:DyZuChN8Hz3ARxGVV8ePaNXh1dQ7d76AiB117xcREwA= github.com/getsentry/sentry-go v0.29.1/go.mod h1:x3AtIzN01d6SiWkderzaH28Tm0lgkafpJ5Bm3li39O0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -15,6 +17,7 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= 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= From bd559f490eb19a39d0bc24d31a3c0530d2b587b0 Mon Sep 17 00:00:00 2001 From: Michi Hoffmann Date: Thu, 14 Nov 2024 15:17:39 +0100 Subject: [PATCH 31/31] Update Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f94c5760e..9cc0959fd 100644 --- a/Makefile +++ b/Makefile @@ -79,4 +79,4 @@ lint: ## Lint (using "golangci-lint") fmt: ## Format all Go files gofmt -l -w -s . -.PHONY: fmt \ No newline at end of file +.PHONY: fmt