From f749b6c5b26f188058f38fafab04c90d2e7f8026 Mon Sep 17 00:00:00 2001 From: Xavier Goffin Date: Mon, 2 Feb 2026 15:57:43 +0100 Subject: [PATCH 1/2] reporter/reporter.go: experiment: allow reporter to send the reported Level to Sentry --- go.mod | 10 ++++--- go.sum | 20 ++++++++------ reporter/reporter.go | 9 ++++++- reporter/sentry/reporter.go | 23 ++++++++++++++-- reporter/sentry/reporter_test.go | 46 ++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 5de4593..c1b2ee6 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,15 @@ go 1.24 require ( github.com/getsentry/sentry-go v0.35.3 github.com/stretchr/testify v1.11.1 + github.com/upfluence/log v0.0.6 + github.com/upfluence/pkg v1.14.0 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/kr/text v0.2.0 // 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 + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 8aab56b..1965482 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/getsentry/sentry-go v0.35.3 h1:u5IJaEqZyPdWqe/hKlBKBBnMTSxB/HenCqF3QLabeds= github.com/getsentry/sentry-go v0.35.3/go.mod h1:mdL49ixwT2yi57k5eh7mpnDyPybixPzlzEJFu0Z76QA= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -15,18 +15,22 @@ 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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/upfluence/log v0.0.6 h1:cG+dq0CXTZTXGknzwZbQEW2QQH6KRjUu9rysdhmhBcA= +github.com/upfluence/log v0.0.6/go.mod h1:pCbKPbgnoF5zqR9JsTgParTIEBvqXsIuaa8eoEVhdPA= +github.com/upfluence/pkg v1.14.0 h1:7mzRGOL2mC6wsygts03pefCZB+5qMpmn24l41eZnEBw= +github.com/upfluence/pkg v1.14.0/go.mod h1:Dmz2/YfHzxE+EZPhbulsoeig21sIY80XqTPmT3rjqUg= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -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= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/reporter/reporter.go b/reporter/reporter.go index b77d806..5d81044 100644 --- a/reporter/reporter.go +++ b/reporter/reporter.go @@ -5,7 +5,11 @@ // contextual information including request details, user information, and custom tags. package reporter -import "io" +import ( + "io" + + "github.com/upfluence/log/record" +) // Common tag keys for error reporting metadata. const ( @@ -42,6 +46,9 @@ type ReportOptions struct { Tags map[string]interface{} Depth int + + // Add the record level that the logger used + ReportedLevel *record.Level } // Reporter is the interface for error reporting implementations. diff --git a/reporter/sentry/reporter.go b/reporter/sentry/reporter.go index 6b2faf0..d80e40b 100644 --- a/reporter/sentry/reporter.go +++ b/reporter/sentry/reporter.go @@ -22,6 +22,7 @@ import ( "github.com/upfluence/errors/reporter" "github.com/upfluence/errors/stacktrace" "github.com/upfluence/errors/tags" + "github.com/upfluence/log/record" ) // Reporter is a Sentry error reporter implementation. @@ -137,7 +138,7 @@ func (r *Reporter) buildEvent(err error, opts reporter.ReportOptions) *sentry.Ev evt := sentry.NewEvent() - evt.Level = r.computeLevel(err) + evt.Level = r.computeLevel(err, opts) evt.Timestamp = time.Now() evt.Message = err.Error() evt.Transaction = transactionName(errorTags) @@ -166,7 +167,25 @@ func (r *Reporter) buildEvent(err error, opts reporter.ReportOptions) *sentry.Ev return evt } -func (r *Reporter) computeLevel(err error) sentry.Level { +var reporterToSentryLevel = map[record.Level]sentry.Level{ + record.Debug: sentry.LevelDebug, + record.Info: sentry.LevelInfo, + record.Notice: sentry.LevelInfo, + record.Warning: sentry.LevelWarning, + record.Error: sentry.LevelError, + record.Fatal: sentry.LevelFatal, +} + +func (r *Reporter) computeLevel(err error, opts reporter.ReportOptions) sentry.Level { + // we suppose that the programmer knows best: if an error is loged as warning, + // it is a warning, in spite of the level mappers. + // as Error is the default level, it is ignored for this process + if opts.ReportedLevel != nil && *opts.ReportedLevel != record.Error { + if sl, ok := reporterToSentryLevel[*opts.ReportedLevel]; ok { + return sl + } + } + for _, errFunc := range r.levelMappers { if level := errFunc(err); level != "" { return level diff --git a/reporter/sentry/reporter_test.go b/reporter/sentry/reporter_test.go index bcc3385..17f6c73 100644 --- a/reporter/sentry/reporter_test.go +++ b/reporter/sentry/reporter_test.go @@ -12,6 +12,8 @@ import ( "github.com/upfluence/errors" "github.com/upfluence/errors/recovery" "github.com/upfluence/errors/reporter" + "github.com/upfluence/log/record" + "github.com/upfluence/pkg/pointers" ) type mockError struct{} @@ -257,6 +259,50 @@ func TestBuildEvent(t *testing.T) { ) }, }, + { + name: "wrapped error type with reported level Error", + err: errors.Wrap(&mockError{}, "i am being mocked"), + modifiers: []func(*Reporter){ + func(r *Reporter) { + r.levelMappers = append( + r.levelMappers, + ErrorIsOfTypeLevel[*mockError](sentry.LevelDebug), + ) + }, + }, + ropts: reporter.ReportOptions{ + ReportedLevel: pointers.Ptr(record.Error), + }, + evtfn: func(t *testing.T, evt *sentry.Event) { + assert.Equal( + t, + sentry.LevelDebug, + evt.Level, + ) + }, + }, + { + name: "wrapped error type with reported level Warning", + err: errors.Wrap(&mockError{}, "i am being mocked"), + modifiers: []func(*Reporter){ + func(r *Reporter) { + r.levelMappers = append( + r.levelMappers, + ErrorIsOfTypeLevel[*mockError](sentry.LevelDebug), + ) + }, + }, + ropts: reporter.ReportOptions{ + ReportedLevel: pointers.Ptr(record.Warning), + }, + evtfn: func(t *testing.T, evt *sentry.Event) { + assert.Equal( + t, + sentry.LevelWarning, + evt.Level, + ) + }, + }, } { t.Run(tt.name, func(t *testing.T) { r, err := NewReporter(tt.opts...) From a4949ece809153db0ab805bcc52adcf39daa2b9f Mon Sep 17 00:00:00 2001 From: Xavier Goffin <86716549+xgoffin@users.noreply.github.com> Date: Tue, 3 Feb 2026 10:01:42 +0100 Subject: [PATCH 2/2] Update reporter/sentry/reporter.go Co-authored-by: Alexis Montagne --- reporter/sentry/reporter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reporter/sentry/reporter.go b/reporter/sentry/reporter.go index d80e40b..7f12a1f 100644 --- a/reporter/sentry/reporter.go +++ b/reporter/sentry/reporter.go @@ -177,7 +177,7 @@ var reporterToSentryLevel = map[record.Level]sentry.Level{ } func (r *Reporter) computeLevel(err error, opts reporter.ReportOptions) sentry.Level { - // we suppose that the programmer knows best: if an error is loged as warning, + // we suppose that the programmer knows best: if an error is logged as warning, // it is a warning, in spite of the level mappers. // as Error is the default level, it is ignored for this process if opts.ReportedLevel != nil && *opts.ReportedLevel != record.Error {