nri-prelude-0.7.0.0: src/Platform/Analytics/Internal.hs
{-# LANGUAGE FlexibleInstances #-}
-- | Internal entry point for emitting analytics events from `Task` code.
--
-- This module is intentionally `.Internal`. It is NOT re-exported from
-- the prelude's public `Platform` module. Higher layers (NoRedInk's
-- `Analytics.track`) wrap this and own the user-facing API; downstream
-- code that imports `Platform.Analytics.Internal` directly is bypassing
-- the closed event dictionary and should be flagged in review.
module Platform.Analytics.Internal
( trackEvent,
AnalyticsEventDetails,
)
where
import qualified Data.Aeson as Aeson
import NriPrelude
import qualified Platform
import qualified Platform.Internal as Internal
import qualified Prelude
-- | Send an analytics event. Opens a child tracing span named
-- @analytics.track@, attaches the JSON payload as the span's details,
-- and invokes the `LogHandler`'s analytics callback. The callback runs
-- as a `Task` with the current `LogHandler`, so any errors it logs flow
-- through the normal observability pipeline.
trackEvent :: (Aeson.ToJSON e) => e -> Task err ()
trackEvent event =
let value = Aeson.toJSON event
in Platform.tracingSpan "analytics.track" <| do
Platform.setTracingSpanDetails (AnalyticsEventDetails value)
Internal.Task
( \handler -> do
let Internal.Task runCallback = Internal.trackAnalyticsEvent handler value
_ <- runCallback handler
Prelude.pure (Ok ())
)
-- | A `TracingSpanDetails` wrapper around the analytics event payload, so
-- that the JSON we send to the analytics backend is also attached to the
-- @analytics.track@ span and visible in the existing observability
-- reporters.
newtype AnalyticsEventDetails = AnalyticsEventDetails Aeson.Value
deriving (Aeson.ToJSON)
instance Internal.TracingSpanDetails AnalyticsEventDetails