Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 0
feat(reporter/sentry): filtering funcs to set custom error level on sentry#18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
01fd3c04a03d7aa2fea3dcdd19d53e33ddbc51e6c2File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,55 @@ | ||
| package sentry | ||
| import ( | ||
| "context" | ||
| "io" | ||
| "os" | ||
| "strings" | ||
| "time" | ||
| "github.com/getsentry/sentry-go" | ||
| uerrors "github.com/upfluence/errors" | ||
| "github.com/upfluence/errors/base" | ||
| "github.com/upfluence/errors/reporter" | ||
| ) | ||
| var defaultOptions = Options{ | ||
| Tags: make(map[string]string), | ||
| SentryOptions: sentry.ClientOptions{ | ||
| Dsn: os.Getenv("SENTRY_DSN"), | ||
| Environment: os.Getenv("ENV"), | ||
| SendDefaultPII: true, | ||
| }, | ||
| TagWhitelist: toStringMap( | ||
| []string{reporter.RemoteIP, reporter.RemotePort, reporter.DomainKey}, | ||
| ), | ||
| Timeout: time.Minute, | ||
| TagBlacklist: []func(string) bool{ | ||
| stringEqual(reporter.TransactionKey), | ||
| stringEqual(reporter.UserEmailKey), | ||
| stringEqual(reporter.UserIDKey), | ||
| stringEqual(reporter.HTTPRequestProtoKey), | ||
| stringEqual(reporter.HTTPRequestPathKey), | ||
| stringEqual(reporter.HTTPRequestHostKey), | ||
| stringEqual(reporter.HTTPRequestMethodKey), | ||
| stringEqual(reporter.HTTPRequestBodyKey), | ||
| stringPrefix(reporter.HTTPRequestHeaderKeyPrefix), | ||
| stringPrefix(reporter.HTTPRequestQueryValuesKeyPrefix), | ||
| }, | ||
| type ErrorLevelMapper func(error) sentry.Level | ||
| var defaultErrorLevelMappers = []ErrorLevelMapper{ | ||
| ErrorIsLevel(context.DeadlineExceeded, sentry.LevelWarning), | ||
| ErrorIsLevel(context.Canceled, sentry.LevelWarning), | ||
| ErrorIsLevel(io.EOF, sentry.LevelWarning), | ||
| ErrorCauseTextContainsLevel("net/http: TLS handshake timeout", sentry.LevelWarning), | ||
| ErrorCauseTextContainsLevel("operation was canceled", sentry.LevelWarning), | ||
| ErrorCauseTextContainsLevel("EOF", sentry.LevelWarning), | ||
| } | ||
| func defaultOptions() Options { | ||
| return Options{ | ||
| Tags: make(map[string]string), | ||
| SentryOptions: sentry.ClientOptions{ | ||
| Dsn: os.Getenv("SENTRY_DSN"), | ||
| Environment: os.Getenv("ENV"), | ||
| SendDefaultPII: true, | ||
| }, | ||
| TagWhitelist: toStringMap( | ||
| []string{reporter.RemoteIP, reporter.RemotePort, reporter.DomainKey}, | ||
| ), | ||
| Timeout: time.Minute, | ||
| TagBlacklist: []func(string) bool{ | ||
| stringEqual(reporter.TransactionKey), | ||
| stringEqual(reporter.UserEmailKey), | ||
| stringEqual(reporter.UserIDKey), | ||
| stringEqual(reporter.HTTPRequestProtoKey), | ||
| stringEqual(reporter.HTTPRequestPathKey), | ||
| stringEqual(reporter.HTTPRequestHostKey), | ||
| stringEqual(reporter.HTTPRequestMethodKey), | ||
| stringEqual(reporter.HTTPRequestBodyKey), | ||
| stringPrefix(reporter.HTTPRequestHeaderKeyPrefix), | ||
| stringPrefix(reporter.HTTPRequestQueryValuesKeyPrefix), | ||
| }, | ||
| ErrorLevelMappers: defaultErrorLevelMappers, | ||
| } | ||
| } | ||
| func stringEqual(x string) func(string) bool { | ||
| @@ -52,6 +70,44 @@ func toStringMap(vs []string) map[string]struct{} { | ||
| return res | ||
| } | ||
| // ErrorIsLevel creates an ErrorLevelMapper of the passed level that checks if | ||
| // reported errors are the same as the given sentinel error | ||
| func ErrorIsLevel(sentinel error, level sentry.Level) ErrorLevelMapper { | ||
| return func(err error) sentry.Level { | ||
| if uerrors.Is(err, sentinel) { | ||
| return level | ||
| } | ||
| return "" | ||
| } | ||
| } | ||
| // ErrorIsOfTypeLevel creates an ErrorLevelMapper of the passed level that checks | ||
| // if reported errors are of the passed generic type | ||
| func ErrorIsOfTypeLevel[T error](level sentry.Level) ErrorLevelMapper { | ||
| return func(err error) sentry.Level { | ||
| if uerrors.IsOfType[T](err) { | ||
| return level | ||
| } | ||
| return "" | ||
| } | ||
| } | ||
| // ErrorCauseTextContainsLevel creates an ErrorLevelMapper of the passed level that checks | ||
| // if reported errors' cause's Error() text contains the passed string | ||
| func ErrorCauseTextContainsLevel(errorText string, level sentry.Level) ErrorLevelMapper { | ||
| return func(err error) sentry.Level { | ||
| rootCause := base.UnwrapAll(err).Error() | ||
| if strings.Contains(rootCause, errorText) { | ||
| return level | ||
| } | ||
| return "" | ||
| } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nil error causes panic in ErrorCauseTextContainsLevel mapperThe | ||
| } | ||
| type Options struct { | ||
| Tags map[string]string | ||
| @@ -60,6 +116,8 @@ type Options struct { | ||
| TagWhitelist map[string]struct{} | ||
| TagBlacklist []func(string) bool | ||
| ErrorLevelMappers []ErrorLevelMapper | ||
| } | ||
| func (o Options) client() (*sentry.Client, error) { | ||
| @@ -74,10 +132,25 @@ func (o Options) client() (*sentry.Client, error) { | ||
| type Option func(*Options) | ||
| // WithTags allows for custom tags to be given to the Reporter | ||
cursor[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| func WithTags(tags map[string]string) Option { | ||
| return func(opts *Options) { | ||
| for k, v := range tags { | ||
| opts.Tags[k] = v | ||
| } | ||
| } | ||
| } | ||
| // AppendErrorLevelMappers adds the passed funcs to the ErrorLevelMappers of the Reporter | ||
| func AppendErrorLevelMappers(funcs ...ErrorLevelMapper) Option { | ||
| return func(opts *Options) { | ||
| opts.ErrorLevelMappers = append(opts.ErrorLevelMappers, funcs...) | ||
| } | ||
| } | ||
| // ReplaceErrorLevelMappers replaces the ErrorLevelMappers of the Reporter with the passed ones | ||
| func ReplaceErrorLevelMappers(funcs []ErrorLevelMapper) Option { | ||
| return func(opts *Options) { | ||
| opts.ErrorLevelMappers = funcs | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -30,13 +30,14 @@ type Reporter struct { | ||
| tagWhitelist []func(string) bool | ||
| tagBlacklist []func(string) bool | ||
| levelMappers []ErrorLevelMapper | ||
| timeout time.Duration | ||
| } | ||
| // NewReporter creates a new Sentry reporter with the given options. | ||
| func NewReporter(os ...Option) (*Reporter, error) { | ||
| var opts = defaultOptions | ||
| var opts = defaultOptions() | ||
| for _, o := range os { | ||
| o(&opts) | ||
| @@ -58,6 +59,7 @@ func NewReporter(os ...Option) (*Reporter, error) { | ||
| }, | ||
| tagBlacklist: opts.TagBlacklist, | ||
| timeout: opts.Timeout, | ||
| levelMappers: opts.ErrorLevelMappers, | ||
| }, nil | ||
| } | ||
| @@ -121,26 +123,26 @@ func (r *Reporter) buildEvent(err error, opts reporter.ReportOptions) *sentry.Ev | ||
| return nil | ||
| } | ||
| ts := tags.GetTags(err) | ||
| errorTags := tags.GetTags(err) | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick: the repository is already named Same feedback for:
ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem here is that Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that makes sends for ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, can do when I next get to work on this one 👍 | ||
| if ts == nil && len(opts.Tags) > 0 { | ||
| ts = make(map[string]interface{}, len(opts.Tags)) | ||
| if errorTags == nil && len(opts.Tags) > 0 { | ||
| errorTags = make(map[string]interface{}, len(opts.Tags)) | ||
| } | ||
| for k, v := range opts.Tags { | ||
| if _, ok := ts[k]; !ok { | ||
| ts[k] = v | ||
| if _, ok := errorTags[k]; !ok { | ||
| errorTags[k] = v | ||
| } | ||
| } | ||
| evt := sentry.NewEvent() | ||
| evt.Level = sentry.LevelError | ||
| evt.Level = r.computeLevel(err) | ||
| evt.Timestamp = time.Now() | ||
| evt.Message = err.Error() | ||
| evt.Transaction = transactionName(ts) | ||
| evt.User = buildUser(ts) | ||
| evt.Request = buildRequest(ts) | ||
| evt.Transaction = transactionName(errorTags) | ||
| evt.User = buildUser(errorTags) | ||
| evt.Request = buildRequest(errorTags) | ||
| cause := base.UnwrapAll(err) | ||
| @@ -153,7 +155,7 @@ func (r *Reporter) buildEvent(err error, opts reporter.ReportOptions) *sentry.Ev | ||
| }, | ||
| } | ||
| for k, v := range ts { | ||
| for k, v := range errorTags { | ||
| r.appendTag(k, v, evt) | ||
| } | ||
| @@ -164,6 +166,16 @@ func (r *Reporter) buildEvent(err error, opts reporter.ReportOptions) *sentry.Ev | ||
| return evt | ||
| } | ||
| func (r *Reporter) computeLevel(err error) sentry.Level { | ||
| for _, errFunc := range r.levelMappers { | ||
| if level := errFunc(err); level != "" { | ||
| return level | ||
| } | ||
| } | ||
| return sentry.LevelError | ||
| } | ||
| func extractStacktrace(err error, n int) *sentry.Stacktrace { | ||
| var s sentry.Stacktrace | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw that you applied the comment https://github.com/upfluence/errors/pull/18/changes#r2578258351 in the
reporter.gofile can you apply the comment in this file as wellThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, for exported names, we had that conversation previously with @Sypheos and @karitham : #18 (comment), not sure it's a very good idea for clarity's sake to just call them
LevelFuncs, for instance, unless you have a better idea?For private constructions I don't mind