fix(GODT-2390): Add reports for uncaught json and net.opErr

Report to sentry if we see some uncaught network err, but don't force
the user logout.

If we catch an uncaught json parser error we report the error to sentry
and let the user be logged out later.

Finally this patch also prints the error type in UserBadEvent sentry
report to further help diagnose issues.
This commit is contained in:
Leander Beernaert
2023-02-22 13:30:45 +01:00
parent 065dcd4d47
commit 3e878058e7
3 changed files with 45 additions and 1 deletions

View File

@ -56,6 +56,9 @@ func (bridge *Bridge) handleUserEvent(ctx context.Context, user *user.User, even
case events.UserBadEvent: case events.UserBadEvent:
bridge.handleUserBadEvent(ctx, user, event.Error) bridge.handleUserBadEvent(ctx, user, event.Error)
case events.UncategorizedEventError:
bridge.handleUncategorizedErrorEvent(event)
} }
return nil return nil
@ -139,7 +142,8 @@ func (bridge *Bridge) handleUserDeauth(ctx context.Context, user *user.User) {
func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, err error) { func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, err error) {
safe.Lock(func() { safe.Lock(func() {
if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event", reporter.Context{ if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event", reporter.Context{
"error": err, "error_type": fmt.Sprintf("%T", err),
"error": err,
}); rerr != nil { }); rerr != nil {
logrus.WithError(rerr).Error("Failed to report failed event handling") logrus.WithError(rerr).Error("Failed to report failed event handling")
} }
@ -147,3 +151,12 @@ func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, e
bridge.logoutUser(ctx, user, true, false) bridge.logoutUser(ctx, user, true, false)
}, bridge.usersLock) }, bridge.usersLock)
} }
func (bridge *Bridge) handleUncategorizedErrorEvent(event events.UncategorizedEventError) {
if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle due to uncategorized error", reporter.Context{
"error_type": fmt.Sprintf("%T", event.Error),
"error": event.Error,
}); rerr != nil {
logrus.WithError(rerr).Error("Failed to report failed event handling")
}
}

View File

@ -179,3 +179,14 @@ type IMAPLoginFailed struct {
func (event IMAPLoginFailed) String() string { func (event IMAPLoginFailed) String() string {
return fmt.Sprintf("IMAPLoginFailed: Username: %s", event.Username) return fmt.Sprintf("IMAPLoginFailed: Username: %s", event.Username)
} }
type UncategorizedEventError struct {
eventBase
UserID string
Error error
}
func (event UncategorizedEventError) String() string {
return fmt.Sprintf("UncategorizedEventError: UserID: %s, Source:%T, Error: %s", event.UserID, event.Error, event.Error)
}

View File

@ -20,9 +20,11 @@ package user
import ( import (
"context" "context"
"crypto/subtle" "crypto/subtle"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time" "time"
@ -649,6 +651,24 @@ func (user *User) doEventPoll(ctx context.Context) error {
return fmt.Errorf("failed to handle event due to network issue: %w", err) return fmt.Errorf("failed to handle event due to network issue: %w", err)
} }
// Catch all for uncategorized net errors that may slip through.
if netErr := new(net.OpError); errors.As(err, &netErr) {
user.eventCh.Enqueue(events.UncategorizedEventError{
UserID: user.ID(),
Error: err,
})
return fmt.Errorf("failed to handle event due to network issues (uncategorized): %w", err)
}
// In case a json decode error slips through.
if jsonErr := new(json.UnmarshalTypeError); errors.As(err, &jsonErr) {
user.eventCh.Enqueue(events.UncategorizedEventError{
UserID: user.ID(),
Error: err,
})
}
// If the error is a server-side issue, return error to retry later. // If the error is a server-side issue, return error to retry later.
if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status >= 500 { if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status >= 500 {
return fmt.Errorf("failed to handle event due to server error: %w", err) return fmt.Errorf("failed to handle event due to server error: %w", err)