opentracing-jaeger-0.2.0: src/OpenTracing/Jaeger/AgentReporter.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TemplateHaskell #-}
module OpenTracing.Jaeger.AgentReporter
( JaegerAgentOptions
, jaegerAgentOptions
, jaoServiceName
, jaoServiceTags
, jaoAddr
, jaoErrorLog
, defaultJaegerAgentAddr
, JaegerAgent
, newJaegerAgent
, closeJaegerAgent
, withJaegerAgent
, jaegerAgentReporter
, jaegerPropagation
)
where
import qualified Agent.Client as Thrift
import Control.Exception.Safe
import Control.Lens (makeLenses, view)
import Control.Monad.IO.Class
import Data.ByteString.Builder
import Data.Text (Text)
import qualified Data.Vector as Vector
import qualified Jaeger.Types as Thrift
import Network.Socket
import OpenTracing.Jaeger.Propagation (jaegerPropagation)
import OpenTracing.Jaeger.Thrift
import OpenTracing.Reporting (defaultErrorLog)
import OpenTracing.Span
import OpenTracing.Tags
import OpenTracing.Types
import qualified Pinch
import qualified Pinch.Client as Pinch
import qualified Pinch.Transport as Pinch
data JaegerAgent = JaegerAgent
{ envLocalProcess :: Thrift.Process
, envErrorLog :: Builder -> IO ()
, envClient :: JaegerClient
}
data JaegerClient = JaegerClient
{
jclClient :: Pinch.Client
, jclSocket :: Socket
}
instance Pinch.ThriftClient JaegerClient where
call JaegerClient{jclClient} = Pinch.call jclClient
data JaegerAgentOptions = JaegerAgentOptions
{ _jaoServiceName :: Text
, _jaoServiceTags :: Tags
, _jaoAddr :: Addr 'UDP
, _jaoErrorLog :: Builder -> IO ()
}
jaegerAgentOptions :: Text -> JaegerAgentOptions
jaegerAgentOptions srv = JaegerAgentOptions
{ _jaoServiceName = srv
, _jaoServiceTags = mempty
, _jaoAddr = defaultJaegerAgentAddr
, _jaoErrorLog = defaultErrorLog
}
defaultJaegerAgentAddr :: Addr 'UDP
defaultJaegerAgentAddr = UDPAddr "127.0.0.1" 6831
newJaegerAgent :: JaegerAgentOptions -> IO JaegerAgent
newJaegerAgent JaegerAgentOptions{..} =
let tproc = toThriftProcess _jaoServiceName _jaoServiceTags
in JaegerAgent tproc _jaoErrorLog <$> openAgentTransport _jaoAddr
closeJaegerAgent :: JaegerAgent -> IO ()
closeJaegerAgent JaegerAgent{envClient=JaegerClient{jclSocket}} =
handleAny (const (return ())) $
close jclSocket
withJaegerAgent
:: ( MonadIO m
, MonadMask m
)
=> JaegerAgentOptions
-> (JaegerAgent -> m a)
-> m a
withJaegerAgent opts =
bracket (liftIO $ newJaegerAgent opts) (liftIO . closeJaegerAgent)
openAgentTransport :: Addr 'UDP -> IO JaegerClient
openAgentTransport addr = do
AddrInfo{..} : _ <- getAddrInfo (Just defaultHints { addrSocketType = Datagram })
(Just . view addrHostName $ addr)
(Just . show . view addrPort $ addr)
sock <- socket addrFamily addrSocketType addrProtocol
connect sock addrAddress
channel <- Pinch.createChannel sock Pinch.unframedTransport Pinch.compactProtocol
return JaegerClient
{
jclClient = Pinch.client channel
, jclSocket = sock
}
jaegerAgentReporter :: MonadIO m => JaegerAgent -> FinishedSpan -> m ()
jaegerAgentReporter JaegerAgent{..} s = liftIO $ emit `catchAny` err
where
emit = Pinch.call envClient (Thrift.emitBatch batch)
batch = toThriftBatch envLocalProcess (Vector.singleton s)
err e = envErrorLog $ shortByteString "Jaeger Agent Thrift error: "
<> string8 (show e)
<> char8 '\n'
makeLenses ''JaegerAgentOptions