packages feed

lightstep-haskell-0.1.0: src/LightStep/GlobalSharedMutableSingleton.hs

module LightStep.GlobalSharedMutableSingleton where

import Control.Concurrent.Async
import Control.Concurrent.STM
import Control.Monad.Catch
import Control.Monad.Except
import LightStep.Internal.Debug
import LightStep.LowLevel
import System.IO.Unsafe

{-# NOINLINE globalSharedMutableSingletonState #-}
globalSharedMutableSingletonState :: TBQueue Span
globalSharedMutableSingletonState = unsafePerformIO $ newTBQueueIO 100

withSingletonLightStep :: LightStepConfig -> IO () -> IO ()
withSingletonLightStep cfg action =
  race_ (action >> waitUntilQueueIsEmpty) $ do
    let work client = do
          d_ "Getting more spans"
          spans <- liftIO $ atomically $ do
            x <- readTBQueue globalSharedMutableSingletonState
            xs <- flushTBQueue globalSharedMutableSingletonState
            pure (x : xs)
          d_ $ "Got " <> show (length spans) <> " spans"
          reportSpans client spans
          d_ $ "Reported " <> show (length spans) <> " spans"
        shutdown client = do
          d_ "Getting the last spans before shutdown"
          spans <- liftIO $ atomically $ flushTBQueue globalSharedMutableSingletonState
          d_ $ "Got " <> show (length spans) <> " spans"
          when (not $ null spans) $
            reportSpans client spans
          d_ $ "Reported " <> show (length spans) <> " spans"
          closeClient client
          d_ "Client closed"
    runExceptT
      $ bracket
        (mkClient cfg)
        shutdown
      $ \client -> do
        let loop = do
              work client
              loop
        loop
    pure ()

submitSpan :: Span -> IO ()
submitSpan = atomically . writeTBQueue globalSharedMutableSingletonState

-- TODO: handle span batches larger that queue size
submitSpans :: Foldable f => f Span -> IO ()
submitSpans = atomically . mapM_ (writeTBQueue globalSharedMutableSingletonState)

waitUntilQueueIsEmpty :: IO ()
waitUntilQueueIsEmpty = atomically $ do
  e <- isEmptyTBQueue globalSharedMutableSingletonState
  when (not e) retry