MIT licensed
Maintained by Taylor Fausak
This version can be pinned in stack with:patrol-1.2.0.5@sha256:118771fe2925ab605bb894abbd045025a5ada4dc1f4fd56cca44b7a2758ce6fd,5170

Patrol

CI Hackage

Patrol is a Sentry SDK for Haskell.

Usage

Basic exception reporting

The simplest way to report an exception is with captureException. It reads the DSN from the SENTRY_DSN environment variable.

import qualified Patrol

main :: IO ()
main = do
  result <- doSomething
  case result of
    Left err -> do
      _ <- Patrol.captureException err
      pure ()
    Right val -> use val

Customizing the event

Use captureExceptionWith to add tags, set the environment, attach user info, or otherwise modify the event before it is sent.

import qualified Data.Map as Map
import qualified Data.Text as Text
import qualified Patrol
import qualified Patrol.Type.Dsn as Dsn
import qualified Patrol.Type.Event as Event
import qualified Patrol.Type.Level as Level
import qualified Patrol.Type.User as User

reportException :: Dsn.Dsn -> SomeException -> IO ()
reportException dsn err = do
  _ <- Patrol.captureExceptionWith modifyEvent dsn err
  pure ()
  where
    modifyEvent :: Event.Event -> IO Event.Event
    modifyEvent event = pure event
      { Event.tags = Map.fromList
          [ (Text.pack "component", Text.pack "api")
          ]
      , Event.level = Just Level.Warning
      , Event.user = Just User.empty
          { User.id = Text.pack "user-123"
          , User.email = Text.pack "[email protected]"
          }
      , Event.environment = Text.pack "staging"
      }

Warp middleware

Here is an example of a Warp middleware that reports non-success HTTP responses to Sentry.

import qualified Data.Map as Map
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import qualified Network.HTTP.Types as Http
import qualified Network.Wai as Wai
import qualified Patrol
import qualified Patrol.Type.Dsn as Dsn
import qualified Patrol.Type.Event as Event

sentryMiddleware :: Dsn.Dsn -> Wai.Middleware
sentryMiddleware dsn app request respond =
  app request $ \response -> do
    let status = Wai.responseStatus response
    Control.Monad.when (Http.statusCode status >= 500) $ do
      let err = userError $ "HTTP " <> show (Http.statusCode status)
      _ <- Patrol.captureExceptionWith (modifyEvent request status) dsn err
      pure ()
    respond response
  where
    modifyEvent :: Wai.Request -> Http.Status -> Event.Event -> IO Event.Event
    modifyEvent request status event = pure event
      { Event.tags = Map.fromList
          [ (Text.pack "path", Text.decodeUtf8 (Wai.rawPathInfo request))
          , (Text.pack "status_code", Text.pack (show (Http.statusCode status)))
          ]
      }

Changes

Change log

Patrol uses the Package Versioning Policy. The change log is available through the releases on GitHub.