pbrisbin / bugsnag-haskell

Bugsnag error reporter for Haskell
10 stars 7 forks source link

Better grouping of errors #43

Closed MaxGabriel closed 5 years ago

MaxGabriel commented 5 years ago

Many of the exceptions our app generates are SomeException or IOException without a known file or line number. Do you run into this a lot? It causes many of our exceptions to be grouped together erroneously:

image

I was thinking a possible workaround for us is to report exceptions by the full name (e.g. SqlError {sqlState = "23514", sqlExecStatus = FatalError, sqlErrorMsg = "value for domain text299...), or look into using a features like the grouping hash to group better.

Any thoughts on this?

pbrisbin commented 5 years ago

This library actually has good support for Grouping Hash. If you wanted to do exactly what you describe (group by message), that would look something like:

let beforeNotify = defaultBeforeNotify
        . setGroupingHashBy (beMessage . beException)

But that would lead to unique exceptions by message, which means the same duplicate key error will be unique exceptions because the conflicting id differs between occurrences. It's not much of an improvement.

What we've been doing instead is using updateEventFromOriginalException. This lets you "cast" (via fromException) to an in-scope type (e.g. SqlError) and use it to better-define grouping.

let beforeNotify = defaultBeforeNotify
        . updateEventFromOriginalException asSqlError
        . updateEventFromOriginalException asHttpException

asSqlError :: SqlError -> BeforeNotify
asSqlError SqlError {..} = updateException $ \ex -> ex
  { beErrorClass = decodeUtf8 $ "SqlError-" <> sqlState
  , beMessage =
    Just
    $ decodeUtf8
    $ sqlErrorMsg
    <> ": "
    <> sqlErrorDetail
    <> " ("
    <> sqlErrorHint
    <> ")"
  }

asHttpException :: HttpException -> BeforeNotify
asHttpException (HttpExceptionRequest req content) = updateException $ \ex ->
  ex
    { beErrorClass = "HttpExceptionRequest"
    , beMessage =
      Just
      . decodeUtf8
      $ method req
      <> " request to "
      <> host req
      <> " failed: "
      <> BS8.pack (show content)
    }
asHttpException (InvalidUrlException url msg) = updateException $ \ex -> ex
  { beErrorClass = "InvalidUrlException"
  , beMessage = Just $ pack $ url <> " is invalid: " <> msg
  }

Grouping it by the sqlState has been... OK, it still groups things that shouldn't be grouped, but it is better than nothing.

pbrisbin commented 5 years ago

I'm going to close this as I don't think it's an open problem in the library. But happy to continue discussion (as usual).