From 2100e2ff7cac86f8bdb93ae424dfe026820fb6cd Mon Sep 17 00:00:00 2001 From: Michal Horejsek Date: Tue, 1 Dec 2020 15:13:16 +0100 Subject: [PATCH] Enhanced sentry reporting --- internal/cmd/main.go | 6 ++++-- pkg/sentry/report.go | 40 +++++++++++++++++++++++++++++++++--- pkg/sentry/report_test.go | 43 +++++++++++++++++++++++++++++++++++++++ unreleased.md | 1 + 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 pkg/sentry/report_test.go diff --git a/internal/cmd/main.go b/internal/cmd/main.go index fa15636d..d34fb255 100644 --- a/internal/cmd/main.go +++ b/internal/cmd/main.go @@ -22,6 +22,7 @@ import ( "runtime" "github.com/ProtonMail/proton-bridge/pkg/constants" + pkgSentry "github.com/ProtonMail/proton-bridge/pkg/sentry" "github.com/getsentry/sentry-go" "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -52,8 +53,9 @@ var ( // Main sets up Sentry, filters out unwanted args, creates app and runs it. func Main(appName, usage string, extraFlags []cli.Flag, run func(*cli.Context) error) { err := sentry.Init(sentry.ClientOptions{ - Dsn: constants.DSNSentry, - Release: constants.Revision, + Dsn: constants.DSNSentry, + Release: constants.Revision, + BeforeSend: pkgSentry.EnhanceSentryEvent, }) sentry.ConfigureScope(func(scope *sentry.Scope) { diff --git a/pkg/sentry/report.go b/pkg/sentry/report.go index cd967584..f447fda6 100644 --- a/pkg/sentry/report.go +++ b/pkg/sentry/report.go @@ -19,13 +19,19 @@ package sentry import ( "errors" + "regexp" "runtime" + "strings" "time" "github.com/getsentry/sentry-go" log "github.com/sirupsen/logrus" ) +var ( + isPanicHandlerRegexp = regexp.MustCompile(`^ReportSentryCrash|^(\(\*PanicHandler\)\.)?HandlePanic`) //nolint[gochecknoglobals] +) + // ReportSentryCrash reports a sentry crash. func ReportSentryCrash(clientID, appVersion, userAgent string, reportErr error) (err error) { if reportErr == nil { @@ -40,16 +46,44 @@ func ReportSentryCrash(clientID, appVersion, userAgent string, reportErr error) "UserID": "", } + var reportID string sentry.WithScope(func(scope *sentry.Scope) { scope.SetTags(tags) - sentry.CaptureException(reportErr) + eventID := sentry.CaptureException(reportErr) + if eventID != nil { + reportID = string(*eventID) + } }) if !sentry.Flush(time.Second * 10) { - log.WithField("error", reportErr).Error("failed to report sentry error") + log.WithField("error", reportErr).Error("Failed to report sentry error") return errors.New("failed to report sentry error") } - log.WithField("error", reportErr).Warn("reported sentry error") + log.WithField("error", reportErr).WithField("id", reportID).Warn("Sentry error reported") return } + +// EnhanceSentryEvent swaps type with value and removes panic handlers from the stacktrace. +func EnhanceSentryEvent(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { + for idx, exception := range event.Exception { + exception.Type, exception.Value = exception.Value, exception.Type + if exception.Stacktrace != nil { + exception.Stacktrace.Frames = filterOutPanicHandlers(exception.Stacktrace.Frames) + } + event.Exception[idx] = exception + } + return event +} + +func filterOutPanicHandlers(frames []sentry.Frame) []sentry.Frame { + idx := 0 + for _, frame := range frames { + if strings.HasPrefix(frame.Module, "github.com/ProtonMail/proton-bridge") && + isPanicHandlerRegexp.MatchString(frame.Function) { + break + } + idx++ + } + return frames[:idx] +} diff --git a/pkg/sentry/report_test.go b/pkg/sentry/report_test.go new file mode 100644 index 00000000..a473e063 --- /dev/null +++ b/pkg/sentry/report_test.go @@ -0,0 +1,43 @@ +// Copyright (c) 2020 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ProtonMail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ProtonMail Bridge. If not, see . + +package sentry + +import ( + "testing" + + r "github.com/stretchr/testify/require" + + "github.com/getsentry/sentry-go" +) + +func TestFilterOutPanicHandlers(t *testing.T) { + frames := []sentry.Frame{ + {Module: "github.com/ProtonMail/proton-bridge/internal/cmd", Function: "main"}, + {Module: "github.com/urfave/cli", Function: "(*App).Run"}, + {Module: "github.com/ProtonMail/proton-bridge/internal/cmd", Function: "RegisterHandlePanic"}, + {Module: "github.com/ProtonMail/pkg", Function: "HandlePanic"}, + {Module: "main", Function: "run"}, + {Module: "github.com/ProtonMail/proton-bridge/pkg/config", Function: "(*PanicHandler).HandlePanic"}, + {Module: "github.com/ProtonMail/proton-bridge/pkg/config", Function: "HandlePanic"}, + {Module: "github.com/ProtonMail/proton-bridge/pkg/sentry", Function: "ReportSentryCrash"}, + {Module: "github.com/ProtonMail/proton-bridge/pkg/sentry", Function: "ReportSentryCrash.func1"}, + } + + gotFrames := filterOutPanicHandlers(frames) + r.Equal(t, frames[:5], gotFrames) +} diff --git a/unreleased.md b/unreleased.md index 670b14d1..214e18d0 100644 --- a/unreleased.md +++ b/unreleased.md @@ -8,6 +8,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) ### Changed * GODT-893 Bump go-rfc5322 dependency to v0.2.1 to properly detect syntax errors during parsing. +* GODT-892 Swap type and value from sentry exception and cut panic handlers from the traceback. ### Removed * GODT-651 Build creates proper binary names.