{-# LANGUAGE OverloadedStrings #-}
module Network.Bugsnag.BeforeNotify
( BeforeNotify
, defaultBeforeNotify
, updateException
, filterStackFrames
, setStackFramesInProject
, setGroupingHash
, setGroupingHashBy
, updateEventFromSession
, updateEventFromWaiRequest
, redactRequestHeaders
, setDevice
, setRequest
, setStacktrace
, setWarningSeverity
, setErrorSeverity
, setInfoSeverity
) where
import Data.Text (Text)
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
defaultBeforeNotify :: BeforeNotify
defaultBeforeNotify =
redactRequestHeaders ["Authorization", "Cookie", "X-XSRF-TOKEN"]
updateException :: (BugsnagException -> BugsnagException) -> BeforeNotify
updateException f event = event { beExceptions = f <$> beExceptions event }
filterStackFrames :: (BugsnagStackFrame -> Bool) -> BeforeNotify
filterStackFrames p =
updateException $ \ex -> ex { beStacktrace = filter p $ beStacktrace ex }
setStackFramesInProject :: (FilePath -> Bool) -> BeforeNotify
setStackFramesInProject p = updateException
$ \ex -> ex { beStacktrace = map updateStackFrames $ beStacktrace ex }
where
updateStackFrames :: BugsnagStackFrame -> BugsnagStackFrame
updateStackFrames sf = sf { bsfInProject = Just $ p $ bsfFile sf }
setGroupingHash :: Text -> BeforeNotify
setGroupingHash hash = setGroupingHashBy $ const $ Just hash
setGroupingHashBy :: (BugsnagEvent -> Maybe Text) -> BeforeNotify
setGroupingHashBy f event = event { beGroupingHash = f event }
updateEventFromWaiRequest :: Request -> BeforeNotify
updateEventFromWaiRequest 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 }