Skip to content

mkException puts the rendered exception text in class, breaking Rollbar grouping #98

Description

@resparza95

Problem

mkException fills the class field with the full rendered exception text:

-- rollbar-client/src/Rollbar/Client/Item.hs
mkException :: E.Exception e => e -> Exception
mkException e = Exception
  { exceptionClass = T.pack $ E.displayException e
  , exceptionMessage = Nothing
  , exceptionDescription = Nothing
  }

This contradicts the Exception type's own field docs (exceptionClass — "The exception class name", exceptionMessage — "The exception message, as a string") and Rollbar's API, which uses class as the primary grouping key for trace payloads. Since every distinct message produces a distinct class, each unique message mints its own Rollbar item. Messages routinely embed per-occurrence data (URLs, ids, CallStacks with package build hashes), so real-world deployments get one item per occurrence instead of one item per failure cause — we measured 135 items for ~2 causes in one 90-day export (iTrafficCenter/full-circle#3379).

Both library call sites are affected: withRollbar (Rollbar.Client) and the wai/yesod middleware (Rollbar.Wai).

Proposal

  • class = the concrete exception type name, e.g. via Data.Typeable (unwrapping SomeException first, since both call sites pass SomeException and typeOf would otherwise always yield "SomeException"):

    mkException :: E.Exception e => e -> Exception
    mkException e = Exception
      { exceptionClass = T.pack $ show $ typeOf inner
      , exceptionMessage = Just $ firstLine rendered
      , exceptionDescription = Just rendered
      }
      where
        SomeException inner = E.toException e
        rendered = T.pack $ E.displayException e
        firstLine = T.takeWhile (/= '\n')
  • message = first line of displayException; description = the full text, so no information is lost — it just stops living in the grouping key.

Related: empty frames

Both call sites send Trace [] …. Rollbar's default grouping for trace payloads is class + frames, so with the fix above all exceptions of one type collapse into a single item unless the reporting application sets an explicit fingerprint. The Frame type already exists but nothing populates it. Options worth exploring (possibly as a separate issue): an API for callers to supply frames, populating them from HasCallStack/ErrorCallWithLocation where available, or the exception backtraces available from GHC 9.10.

Breaking change

Any consumer relying on the current defaults will see all existing Rollbar items re-group once (new classes → new items) after upgrading. This warrants a major version bump and a release-notes warning.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions