{-# LANGUAGE FlexibleContexts #-}
module Monitor.Tracing.Local (
collectSpanSamples
) where
import Control.Concurrent.STM (atomically, readTVar, readTChan, tryReadTChan)
import Control.Monad.Fix (fix)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Trace
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.IORef (modifyIORef', newIORef, readIORef)
collectSpanSamples :: (MonadIO m, MonadBaseControl IO m)
=> TraceT m a -> m (a, [Sample])
collectSpanSamples actn = do
tracer <- newTracer
rv <- runTraceT actn tracer
ref <- liftIO $ newIORef []
let
addSample spl = liftIO $ modifyIORef' ref (spl:)
samplesTC = spanSamples tracer
pendingTV = pendingSpanCount tracer
liftIO $ fix $ \loop -> do
(mbSample, pending) <- atomically $ (,) <$> tryReadTChan samplesTC <*> readTVar pendingTV
case mbSample of
Just spl -> addSample spl >> loop
Nothing | pending > 0 -> liftIO (atomically $ readTChan samplesTC) >>= addSample >> loop
_ -> pure ()
spls <- reverse <$> liftIO (readIORef ref)
pure (rv, spls)