{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-|
Module : Instana.SDK.Span.Span
Description : A type for spans (entries, exits or intermediates).
-}
module Instana.SDK.Span.Span
( Span (Entry, Exit)
, SpanKind (EntryKind, ExitKind, IntermediateKind)
, traceId
, spanId
, spanKind
, parentId
, spanName
, timestamp
, errorCount
, addToErrorCount
, serviceName
, setServiceName
, spanData
, addRegisteredData
, addRegisteredDataAt
, addTag
, addTagAt
) where
import Data.Aeson (Value, (.=))
import qualified Data.Aeson as Aeson
import qualified Data.List as List
import Data.Text as T
import Data.Text (Text)
import GHC.Generics
import Instana.SDK.Internal.Id (Id)
import Instana.SDK.Span.EntrySpan (EntrySpan)
import qualified Instana.SDK.Span.EntrySpan as EntrySpan
import Instana.SDK.Span.ExitSpan (ExitSpan)
import qualified Instana.SDK.Span.ExitSpan as ExitSpan
-- |The span kind (entry, exit or intermediate).
data SpanKind =
-- |The monitored componenent receives a call.
EntryKind
-- |The monitored componenent calls something else.
| ExitKind
-- |An additional annotation that is added to the trace while a traced call
-- is being processed.
| IntermediateKind
deriving (Eq, Generic, Show)
-- |A span.
data Span =
Entry EntrySpan
| Exit ExitSpan
deriving (Eq, Generic, Show)
-- |Accessor for the trace ID.
traceId :: Span -> Id
traceId span_ =
case span_ of
Entry entry -> EntrySpan.traceId entry
Exit exit -> ExitSpan.traceId exit
-- |Accessor for the span ID.
spanId :: Span -> Id
spanId span_ =
case span_ of
Entry entry -> EntrySpan.spanId entry
Exit exit -> ExitSpan.spanId exit
-- |Parent span ID.
parentId :: Span -> Maybe Id
parentId span_ =
case span_ of
Entry entry -> EntrySpan.parentId entry
Exit exit -> Just $ ExitSpan.parentId exit
-- |Name of span.
spanName :: Span -> Text
spanName span_ =
case span_ of
Entry entry -> EntrySpan.spanName entry
Exit exit -> ExitSpan.spanName exit
-- |Kind of span.
spanKind :: Span -> SpanKind
spanKind span_ =
case span_ of
Entry _ -> EntryKind
Exit _ -> ExitKind
-- |Start time.
timestamp :: Span -> Int
timestamp span_ =
case span_ of
Entry entry -> EntrySpan.timestamp entry
Exit exit -> ExitSpan.timestamp exit
-- |Error count.
errorCount :: Span -> Int
errorCount span_ =
case span_ of
Entry entry -> EntrySpan.errorCount entry
Exit exit -> ExitSpan.errorCount exit
-- |Add to the error count.
addToErrorCount :: Int -> Span -> Span
addToErrorCount increment span_ =
case span_ of
Entry entry ->
Entry $ EntrySpan.addToErrorCount increment entry
Exit exit ->
Exit $ ExitSpan.addToErrorCount increment exit
-- |An optional attribute for overriding the name of the service in Instana.
serviceName :: Span -> Maybe Text
serviceName span_ =
case span_ of
Entry entry -> EntrySpan.serviceName entry
Exit exit -> ExitSpan.serviceName exit
-- |Override the name of the service for the associated call in Instana.
setServiceName :: Text -> Span -> Span
setServiceName serviceName_ span_ =
case span_ of
Entry entry ->
Entry $ EntrySpan.setServiceName serviceName_ entry
Exit exit ->
Exit $ ExitSpan.setServiceName serviceName_ exit
-- |Optional additional span data.
spanData :: Span -> Value
spanData span_ =
case span_ of
Entry entry -> EntrySpan.spanData entry
Exit exit -> ExitSpan.spanData exit
-- |Add a value to the span's custom tags section. This should be used for SDK
-- spans instead of addRegisteredData.
addTag :: Value -> Span -> Span
addTag value span_ =
addRegisteredDataAt "sdk.custom.tags" value span_
-- |Add a value to the given path to the span's custom tags section. This should
-- be used for SDK spans instead of addRegisteredDataAt.
addTagAt :: Aeson.ToJSON a => Text -> a -> Span -> Span
addTagAt path value span_ =
addRegisteredDataAt (T.concat ["sdk.custom.tags.", path]) value span_
-- |Add a value to the span's data section. This should only be used for
-- registered spans, not for SDK spans. For SDK spans, you should use addTag
-- instead.
addRegisteredData :: Value -> Span -> Span
addRegisteredData value span_ =
case span_ of
Entry entry -> Entry $ EntrySpan.addData value entry
Exit exit -> Exit $ ExitSpan.addData value exit
-- |Add a value at the given path to the span's data section. For SDK spans, you
-- should use addTagAt instead.
addRegisteredDataAt :: Aeson.ToJSON a => Text -> a -> Span -> Span
addRegisteredDataAt path value span_ =
let
pathSegments = T.splitOn "." path
newData = List.foldr
(\nextPathSegment accumulatedAesonValue ->
Aeson.object [
nextPathSegment .= accumulatedAesonValue
]
)
(Aeson.toJSON value)
pathSegments
in
addRegisteredData newData span_