module OpenTelemetry.Exporter.InMemory (
  inMemoryChannelExporter,
  inMemoryListExporter,
  module Control.Concurrent.Chan.Unagi,
) where

import Control.Concurrent.Async
import Control.Concurrent.Chan.Unagi
import Control.Monad.IO.Class
import Data.IORef
import OpenTelemetry.Processor
import OpenTelemetry.Trace.Core


{- | Access exported spans via a concurrently accessible channel that produces spans.
 The spans are exported in the order that the spans end.
-}
inMemoryChannelExporter :: (MonadIO m) => m (Processor, OutChan ImmutableSpan)
inMemoryChannelExporter :: forall (m :: * -> *).
MonadIO m =>
m (Processor, OutChan ImmutableSpan)
inMemoryChannelExporter = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
  (InChan ImmutableSpan
inChan, OutChan ImmutableSpan
outChan) <- forall a. IO (InChan a, OutChan a)
newChan
  let processor :: Processor
processor =
        Processor
          { processorOnStart :: IORef ImmutableSpan -> Context -> IO ()
processorOnStart = \IORef ImmutableSpan
_ Context
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
          , processorOnEnd :: IORef ImmutableSpan -> IO ()
processorOnEnd = \IORef ImmutableSpan
ref -> do
              forall a. InChan a -> a -> IO ()
writeChan InChan ImmutableSpan
inChan forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. IORef a -> IO a
readIORef IORef ImmutableSpan
ref
          , processorShutdown :: IO (Async ShutdownResult)
processorShutdown = do
              forall a. IO a -> IO (Async a)
async forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure ShutdownResult
ShutdownSuccess
          , processorForceFlush :: IO ()
processorForceFlush = forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
          }
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Processor
processor, OutChan ImmutableSpan
outChan)


{- | Access exported spans via a mutable reference to a list of spans. The spans
 are not guaranteed to be exported in a particular order.
-}
inMemoryListExporter :: (MonadIO m) => m (Processor, IORef [ImmutableSpan])
inMemoryListExporter :: forall (m :: * -> *).
MonadIO m =>
m (Processor, IORef [ImmutableSpan])
inMemoryListExporter = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
  IORef [ImmutableSpan]
listRef <- forall a. a -> IO (IORef a)
newIORef []
  let processor :: Processor
processor =
        Processor
          { processorOnStart :: IORef ImmutableSpan -> Context -> IO ()
processorOnStart = \IORef ImmutableSpan
_ Context
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
          , processorOnEnd :: IORef ImmutableSpan -> IO ()
processorOnEnd = \IORef ImmutableSpan
ref -> do
              ImmutableSpan
s <- forall a. IORef a -> IO a
readIORef IORef ImmutableSpan
ref
              forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef [ImmutableSpan]
listRef (\[ImmutableSpan]
l -> (ImmutableSpan
s forall a. a -> [a] -> [a]
: [ImmutableSpan]
l, ()))
          , processorShutdown :: IO (Async ShutdownResult)
processorShutdown = do
              forall a. IO a -> IO (Async a)
async forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure ShutdownResult
ShutdownSuccess
          , processorForceFlush :: IO ()
processorForceFlush = forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
          }
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Processor
processor, IORef [ImmutableSpan]
listRef)