{-# 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 :: TraceT m a -> m (a, [Sample])
collectSpanSamples TraceT m a
actn = do
Tracer
tracer <- m Tracer
forall (m :: * -> *). MonadIO m => m Tracer
newTracer
a
rv <- TraceT m a -> Tracer -> m a
forall (m :: * -> *) a. TraceT m a -> Tracer -> m a
runTraceT TraceT m a
actn Tracer
tracer
IORef [Sample]
ref <- IO (IORef [Sample]) -> m (IORef [Sample])
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef [Sample]) -> m (IORef [Sample]))
-> IO (IORef [Sample]) -> m (IORef [Sample])
forall a b. (a -> b) -> a -> b
$ [Sample] -> IO (IORef [Sample])
forall a. a -> IO (IORef a)
newIORef []
let
addSample :: Sample -> m ()
addSample Sample
spl = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef [Sample] -> ([Sample] -> [Sample]) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef [Sample]
ref (Sample
splSample -> [Sample] -> [Sample]
forall a. a -> [a] -> [a]
:)
samplesTC :: TChan Sample
samplesTC = Tracer -> TChan Sample
spanSamples Tracer
tracer
pendingTV :: TVar Int
pendingTV = Tracer -> TVar Int
pendingSpanCount Tracer
tracer
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ (IO () -> IO ()) -> IO ()
forall a. (a -> a) -> a
fix ((IO () -> IO ()) -> IO ()) -> (IO () -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \IO ()
loop -> do
(Maybe Sample
mbSample, Int
pending) <- STM (Maybe Sample, Int) -> IO (Maybe Sample, Int)
forall a. STM a -> IO a
atomically (STM (Maybe Sample, Int) -> IO (Maybe Sample, Int))
-> STM (Maybe Sample, Int) -> IO (Maybe Sample, Int)
forall a b. (a -> b) -> a -> b
$ (,) (Maybe Sample -> Int -> (Maybe Sample, Int))
-> STM (Maybe Sample) -> STM (Int -> (Maybe Sample, Int))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TChan Sample -> STM (Maybe Sample)
forall a. TChan a -> STM (Maybe a)
tryReadTChan TChan Sample
samplesTC STM (Int -> (Maybe Sample, Int))
-> STM Int -> STM (Maybe Sample, Int)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
pendingTV
case Maybe Sample
mbSample of
Just Sample
spl -> Sample -> IO ()
forall (m :: * -> *). MonadIO m => Sample -> m ()
addSample Sample
spl IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
loop
Maybe Sample
Nothing | Int
pending Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 -> IO Sample -> IO Sample
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (STM Sample -> IO Sample
forall a. STM a -> IO a
atomically (STM Sample -> IO Sample) -> STM Sample -> IO Sample
forall a b. (a -> b) -> a -> b
$ TChan Sample -> STM Sample
forall a. TChan a -> STM a
readTChan TChan Sample
samplesTC) IO Sample -> (Sample -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Sample -> IO ()
forall (m :: * -> *). MonadIO m => Sample -> m ()
addSample IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
loop
Maybe Sample
_ -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
[Sample]
spls <- [Sample] -> [Sample]
forall a. [a] -> [a]
reverse ([Sample] -> [Sample]) -> m [Sample] -> m [Sample]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [Sample] -> m [Sample]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IORef [Sample] -> IO [Sample]
forall a. IORef a -> IO a
readIORef IORef [Sample]
ref)
(a, [Sample]) -> m (a, [Sample])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
rv, [Sample]
spls)