{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module OpenTracing.Propagation
( TextMap
, Headers
, Propagation
, HasPropagation(..)
, Carrier(..)
, HasCarrier
, HasCarriers
, carrier
, inject
, extract
, otPropagation
, b3Propagation
, _OTTextMap
, _OTHeaders
, _B3TextMap
, _B3Headers
, _HeadersTextMap
, Rec ((:&), RNil)
, rappend, (<+>)
, rcast
)
where
import Control.Applicative ((<|>))
import Control.Lens
import Data.Bool (bool)
import Data.ByteString.Builder (toLazyByteString)
import qualified Data.CaseInsensitive as CI
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Maybe (catMaybes)
import Data.Monoid
import Data.Proxy
import Data.Text (Text, isPrefixOf, toLower)
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import qualified Data.Text.Read as Text
import Data.Vinyl
import Data.Word
import Network.HTTP.Types (Header)
import OpenTracing.Span
import OpenTracing.Types
import URI.ByteString (urlDecodeQuery, urlEncodeQuery)
type TextMap = HashMap Text Text
type = [Header]
type Propagation carriers = Rec Carrier carriers
class HasPropagation a p | a -> p where
propagation :: Getting r a (Propagation p)
instance HasPropagation (Propagation p) p where
propagation :: Getting r (Propagation p) (Propagation p)
propagation = Getting r (Propagation p) (Propagation p)
forall a. a -> a
id
newtype Carrier a = Carrier { Carrier a
-> forall (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p SpanContext (f SpanContext) -> p a (f a)
fromCarrier :: Prism' a SpanContext }
type HasCarrier c cs = c ∈ cs
type HasCarriers cs ds = cs ⊆ ds
carrier
:: ( HasCarrier c cs
, HasPropagation r cs
)
=> proxy c
-> r
-> Prism' c SpanContext
carrier :: proxy c -> r -> Prism' c SpanContext
carrier proxy c
_c = Carrier c -> p SpanContext (f SpanContext) -> p c (f c)
forall a.
Carrier a
-> forall (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p SpanContext (f SpanContext) -> p a (f a)
fromCarrier (Carrier c -> p SpanContext (f SpanContext) -> p c (f c))
-> (r -> Carrier c)
-> r
-> p SpanContext (f SpanContext)
-> p c (f c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting (Carrier c) r (Carrier c) -> r -> Carrier c
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting (Carrier c) r (Propagation cs)
forall a (p :: [*]) r.
HasPropagation a p =>
Getting r a (Propagation p)
propagation Getting (Carrier c) r (Propagation cs)
-> ((Carrier c -> Const (Carrier c) (Carrier c))
-> Propagation cs -> Const (Carrier c) (Propagation cs))
-> Getting (Carrier c) r (Carrier c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Carrier c -> Const (Carrier c) (Carrier c))
-> Propagation cs -> Const (Carrier c) (Propagation cs)
forall k (r :: k) (record :: (k -> *) -> [k] -> *) (rs :: [k])
(f :: k -> *) (g :: * -> *).
(RecElem record r r rs rs (RIndex r rs), RecElemFCtx record f,
Functor g) =>
(f r -> g (f r)) -> record f rs -> g (record f rs)
rlens)
inject
:: forall c r p.
( HasCarrier c p
, HasPropagation r p
)
=> r
-> SpanContext
-> c
inject :: r -> SpanContext -> c
inject r
r = AReview c SpanContext -> SpanContext -> c
forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review (Proxy c -> r -> Prism' c SpanContext
forall c (cs :: [*]) r (proxy :: * -> *).
(HasCarrier c cs, HasPropagation r cs) =>
proxy c -> r -> Prism' c SpanContext
carrier (Proxy c
forall k (t :: k). Proxy t
Proxy @c) r
r)
extract
:: forall c r p.
( HasCarrier c p
, HasPropagation r p
)
=> r
-> c
-> Maybe SpanContext
r
r = Getting (First SpanContext) c SpanContext -> c -> Maybe SpanContext
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview (Proxy c -> r -> Prism' c SpanContext
forall c (cs :: [*]) r (proxy :: * -> *).
(HasCarrier c cs, HasPropagation r cs) =>
proxy c -> r -> Prism' c SpanContext
carrier (Proxy c
forall k (t :: k). Proxy t
Proxy @c) r
r)
otPropagation :: Propagation '[TextMap, Headers]
otPropagation :: Propagation '[TextMap, Headers]
otPropagation = Prism' TextMap SpanContext -> Carrier TextMap
forall a.
(forall (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p SpanContext (f SpanContext) -> p a (f a))
-> Carrier a
Carrier Prism' TextMap SpanContext
_OTTextMap Carrier TextMap
-> Rec Carrier '[Headers] -> Propagation '[TextMap, Headers]
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Prism' Headers SpanContext -> Carrier Headers
forall a.
(forall (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p SpanContext (f SpanContext) -> p a (f a))
-> Carrier a
Carrier Prism' Headers SpanContext
_OTHeaders Carrier Headers -> Rec Carrier '[] -> Rec Carrier '[Headers]
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Rec Carrier '[]
forall u (a :: u -> *). Rec a '[]
RNil
b3Propagation :: Propagation '[TextMap, Headers]
b3Propagation :: Propagation '[TextMap, Headers]
b3Propagation = Prism' TextMap SpanContext -> Carrier TextMap
forall a.
(forall (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p SpanContext (f SpanContext) -> p a (f a))
-> Carrier a
Carrier Prism' TextMap SpanContext
_B3TextMap Carrier TextMap
-> Rec Carrier '[Headers] -> Propagation '[TextMap, Headers]
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Prism' Headers SpanContext -> Carrier Headers
forall a.
(forall (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p SpanContext (f SpanContext) -> p a (f a))
-> Carrier a
Carrier Prism' Headers SpanContext
_B3Headers Carrier Headers -> Rec Carrier '[] -> Rec Carrier '[Headers]
forall u (a :: u -> *) (r :: u) (rs :: [u]).
a r -> Rec a rs -> Rec a (r : rs)
:& Rec Carrier '[]
forall u (a :: u -> *). Rec a '[]
RNil
_OTTextMap :: Prism' TextMap SpanContext
_OTTextMap :: p SpanContext (f SpanContext) -> p TextMap (f TextMap)
_OTTextMap = (SpanContext -> TextMap)
-> (TextMap -> Maybe SpanContext) -> Prism' TextMap SpanContext
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' SpanContext -> TextMap
fromCtx TextMap -> Maybe SpanContext
toCtx
where
fromCtx :: SpanContext -> TextMap
fromCtx c :: SpanContext
c@SpanContext{Maybe Word64
Word64
TextMap
TraceID
Sampled
_ctxBaggage :: SpanContext -> TextMap
_ctxSampled :: SpanContext -> Sampled
ctxParentSpanID :: SpanContext -> Maybe Word64
ctxSpanID :: SpanContext -> Word64
ctxTraceID :: SpanContext -> TraceID
_ctxBaggage :: TextMap
_ctxSampled :: Sampled
ctxParentSpanID :: Maybe Word64
ctxSpanID :: Word64
ctxTraceID :: TraceID
..} = [(Text, Text)] -> TextMap
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList ([(Text, Text)] -> TextMap) -> [(Text, Text)] -> TextMap
forall a b. (a -> b) -> a -> b
$
(Text
"ot-tracer-traceid", Getting Text TraceID Text -> TraceID -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text TraceID Text
forall a. AsHex a => Getter a Text
hexText TraceID
ctxTraceID)
(Text, Text) -> [(Text, Text)] -> [(Text, Text)]
forall a. a -> [a] -> [a]
: (Text
"ot-tracer-spanid" , Getting Text Word64 Text -> Word64 -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Word64 Text
forall a. AsHex a => Getter a Text
hexText Word64
ctxSpanID)
(Text, Text) -> [(Text, Text)] -> [(Text, Text)]
forall a. a -> [a] -> [a]
: (Text
"ot-tracer-sampled", Getting Text SpanContext Text -> SpanContext -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Sampled -> Const Text Sampled)
-> SpanContext -> Const Text SpanContext
Lens' SpanContext Sampled
ctxSampled ((Sampled -> Const Text Sampled)
-> SpanContext -> Const Text SpanContext)
-> ((Text -> Const Text Text) -> Sampled -> Const Text Sampled)
-> Getting Text SpanContext Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AReview Text Sampled -> Getter Sampled Text
forall t b. AReview t b -> Getter b t
re AReview Text Sampled
Prism' Text Sampled
_OTSampled) SpanContext
c)
(Text, Text) -> [(Text, Text)] -> [(Text, Text)]
forall a. a -> [a] -> [a]
: ((Text, Text) -> (Text, Text)) -> [(Text, Text)] -> [(Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map (ASetter (Text, Text) (Text, Text) Text Text
-> (Text -> Text) -> (Text, Text) -> (Text, Text)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter (Text, Text) (Text, Text) Text Text
forall s t a b. Field1 s t a b => Lens s t a b
_1 (Text
"ot-baggage-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)) (TextMap -> [(Text, Text)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList TextMap
_ctxBaggage)
toCtx :: TextMap -> Maybe SpanContext
toCtx TextMap
m = TraceID
-> Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext
SpanContext
(TraceID
-> Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext)
-> Maybe TraceID
-> Maybe
(Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text -> TextMap -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
"ot-tracer-traceid" TextMap
m Maybe Text -> (Text -> Maybe TraceID) -> Maybe TraceID
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Getting (First TraceID) Hex TraceID -> Hex -> Maybe TraceID
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview Getting (First TraceID) Hex TraceID
forall a. AsHex a => Prism' Hex a
_Hex (Hex -> Maybe TraceID) -> (Text -> Hex) -> Text -> Maybe TraceID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Hex
knownHex)
Maybe (Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext)
-> Maybe Word64
-> Maybe (Maybe Word64 -> Sampled -> TextMap -> SpanContext)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Text -> TextMap -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
"ot-tracer-spanid" TextMap
m Maybe Text -> (Text -> Maybe Word64) -> Maybe Word64
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Getting (First Word64) Hex Word64 -> Hex -> Maybe Word64
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview Getting (First Word64) Hex Word64
forall a. AsHex a => Prism' Hex a
_Hex (Hex -> Maybe Word64) -> (Text -> Hex) -> Text -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Hex
knownHex)
Maybe (Maybe Word64 -> Sampled -> TextMap -> SpanContext)
-> Maybe (Maybe Word64)
-> Maybe (Sampled -> TextMap -> SpanContext)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Word64 -> Maybe (Maybe Word64)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Word64
forall a. Maybe a
Nothing
Maybe (Sampled -> TextMap -> SpanContext)
-> Maybe Sampled -> Maybe (TextMap -> SpanContext)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Text -> TextMap -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
"ot-tracer-sampled" TextMap
m Maybe Text -> (Text -> Maybe Sampled) -> Maybe Sampled
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Getting (First Sampled) Text Sampled -> Text -> Maybe Sampled
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview Getting (First Sampled) Text Sampled
Prism' Text Sampled
_OTSampled)
Maybe (TextMap -> SpanContext)
-> Maybe TextMap -> Maybe SpanContext
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TextMap -> Maybe TextMap
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Text -> Text -> Bool) -> TextMap -> TextMap
forall k v. (k -> v -> Bool) -> HashMap k v -> HashMap k v
HashMap.filterWithKey (\Text
k Text
_ -> Text
"ot-baggage-" Text -> Text -> Bool
`isPrefixOf` Text
k) TextMap
m)
_OTHeaders :: Prism' Headers SpanContext
= p TextMap (f TextMap) -> p Headers (f Headers)
Iso' Headers TextMap
_HeadersTextMap (p TextMap (f TextMap) -> p Headers (f Headers))
-> (p SpanContext (f SpanContext) -> p TextMap (f TextMap))
-> p SpanContext (f SpanContext)
-> p Headers (f Headers)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p SpanContext (f SpanContext) -> p TextMap (f TextMap)
Prism' TextMap SpanContext
_OTTextMap
_OTSampled :: Prism' Text Sampled
_OTSampled :: p Sampled (f Sampled) -> p Text (f Text)
_OTSampled = (Sampled -> Text) -> (Text -> Maybe Sampled) -> Prism' Text Sampled
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' Sampled -> Text
enc Text -> Maybe Sampled
dec
where
enc :: Sampled -> Text
enc = \case Sampled
Sampled -> Text
"1"
Sampled
_ -> Text
"0"
dec :: Text -> Maybe Sampled
dec = (String -> Maybe Sampled)
-> (Maybe Sampled -> Maybe Sampled)
-> Either String (Maybe Sampled)
-> Maybe Sampled
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe Sampled -> String -> Maybe Sampled
forall a b. a -> b -> a
const Maybe Sampled
forall a. Maybe a
Nothing) Maybe Sampled -> Maybe Sampled
forall a. a -> a
id
(Either String (Maybe Sampled) -> Maybe Sampled)
-> (Text -> Either String (Maybe Sampled)) -> Text -> Maybe Sampled
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Word8, Text) -> Maybe Sampled)
-> Either String (Word8, Text) -> Either String (Maybe Sampled)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Word8
x,Text
_) -> Sampled -> Maybe Sampled
forall a. a -> Maybe a
Just (Sampled -> Maybe Sampled) -> Sampled -> Maybe Sampled
forall a b. (a -> b) -> a -> b
$ if Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== (Word8
1 :: Word8) then Sampled
Sampled else Sampled
NotSampled)
(Either String (Word8, Text) -> Either String (Maybe Sampled))
-> (Text -> Either String (Word8, Text))
-> Text
-> Either String (Maybe Sampled)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either String (Word8, Text)
forall a. Integral a => Reader a
Text.decimal
_B3TextMap :: Prism' TextMap SpanContext
_B3TextMap :: p SpanContext (f SpanContext) -> p TextMap (f TextMap)
_B3TextMap = (SpanContext -> TextMap)
-> (TextMap -> Maybe SpanContext) -> Prism' TextMap SpanContext
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' SpanContext -> TextMap
fromCtx TextMap -> Maybe SpanContext
toCtx
where
fromCtx :: SpanContext -> TextMap
fromCtx ctx :: SpanContext
ctx@SpanContext{Maybe Word64
Word64
TextMap
TraceID
Sampled
_ctxBaggage :: TextMap
_ctxSampled :: Sampled
ctxParentSpanID :: Maybe Word64
ctxSpanID :: Word64
ctxTraceID :: TraceID
_ctxBaggage :: SpanContext -> TextMap
_ctxSampled :: SpanContext -> Sampled
ctxParentSpanID :: SpanContext -> Maybe Word64
ctxSpanID :: SpanContext -> Word64
ctxTraceID :: SpanContext -> TraceID
..} = [(Text, Text)] -> TextMap
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList ([(Text, Text)] -> TextMap)
-> ([Maybe (Text, Text)] -> [(Text, Text)])
-> [Maybe (Text, Text)]
-> TextMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe (Text, Text)] -> [(Text, Text)]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (Text, Text)] -> TextMap)
-> [Maybe (Text, Text)] -> TextMap
forall a b. (a -> b) -> a -> b
$
(Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just (Text
"x-b3-traceid", Getting Text TraceID Text -> TraceID -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text TraceID Text
forall a. AsHex a => Getter a Text
hexText TraceID
ctxTraceID)
Maybe (Text, Text) -> [Maybe (Text, Text)] -> [Maybe (Text, Text)]
forall a. a -> [a] -> [a]
: (Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just (Text
"x-b3-spanid" , Getting Text Word64 Text -> Word64 -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Word64 Text
forall a. AsHex a => Getter a Text
hexText Word64
ctxSpanID)
Maybe (Text, Text) -> [Maybe (Text, Text)] -> [Maybe (Text, Text)]
forall a. a -> [a] -> [a]
: (Word64 -> (Text, Text)) -> Maybe Word64 -> Maybe (Text, Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Text
"x-b3-parentspanid",) (Text -> (Text, Text))
-> (Word64 -> Text) -> Word64 -> (Text, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Text Word64 Text -> Word64 -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Word64 Text
forall a. AsHex a => Getter a Text
hexText) Maybe Word64
ctxParentSpanID
Maybe (Text, Text) -> [Maybe (Text, Text)] -> [Maybe (Text, Text)]
forall a. a -> [a] -> [a]
: (Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just (Text
"x-b3-sampled", Text -> Text -> Bool -> Text
forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" (Bool -> Text) -> Bool -> Text
forall a b. (a -> b) -> a -> b
$ Getting Bool SpanContext Bool -> SpanContext -> Bool
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Sampled -> Const Bool Sampled)
-> SpanContext -> Const Bool SpanContext
Lens' SpanContext Sampled
ctxSampled ((Sampled -> Const Bool Sampled)
-> SpanContext -> Const Bool SpanContext)
-> ((Bool -> Const Bool Bool) -> Sampled -> Const Bool Sampled)
-> Getting Bool SpanContext Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AReview Bool Sampled -> Getter Sampled Bool
forall t b. AReview t b -> Getter b t
re AReview Bool Sampled
Iso' Bool Sampled
_IsSampled) SpanContext
ctx)
Maybe (Text, Text) -> [Maybe (Text, Text)] -> [Maybe (Text, Text)]
forall a. a -> [a] -> [a]
: ((Text, Text) -> Maybe (Text, Text))
-> [(Text, Text)] -> [Maybe (Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map ((Text, Text) -> Maybe (Text, Text)
forall a. a -> Maybe a
Just ((Text, Text) -> Maybe (Text, Text))
-> ((Text, Text) -> (Text, Text))
-> (Text, Text)
-> Maybe (Text, Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ASetter (Text, Text) (Text, Text) Text Text
-> (Text -> Text) -> (Text, Text) -> (Text, Text)
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter (Text, Text) (Text, Text) Text Text
forall s t a b. Field1 s t a b => Lens s t a b
_1 (Text
"ot-baggage-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)) (TextMap -> [(Text, Text)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList TextMap
_ctxBaggage)
toCtx :: TextMap -> Maybe SpanContext
toCtx TextMap
m = TraceID
-> Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext
SpanContext
(TraceID
-> Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext)
-> Maybe TraceID
-> Maybe
(Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text -> TextMap -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
"x-b3-traceid" TextMap
m Maybe Text -> (Text -> Maybe TraceID) -> Maybe TraceID
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Getting (First TraceID) Hex TraceID -> Hex -> Maybe TraceID
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview Getting (First TraceID) Hex TraceID
forall a. AsHex a => Prism' Hex a
_Hex (Hex -> Maybe TraceID) -> (Text -> Hex) -> Text -> Maybe TraceID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Hex
knownHex)
Maybe (Word64 -> Maybe Word64 -> Sampled -> TextMap -> SpanContext)
-> Maybe Word64
-> Maybe (Maybe Word64 -> Sampled -> TextMap -> SpanContext)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Text -> TextMap -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
"x-b3-spanid" TextMap
m Maybe Text -> (Text -> Maybe Word64) -> Maybe Word64
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Getting (First Word64) Hex Word64 -> Hex -> Maybe Word64
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview Getting (First Word64) Hex Word64
forall a. AsHex a => Prism' Hex a
_Hex (Hex -> Maybe Word64) -> (Text -> Hex) -> Text -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Hex
knownHex)
Maybe (Maybe Word64 -> Sampled -> TextMap -> SpanContext)
-> Maybe (Maybe Word64)
-> Maybe (Sampled -> TextMap -> SpanContext)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Maybe Word64 -> Maybe (Maybe Word64)
forall a. a -> Maybe a
Just (Maybe Word64 -> Maybe (Maybe Word64))
-> Maybe Word64 -> Maybe (Maybe Word64)
forall a b. (a -> b) -> a -> b
$ Text -> TextMap -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup Text
"x-b3-parentspanid" TextMap
m Maybe Text -> (Text -> Maybe Word64) -> Maybe Word64
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Getting (First Word64) Hex Word64 -> Hex -> Maybe Word64
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview Getting (First Word64) Hex Word64
forall a. AsHex a => Prism' Hex a
_Hex (Hex -> Maybe Word64) -> (Text -> Hex) -> Text -> Maybe Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Hex
knownHex)
Maybe (Sampled -> TextMap -> SpanContext)
-> Maybe Sampled -> Maybe (TextMap -> SpanContext)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (TextMap -> Maybe Sampled
forall k a.
(Hashable k, Eq k, Eq a, IsString k, IsString a) =>
HashMap k a -> Maybe Sampled
b3Sampled TextMap
m Maybe Sampled -> Maybe Sampled -> Maybe Sampled
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> TextMap -> Maybe Sampled
forall k a.
(Hashable k, Eq k, Eq a, IsString k, IsString a) =>
HashMap k a -> Maybe Sampled
b3Debug TextMap
m Maybe Sampled -> Maybe Sampled -> Maybe Sampled
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Sampled -> Maybe Sampled
forall a. a -> Maybe a
Just Sampled
NotSampled)
Maybe (TextMap -> SpanContext)
-> Maybe TextMap -> Maybe SpanContext
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TextMap -> Maybe TextMap
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Text -> Text -> Bool) -> TextMap -> TextMap
forall k v. (k -> v -> Bool) -> HashMap k v -> HashMap k v
HashMap.filterWithKey (\Text
k Text
_ -> Text
"ot-baggage-" Text -> Text -> Bool
`isPrefixOf` Text
k) TextMap
m)
b3Sampled :: HashMap k a -> Maybe Sampled
b3Sampled HashMap k a
m = k -> HashMap k a -> Maybe a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup k
"x-b3-sampled" HashMap k a
m Maybe a -> (a -> Maybe Sampled) -> Maybe Sampled
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
a
"true" -> Sampled -> Maybe Sampled
forall a. a -> Maybe a
Just Sampled
Sampled
a
_ -> Maybe Sampled
forall a. Maybe a
Nothing
b3Debug :: HashMap k a -> Maybe Sampled
b3Debug HashMap k a
m = k -> HashMap k a -> Maybe a
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup k
"x-b3-flags" HashMap k a
m Maybe a -> (a -> Maybe Sampled) -> Maybe Sampled
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
a
"1" -> Sampled -> Maybe Sampled
forall a. a -> Maybe a
Just Sampled
Sampled
a
_ -> Maybe Sampled
forall a. Maybe a
Nothing
_B3Headers :: Prism' Headers SpanContext
= p TextMap (f TextMap) -> p Headers (f Headers)
Iso' Headers TextMap
_HeadersTextMap (p TextMap (f TextMap) -> p Headers (f Headers))
-> (p SpanContext (f SpanContext) -> p TextMap (f TextMap))
-> p SpanContext (f SpanContext)
-> p Headers (f Headers)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p SpanContext (f SpanContext) -> p TextMap (f TextMap)
Prism' TextMap SpanContext
_B3TextMap
_HeadersTextMap :: Iso' Headers TextMap
= (Headers -> TextMap)
-> (TextMap -> Headers) -> Iso' Headers TextMap
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso Headers -> TextMap
toTextMap TextMap -> Headers
toHeaders
where
toHeaders :: TextMap -> Headers
toHeaders
= ((Text, Text) -> (CI ByteString, ByteString))
-> [(Text, Text)] -> Headers
forall a b. (a -> b) -> [a] -> [b]
map ((Text -> CI ByteString)
-> (Text -> ByteString)
-> (Text, Text)
-> (CI ByteString, ByteString)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CI.mk (ByteString -> CI ByteString)
-> (Text -> ByteString) -> Text -> CI ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8)
(Getting ByteString ByteString ByteString
-> ByteString -> ByteString
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ByteString ByteString ByteString
forall lazy strict. Strict lazy strict => Iso' lazy strict
strict (ByteString -> ByteString)
-> (Text -> ByteString) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
toLazyByteString (Builder -> ByteString) -> (Text -> Builder) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
urlEncodeQuery (ByteString -> Builder) -> (Text -> ByteString) -> Text -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8))
([(Text, Text)] -> Headers)
-> (TextMap -> [(Text, Text)]) -> TextMap -> Headers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextMap -> [(Text, Text)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList
toTextMap :: Headers -> TextMap
toTextMap
= [(Text, Text)] -> TextMap
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList
([(Text, Text)] -> TextMap)
-> (Headers -> [(Text, Text)]) -> Headers -> TextMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((CI ByteString, ByteString) -> (Text, Text))
-> Headers -> [(Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map ((CI ByteString -> Text)
-> (ByteString -> Text)
-> (CI ByteString, ByteString)
-> (Text, Text)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (Text -> Text
toLower (Text -> Text) -> (CI ByteString -> Text) -> CI ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
decodeUtf8 (ByteString -> Text)
-> (CI ByteString -> ByteString) -> CI ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CI ByteString -> ByteString
forall s. CI s -> s
CI.original)
(ByteString -> Text
decodeUtf8 (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
urlDecodeQuery))