Skip to content

Commit

Permalink
Make Trace a dynamically dispatched effect (#14)
Browse files Browse the repository at this point in the history
* Make Trace a dynamically dispatched effect

After some thinking I decided that `Trace` should be dynamic since currently it
has two interpretations crammed into it based on whether the `Scope` is there or
not (another design flaw of the original library). I also renamed `Tracing` to
`Trace` to keep naming consistent with TraceT and MonadTrace.

I also don't think `addSpanEntry` should do anything in the no-op handler.

* Rename

* Remove withZipkin and runZipkinTrace

withZipkin is Monitor.Tracing.Zipkin.with and runZipkinTrace is somewhat unnecessary.
  • Loading branch information
arybczak authored Sep 5, 2024
1 parent e5dcfc1 commit 1bbe357
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 80 deletions.
63 changes: 63 additions & 0 deletions tracing-effectful/src/Effectful/Trace.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Effectful.Trace
(
-- * Effect
Trace

-- * Handler
, runTrace
, runNoTrace

-- * Reexport
, module Monitor.Tracing
) where

import Control.Monad.Trace
import Control.Monad.Trace.Class
import Effectful
import Effectful.Dispatch.Dynamic
import Effectful.Reader.Static
import Monitor.Tracing

-- | Provides the ability to send traces to a backend.
data Trace :: Effect where
Trace :: Builder -> m a -> Trace m a
ActiveSpan :: Trace m (Maybe Span)
AddSpanEntry :: Key -> Value -> Trace m ()

type instance DispatchOf Trace = Dynamic

-- | Run the 'Trace' effect.
--
-- /Note:/ this is the @effectful@ version of 'runTraceT'.
runTrace
:: IOE :> es
=> Tracer
-> Eff (Trace : es) a
-> Eff es a
runTrace tracer = reinterpret (runReader initialScope) $ \env -> \case
Trace bldr action -> localSeqUnlift env $ \unlift -> do
scope <- ask
withSeqEffToIO $ \runInIO -> do
traceWith bldr scope $ \childScope -> do
runInIO . local (const childScope) $ unlift action
ActiveSpan -> asks scopeSpan
AddSpanEntry key value -> do
scope <- ask
liftIO $ addSpanEntryWith (Just scope) key value
where
initialScope = Scope tracer Nothing Nothing Nothing

-- | Run the 'Trace' effect with a dummy handler that does no tracing.
runNoTrace :: IOE :> es => Eff (Trace : es) a -> Eff es a
runNoTrace = interpret $ \env -> \case
Trace _ action -> localSeqUnlift env $ \unlift -> unlift action
ActiveSpan -> pure Nothing
AddSpanEntry _ _ -> pure ()

-- | Orphan, canonical instance.
instance Trace :> es => MonadTrace (Eff es) where
trace bldr action = send (Trace bldr action)
activeSpan = send ActiveSpan
addSpanEntry key value = send (AddSpanEntry key value)
79 changes: 0 additions & 79 deletions tracing-effectful/src/Effectful/Tracing.hs

This file was deleted.

3 changes: 2 additions & 1 deletion tracing-effectful/tracing-effectful.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ common language
default-extensions:
DataKinds
FlexibleContexts
GADTs
KindSignatures
LambdaCase
TypeFamilies
TypeOperators

library
import: language
exposed-modules: Effectful.Tracing
exposed-modules: Effectful.Trace
build-depends:
, base <5
, effectful-core >=1.0.0.0 && <3.0.0.0
Expand Down

0 comments on commit 1bbe357

Please sign in to comment.