packages feed

freckle-app-1.20.0.1: library/Freckle/App/Bugsnag/MetaData.hs

-- | Working with Bugsnag's 'event_metaData' field
module Freckle.App.Bugsnag.MetaData
  ( MetaData (..)
  , metaData
  , metaDataL

    -- * Collecting ambient data
  , collectMetaData
  , collectMetaDataFromStatsClient
  , collectMetaDataFromThreadContext

    -- * 'BeforeNotify'
  , mergeMetaData
  ) where

import Freckle.App.Prelude

import Blammo.Logging.ThreadContext (myThreadContext)
import Control.Lens (Lens', lens, to, view, (<>~))
import Data.Aeson (Value (..))
import Data.Aeson.KeyMap qualified as KeyMap
import Data.Bugsnag (Event (..))
import Data.String (fromString)
import Freckle.App.Stats (HasStatsClient (..), tagsL)
import Network.Bugsnag (BeforeNotify, updateEvent)
import Network.Bugsnag.MetaData

metaDataL :: Lens' Event MetaData
metaDataL = lens get set
 where
  get event = maybe mempty MetaData $ event_metaData event
  set event md = event {event_metaData = Just $ unMetaData md}

-- | Collect 'MetaData' from a 'StatsClient' and 'myThreadContext'
--
-- Using this (and then 'mergeMetaData') will unify exception metadata with
-- metrics tags and the logging context.
collectMetaData
  :: (MonadIO m, MonadReader env m, HasStatsClient env) => m MetaData
collectMetaData =
  (<>) <$> collectMetaDataFromStatsClient <*> collectMetaDataFromThreadContext

collectMetaDataFromStatsClient
  :: (MonadReader env m, HasStatsClient env) => m MetaData
collectMetaDataFromStatsClient = view $ statsClientL . tagsL . to toMetaData
 where
  toMetaData = metaData "tags" . map (bimap (fromString . unpack) String)

collectMetaDataFromThreadContext :: MonadIO m => m MetaData
collectMetaDataFromThreadContext =
  liftIO $ metaData "context" . KeyMap.toList <$> myThreadContext

-- | Merge 'MetaData' into the 'Event'
--
-- The given metadata will be combined with what already exists using '(<>)',
-- preserving the incoming values on collisions.
mergeMetaData :: MetaData -> BeforeNotify
mergeMetaData md = updateEvent $ metaDataL <>~ md