{-# LANGUAGE OverloadedStrings #-}
module Network.Bugsnag.BeforeNotify
( BeforeNotify
, updateException
, updateStackFrames
, filterStackFrames
, setStackFramesCode
, setStackFramesInProject
, setStackFramesInProjectBy
, setGroupingHash
, setGroupingHashBy
, updateEventFromException
, updateEventFromOriginalException
, updateEventFromSession
, updateEventFromWaiRequest
, updateEventFromWaiRequestUnredacted
, redactRequestHeaders
, setDevice
, setRequest
, setStacktrace
, setWarningSeverity
, setErrorSeverity
, setInfoSeverity
) where
import Control.Exception (Exception, fromException)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Network.Bugsnag.CodeIndex
import Network.Bugsnag.Device
import Network.Bugsnag.Event
import Network.Bugsnag.Exception
import Network.Bugsnag.Request
import Network.Bugsnag.Session
import Network.Bugsnag.Severity
import Network.Bugsnag.StackFrame
import Network.HTTP.Types.Header (Header, HeaderName)
import Network.Wai (Request)
type BeforeNotify = BugsnagEvent -> BugsnagEvent
updateException :: (BugsnagException -> BugsnagException) -> BeforeNotify
updateException f event = event { beException = f $ beException event }
updateStackFrames :: (BugsnagStackFrame -> BugsnagStackFrame) -> BeforeNotify
updateStackFrames f =
updateException $ \ex -> ex { beStacktrace = map f $ beStacktrace ex }
filterStackFrames :: (BugsnagStackFrame -> Bool) -> BeforeNotify
filterStackFrames p =
updateException $ \ex -> ex { beStacktrace = filter p $ beStacktrace ex }
setStackFramesCode :: CodeIndex -> BeforeNotify
setStackFramesCode = updateStackFrames . attachBugsnagCode
setStackFramesInProject :: (FilePath -> Bool) -> BeforeNotify
setStackFramesInProject = setStackFramesInProjectBy bsfFile
setStackFramesInProjectBy
:: (BugsnagStackFrame -> a) -> (a -> Bool) -> BeforeNotify
setStackFramesInProjectBy f p =
updateStackFrames $ \sf -> sf { bsfInProject = Just $ p $ f sf }
setGroupingHash :: Text -> BeforeNotify
setGroupingHash hash = setGroupingHashBy $ const $ Just hash
setGroupingHashBy :: (BugsnagEvent -> Maybe Text) -> BeforeNotify
setGroupingHashBy f event = event { beGroupingHash = f event }
updateEventFromException :: (BugsnagException -> BeforeNotify) -> BeforeNotify
updateEventFromException f event = f (beException event) event
updateEventFromOriginalException
:: Exception e => (e -> BeforeNotify) -> BeforeNotify
updateEventFromOriginalException f event = fromMaybe event $ do
someException <- beOriginalException $ beException event
yourException <- fromException someException
pure $ f yourException event
updateEventFromWaiRequest :: Request -> BeforeNotify
updateEventFromWaiRequest wrequest =
redactRequestHeaders ["Authorization", "Cookie", "X-XSRF-TOKEN"]
. updateEventFromWaiRequestUnredacted wrequest
updateEventFromWaiRequestUnredacted :: Request -> BeforeNotify
updateEventFromWaiRequestUnredacted wrequest =
let
mdevice = bugsnagDeviceFromWaiRequest wrequest
request = bugsnagRequestFromWaiRequest wrequest
in maybe id setDevice mdevice . setRequest request
updateEventFromSession :: BugsnagSession -> BeforeNotify
updateEventFromSession session event =
event { beContext = bsContext session, beUser = bsUser session }
redactRequestHeaders :: [HeaderName] -> BeforeNotify
redactRequestHeaders headers event =
event { beRequest = redactHeaders headers <$> beRequest event }
redactHeaders :: [HeaderName] -> BugsnagRequest -> BugsnagRequest
redactHeaders headers request = request
{ brHeaders = map redactHeader <$> brHeaders request
}
where
redactHeader :: Header -> Header
redactHeader (k, _) | k `elem` headers = (k, "<redacted>")
redactHeader h = h
setRequest :: BugsnagRequest -> BeforeNotify
setRequest request event = event { beRequest = Just request }
setDevice :: BugsnagDevice -> BeforeNotify
setDevice device event = event { beDevice = Just device }
setStacktrace :: [BugsnagStackFrame] -> BeforeNotify
setStacktrace stacktrace =
updateException $ \ex -> ex { beStacktrace = stacktrace }
setErrorSeverity :: BeforeNotify
setErrorSeverity = setSeverity ErrorSeverity
setWarningSeverity :: BeforeNotify
setWarningSeverity = setSeverity WarningSeverity
setInfoSeverity :: BeforeNotify
setInfoSeverity = setSeverity InfoSeverity
setSeverity :: BugsnagSeverity -> BeforeNotify
setSeverity severity event = event { beSeverity = Just severity }