{-# LANGUAGE RankNTypes #-}
module Ecluse.Core.Telemetry.Span (
TracingPort (..),
WorkerTracingPort (..),
JobSpanOutcome (..),
AdvisorySyncTracingPort (..),
ecluseScope,
withOptionalSpan,
openOptionalSpan,
closeOptionalSpan,
) where
import OpenTelemetry.Context qualified as Ctx
import OpenTelemetry.Trace.Core (
Span,
SpanKind,
TracerProvider,
createSpan,
defaultSpanArguments,
endSpan,
kind,
makeTracer,
tracerOptions,
)
import UnliftIO (MonadUnliftIO, bracket)
import Ecluse.Core.Ecosystem (Ecosystem)
import Ecluse.Core.Package (PackageName)
import Ecluse.Core.Queue (RemoteSpanContext)
import Ecluse.Core.Server.Response (ServeDecision)
import Ecluse.Core.Telemetry.Metrics (AdvisorySyncResult)
import Ecluse.Core.Version (Version)
data TracingPort = TracingPort
{ TracingPort
-> forall a.
PackageName -> Version -> IO (a, ServeDecision) -> IO a
spanRuleEval :: forall a. PackageName -> Version -> IO (a, ServeDecision) -> IO a
, TracingPort
-> forall a.
PackageName
-> Version
-> Text
-> (a -> Maybe Text)
-> (Maybe RemoteSpanContext -> IO a)
-> IO a
spanMirrorEnqueue ::
forall a.
PackageName ->
Version ->
Text ->
(a -> Maybe Text) ->
(Maybe RemoteSpanContext -> IO a) ->
IO a
, TracingPort -> forall a. PackageName -> IO a -> IO a
spanPackumentGate ::
forall a.
PackageName ->
IO a ->
IO a
, TracingPort -> forall a. PackageName -> IO a -> IO a
spanMetadataFetch ::
forall a.
PackageName ->
IO a ->
IO a
, TracingPort -> forall a. PackageName -> IO a -> IO a
spanMetadataDecode ::
forall a.
PackageName ->
IO a ->
IO a
}
newtype WorkerTracingPort = WorkerTracingPort
{ WorkerTracingPort
-> forall a.
PackageName
-> Version
-> Maybe RemoteSpanContext
-> (a -> JobSpanOutcome)
-> IO a
-> IO a
wtpMirrorJobSpan ::
forall a.
PackageName ->
Version ->
Maybe RemoteSpanContext ->
(a -> JobSpanOutcome) ->
IO a ->
IO a
}
data JobSpanOutcome = JobSpanOutcome
{ JobSpanOutcome -> Text
jobSpanLabel :: Text
, JobSpanOutcome -> Maybe Text
jobSpanError :: Maybe Text
}
deriving stock (JobSpanOutcome -> JobSpanOutcome -> Bool
(JobSpanOutcome -> JobSpanOutcome -> Bool)
-> (JobSpanOutcome -> JobSpanOutcome -> Bool) -> Eq JobSpanOutcome
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: JobSpanOutcome -> JobSpanOutcome -> Bool
== :: JobSpanOutcome -> JobSpanOutcome -> Bool
$c/= :: JobSpanOutcome -> JobSpanOutcome -> Bool
/= :: JobSpanOutcome -> JobSpanOutcome -> Bool
Eq, Int -> JobSpanOutcome -> ShowS
[JobSpanOutcome] -> ShowS
JobSpanOutcome -> String
(Int -> JobSpanOutcome -> ShowS)
-> (JobSpanOutcome -> String)
-> ([JobSpanOutcome] -> ShowS)
-> Show JobSpanOutcome
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> JobSpanOutcome -> ShowS
showsPrec :: Int -> JobSpanOutcome -> ShowS
$cshow :: JobSpanOutcome -> String
show :: JobSpanOutcome -> String
$cshowList :: [JobSpanOutcome] -> ShowS
showList :: [JobSpanOutcome] -> ShowS
Show)
newtype AdvisorySyncTracingPort = AdvisorySyncTracingPort
{ AdvisorySyncTracingPort
-> forall a. Ecosystem -> (a -> AdvisorySyncResult) -> IO a -> IO a
astpSyncAttemptSpan ::
forall a.
Ecosystem ->
(a -> AdvisorySyncResult) ->
IO a ->
IO a
}
ecluseScope :: (IsString s) => s
ecluseScope :: forall s. IsString s => s
ecluseScope = s
"ecluse"
withOptionalSpan :: (MonadUnliftIO m) => Maybe TracerProvider -> SpanKind -> Text -> (Maybe Span -> m a) -> m a
withOptionalSpan :: forall (m :: * -> *) a.
MonadUnliftIO m =>
Maybe TracerProvider
-> SpanKind -> Text -> (Maybe Span -> m a) -> m a
withOptionalSpan Maybe TracerProvider
mTracerProvider SpanKind
spanKind Text
name =
m (Maybe Span)
-> (Maybe Span -> m ()) -> (Maybe Span -> m a) -> m a
forall (m :: * -> *) a b c.
MonadUnliftIO m =>
m a -> (a -> m b) -> (a -> m c) -> m c
bracket (Maybe TracerProvider -> SpanKind -> Text -> m (Maybe Span)
forall (m :: * -> *).
MonadIO m =>
Maybe TracerProvider -> SpanKind -> Text -> m (Maybe Span)
openOptionalSpan Maybe TracerProvider
mTracerProvider SpanKind
spanKind Text
name) Maybe Span -> m ()
forall (m :: * -> *). MonadIO m => Maybe Span -> m ()
closeOptionalSpan
openOptionalSpan :: (MonadIO m) => Maybe TracerProvider -> SpanKind -> Text -> m (Maybe Span)
openOptionalSpan :: forall (m :: * -> *).
MonadIO m =>
Maybe TracerProvider -> SpanKind -> Text -> m (Maybe Span)
openOptionalSpan Maybe TracerProvider
mTracerProvider SpanKind
spanKind Text
name = case Maybe TracerProvider
mTracerProvider of
Maybe TracerProvider
Nothing -> Maybe Span -> m (Maybe Span)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Span
forall a. Maybe a
Nothing
Just TracerProvider
tracerProvider ->
let tracer :: Tracer
tracer = TracerProvider -> InstrumentationLibrary -> TracerOptions -> Tracer
makeTracer TracerProvider
tracerProvider InstrumentationLibrary
forall s. IsString s => s
ecluseScope TracerOptions
tracerOptions
in Span -> Maybe Span
forall a. a -> Maybe a
Just (Span -> Maybe Span) -> m Span -> m (Maybe Span)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Tracer -> Context -> Text -> SpanArguments -> m Span
forall (m :: * -> *).
(MonadIO m, HasCallStack) =>
Tracer -> Context -> Text -> SpanArguments -> m Span
createSpan Tracer
tracer Context
Ctx.empty Text
name SpanArguments
defaultSpanArguments{kind = spanKind}
closeOptionalSpan :: (MonadIO m) => Maybe Span -> m ()
closeOptionalSpan :: forall (m :: * -> *). MonadIO m => Maybe Span -> m ()
closeOptionalSpan Maybe Span
mSpan = Maybe Span -> (Span -> m ()) -> m ()
forall (f :: * -> *) a.
Applicative f =>
Maybe a -> (a -> f ()) -> f ()
whenJust Maybe Span
mSpan (Span -> Maybe Timestamp -> m ()
forall (m :: * -> *). MonadIO m => Span -> Maybe Timestamp -> m ()
`endSpan` Maybe Timestamp
forall a. Maybe a
Nothing)