{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Instana.SDK.Span.SpanData
( SpanData (SpanData)
, Annotation (..)
, AnnotationValue (..)
, empty
, listAnnotation
, listValue
, merge
, nullAnnotation
, objectAnnotation
, optionalAnnotation
, optionalValue
, simpleAnnotation
, simpleValue
, singleAnnotation
) where
import Data.Aeson (KeyValue, ToJSON, Value, (.=))
import qualified Data.Aeson as Aeson
import qualified Data.List as L
import qualified Data.Maybe as Maybe
import Data.Text (Text)
import qualified Data.Vector as V
import GHC.Generics
import Instana.SDK.Internal.Util ((|>))
data SpanData =
SpanData [Annotation]
deriving (SpanData -> SpanData -> Bool
(SpanData -> SpanData -> Bool)
-> (SpanData -> SpanData -> Bool) -> Eq SpanData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SpanData -> SpanData -> Bool
$c/= :: SpanData -> SpanData -> Bool
== :: SpanData -> SpanData -> Bool
$c== :: SpanData -> SpanData -> Bool
Eq, (forall x. SpanData -> Rep SpanData x)
-> (forall x. Rep SpanData x -> SpanData) -> Generic SpanData
forall x. Rep SpanData x -> SpanData
forall x. SpanData -> Rep SpanData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SpanData x -> SpanData
$cfrom :: forall x. SpanData -> Rep SpanData x
Generic, Int -> SpanData -> ShowS
[SpanData] -> ShowS
SpanData -> String
(Int -> SpanData -> ShowS)
-> (SpanData -> String) -> ([SpanData] -> ShowS) -> Show SpanData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SpanData] -> ShowS
$cshowList :: [SpanData] -> ShowS
show :: SpanData -> String
$cshow :: SpanData -> String
showsPrec :: Int -> SpanData -> ShowS
$cshowsPrec :: Int -> SpanData -> ShowS
Show)
instance ToJSON SpanData where
toJSON :: SpanData -> Value
toJSON :: SpanData -> Value
toJSON (SpanData annotations :: [Annotation]
annotations) =
[Pair] -> Value
Aeson.object ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$
(Annotation -> Maybe Pair) -> [Annotation] -> [Maybe Pair]
forall a b. (a -> b) -> [a] -> [b]
map Annotation -> Maybe Pair
forall kv. KeyValue kv => Annotation -> Maybe kv
annotationToJson [Annotation]
annotations
[Maybe Pair] -> ([Maybe Pair] -> [Pair]) -> [Pair]
forall a b. a -> (a -> b) -> b
|> [Maybe Pair] -> [Pair]
forall a. [Maybe a] -> [a]
Maybe.catMaybes
empty :: SpanData
empty :: SpanData
empty = [Annotation] -> SpanData
SpanData []
merge :: Annotation -> SpanData -> SpanData
merge :: Annotation -> SpanData -> SpanData
merge newAnnotation :: Annotation
newAnnotation (SpanData existingAnnotations :: [Annotation]
existingAnnotations) =
[Annotation] -> SpanData
SpanData ([Annotation] -> SpanData) -> [Annotation] -> SpanData
forall a b. (a -> b) -> a -> b
$ Annotation -> [Annotation] -> [Annotation]
mergeAnnotation Annotation
newAnnotation [Annotation]
existingAnnotations
mergeAnnotation :: Annotation -> [Annotation] -> [Annotation]
mergeAnnotation :: Annotation -> [Annotation] -> [Annotation]
mergeAnnotation newAnnotation :: Annotation
newAnnotation existingAnnotations :: [Annotation]
existingAnnotations =
let
key :: Text
key =
Annotation -> Text
getKey Annotation
newAnnotation
existingAnnotationForKeyMaybe :: Maybe Annotation
existingAnnotationForKeyMaybe =
(Annotation -> Bool) -> [Annotation] -> Maybe Annotation
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
L.find ((Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
key) (Text -> Bool) -> (Annotation -> Text) -> Annotation -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Annotation -> Text
getKey) [Annotation]
existingAnnotations
in
case Maybe Annotation
existingAnnotationForKeyMaybe of
Nothing ->
[Annotation]
existingAnnotations [Annotation] -> [Annotation] -> [Annotation]
forall a. [a] -> [a] -> [a]
++ [Annotation
newAnnotation]
Just existingAnnotationForKey :: Annotation
existingAnnotationForKey ->
let
annotationsWithoutPrevious :: [Annotation]
annotationsWithoutPrevious =
(Annotation -> [Annotation] -> [Annotation]
forall a. Eq a => a -> [a] -> [a]
L.delete Annotation
existingAnnotationForKey [Annotation]
existingAnnotations)
in
case (Annotation
existingAnnotationForKey, Annotation
newAnnotation) of
(Single _ (List values1 :: [Value]
values1), Single _ (List values2 :: [Value]
values2)) ->
[Annotation]
annotationsWithoutPrevious [Annotation] -> [Annotation] -> [Annotation]
forall a. [a] -> [a] -> [a]
++
[Text -> AnnotationValue -> Annotation
Single Text
key (AnnotationValue -> Annotation) -> AnnotationValue -> Annotation
forall a b. (a -> b) -> a -> b
$ [Value] -> AnnotationValue
List ([Value] -> AnnotationValue) -> [Value] -> AnnotationValue
forall a b. (a -> b) -> a -> b
$ [Value]
values1 [Value] -> [Value] -> [Value]
forall a. [a] -> [a] -> [a]
++ [Value]
values2]
(Single _ _, _) ->
[Annotation]
annotationsWithoutPrevious [Annotation] -> [Annotation] -> [Annotation]
forall a. [a] -> [a] -> [a]
++ [Annotation
newAnnotation]
(_, Single _ _) ->
[Annotation]
annotationsWithoutPrevious [Annotation] -> [Annotation] -> [Annotation]
forall a. [a] -> [a] -> [a]
++ [Annotation
newAnnotation]
(Object _ previousChildren :: [Annotation]
previousChildren, Object _ newChildren :: [Annotation]
newChildren) ->
let
mergedChildAnnotations :: [Annotation]
mergedChildAnnotations =
(Annotation -> [Annotation] -> [Annotation])
-> [Annotation] -> [Annotation] -> [Annotation]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
L.foldr
Annotation -> [Annotation] -> [Annotation]
mergeAnnotation
[Annotation]
previousChildren
[Annotation]
newChildren
in
[Annotation]
annotationsWithoutPrevious [Annotation] -> [Annotation] -> [Annotation]
forall a. [a] -> [a] -> [a]
++ [Text -> [Annotation] -> Annotation
Object Text
key [Annotation]
mergedChildAnnotations]
data Annotation =
Object Text [Annotation]
| Single Text AnnotationValue
deriving (Annotation -> Annotation -> Bool
(Annotation -> Annotation -> Bool)
-> (Annotation -> Annotation -> Bool) -> Eq Annotation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Annotation -> Annotation -> Bool
$c/= :: Annotation -> Annotation -> Bool
== :: Annotation -> Annotation -> Bool
$c== :: Annotation -> Annotation -> Bool
Eq, (forall x. Annotation -> Rep Annotation x)
-> (forall x. Rep Annotation x -> Annotation) -> Generic Annotation
forall x. Rep Annotation x -> Annotation
forall x. Annotation -> Rep Annotation x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Annotation x -> Annotation
$cfrom :: forall x. Annotation -> Rep Annotation x
Generic, Int -> Annotation -> ShowS
[Annotation] -> ShowS
Annotation -> String
(Int -> Annotation -> ShowS)
-> (Annotation -> String)
-> ([Annotation] -> ShowS)
-> Show Annotation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Annotation] -> ShowS
$cshowList :: [Annotation] -> ShowS
show :: Annotation -> String
$cshow :: Annotation -> String
showsPrec :: Int -> Annotation -> ShowS
$cshowsPrec :: Int -> Annotation -> ShowS
Show)
annotationToJson :: forall kv . KeyValue kv => Annotation -> Maybe kv
annotationToJson :: Annotation -> Maybe kv
annotationToJson annotation :: Annotation
annotation =
case Annotation
annotation of
Object key :: Text
key childAnnotations :: [Annotation]
childAnnotations ->
let
object :: Value
object :: Value
object =
[Pair] -> Value
Aeson.object ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$
(Annotation -> Maybe Pair) -> [Annotation] -> [Maybe Pair]
forall a b. (a -> b) -> [a] -> [b]
map Annotation -> Maybe Pair
forall kv. KeyValue kv => Annotation -> Maybe kv
annotationToJson [Annotation]
childAnnotations [Maybe Pair] -> ([Maybe Pair] -> [Pair]) -> [Pair]
forall a b. a -> (a -> b) -> b
|> [Maybe Pair] -> [Pair]
forall a. [Maybe a] -> [a]
Maybe.catMaybes
keyValue :: kv
keyValue :: kv
keyValue = (Text
key Text -> Value -> kv
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Value
object)
in
kv -> Maybe kv
forall a. a -> Maybe a
Just kv
keyValue
Single _ (Optional Nothing) ->
Maybe kv
forall a. Maybe a
Nothing
Single key :: Text
key annotationValue :: AnnotationValue
annotationValue ->
let
pair :: kv
pair :: kv
pair = (Text
key Text -> Value -> kv
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= (AnnotationValue -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON AnnotationValue
annotationValue))
in
kv -> Maybe kv
forall a. a -> Maybe a
Just kv
pair
getKey :: Annotation -> Text
getKey :: Annotation -> Text
getKey (Object key :: Text
key _) = Text
key
getKey (Single key :: Text
key _) = Text
key
objectAnnotation :: Text -> [Annotation] -> Annotation
objectAnnotation :: Text -> [Annotation] -> Annotation
objectAnnotation key :: Text
key children :: [Annotation]
children = Text -> [Annotation] -> Annotation
Object Text
key [Annotation]
children
singleAnnotation :: Text -> AnnotationValue -> Annotation
singleAnnotation :: Text -> AnnotationValue -> Annotation
singleAnnotation key :: Text
key value :: AnnotationValue
value = Text -> AnnotationValue -> Annotation
Single Text
key AnnotationValue
value
simpleAnnotation :: ToJSON a => Text -> a -> Annotation
simpleAnnotation :: Text -> a -> Annotation
simpleAnnotation key :: Text
key = (Text -> AnnotationValue -> Annotation
Single Text
key) (AnnotationValue -> Annotation)
-> (a -> AnnotationValue) -> a -> Annotation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> AnnotationValue
forall a. ToJSON a => a -> AnnotationValue
simpleValue
listAnnotation :: ToJSON a => Text -> [a] -> Annotation
listAnnotation :: Text -> [a] -> Annotation
listAnnotation key :: Text
key = (Text -> AnnotationValue -> Annotation
Single Text
key) (AnnotationValue -> Annotation)
-> ([a] -> AnnotationValue) -> [a] -> Annotation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> AnnotationValue
forall a. ToJSON a => [a] -> AnnotationValue
listValue
optionalAnnotation :: ToJSON a => Text -> Maybe a -> Annotation
optionalAnnotation :: Text -> Maybe a -> Annotation
optionalAnnotation key :: Text
key = (Text -> AnnotationValue -> Annotation
Single Text
key) (AnnotationValue -> Annotation)
-> (Maybe a -> AnnotationValue) -> Maybe a -> Annotation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> AnnotationValue
forall a. ToJSON a => Maybe a -> AnnotationValue
optionalValue
nullAnnotation :: Text -> Annotation
nullAnnotation :: Text -> Annotation
nullAnnotation key :: Text
key = Text -> AnnotationValue -> Annotation
Single Text
key (AnnotationValue -> Annotation) -> AnnotationValue -> Annotation
forall a b. (a -> b) -> a -> b
$ Maybe Value -> AnnotationValue
Optional Maybe Value
forall a. Maybe a
Nothing
data AnnotationValue =
Simple Value
| List [Value]
| Optional (Maybe Value)
deriving (AnnotationValue -> AnnotationValue -> Bool
(AnnotationValue -> AnnotationValue -> Bool)
-> (AnnotationValue -> AnnotationValue -> Bool)
-> Eq AnnotationValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AnnotationValue -> AnnotationValue -> Bool
$c/= :: AnnotationValue -> AnnotationValue -> Bool
== :: AnnotationValue -> AnnotationValue -> Bool
$c== :: AnnotationValue -> AnnotationValue -> Bool
Eq, (forall x. AnnotationValue -> Rep AnnotationValue x)
-> (forall x. Rep AnnotationValue x -> AnnotationValue)
-> Generic AnnotationValue
forall x. Rep AnnotationValue x -> AnnotationValue
forall x. AnnotationValue -> Rep AnnotationValue x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AnnotationValue x -> AnnotationValue
$cfrom :: forall x. AnnotationValue -> Rep AnnotationValue x
Generic, Int -> AnnotationValue -> ShowS
[AnnotationValue] -> ShowS
AnnotationValue -> String
(Int -> AnnotationValue -> ShowS)
-> (AnnotationValue -> String)
-> ([AnnotationValue] -> ShowS)
-> Show AnnotationValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AnnotationValue] -> ShowS
$cshowList :: [AnnotationValue] -> ShowS
show :: AnnotationValue -> String
$cshow :: AnnotationValue -> String
showsPrec :: Int -> AnnotationValue -> ShowS
$cshowsPrec :: Int -> AnnotationValue -> ShowS
Show)
instance ToJSON AnnotationValue where
toJSON :: AnnotationValue -> Value
toJSON :: AnnotationValue -> Value
toJSON annotation :: AnnotationValue
annotation =
case AnnotationValue
annotation of
Simple value :: Value
value ->
Value
value
List values :: [Value]
values ->
Array -> Value
Aeson.Array (Array -> Value) -> Array -> Value
forall a b. (a -> b) -> a -> b
$ [Value] -> Array
forall a. [a] -> Vector a
V.fromList [Value]
values
Optional maybeValue :: Maybe Value
maybeValue ->
case Maybe Value
maybeValue of
Just value :: Value
value -> Value
value
Nothing -> Value
Aeson.Null
simpleValue :: ToJSON a => a -> AnnotationValue
simpleValue :: a -> AnnotationValue
simpleValue =
Value -> AnnotationValue
Simple (Value -> AnnotationValue) -> (a -> Value) -> a -> AnnotationValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON
listValue :: ToJSON a => [a] -> AnnotationValue
listValue :: [a] -> AnnotationValue
listValue =
[Value] -> AnnotationValue
List ([Value] -> AnnotationValue)
-> ([a] -> [Value]) -> [a] -> AnnotationValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Value) -> [a] -> [Value]
forall a b. (a -> b) -> [a] -> [b]
map a -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON
optionalValue :: ToJSON a => Maybe a -> AnnotationValue
optionalValue :: Maybe a -> AnnotationValue
optionalValue value :: Maybe a
value =
Maybe Value -> AnnotationValue
Optional (Maybe Value -> AnnotationValue) -> Maybe Value -> AnnotationValue
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON (a -> Value) -> Maybe a -> Maybe Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
value