{-# 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)
, addRegisteredData
, addRegisteredDataAt
, addTag
, addTagAt
, addToErrorCount
, correlationId
, correlationType
, errorCount
, parentId
, serviceName
, setCorrelationId
, setCorrelationType
, setServiceName
, setSynthetic
, setW3cTraceContext
, spanData
, setTpFlag
, spanId
, spanKind
, spanName
, synthetic
, timestamp
, tpFlag
, traceId
, w3cTraceContext
) where
import Data.Aeson (Value, (.=))
import qualified Data.Aeson as Aeson
import qualified Data.List as List
import Data.Text as T
import GHC.Generics
import Instana.SDK.Internal.Id (Id)
import Instana.SDK.Internal.W3CTraceContext (W3CTraceContext)
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
-- |The website monitoring correlation type.
correlationType :: Span -> Maybe Text
correlationType span_ =
case span_ of
Entry entry -> EntrySpan.correlationType entry
Exit _ -> Nothing
-- |Set the website monitoring correlation type. This should only be set on
-- root entry spans. It will be silently ignored for other types of spans.
setCorrelationType :: Text -> Span -> Span
setCorrelationType correlationType_ span_ =
case span_ of
Entry entry ->
Entry $ EntrySpan.setCorrelationType correlationType_ entry
Exit _ ->
span_
-- |The website monitoring correlation ID.
correlationId :: Span -> Maybe Text
correlationId span_ =
case span_ of
Entry entry -> EntrySpan.correlationId entry
Exit _ -> Nothing
-- |Set the website monitoring correlation ID. This should only be set on
-- root entry spans. It will be silently ignored for other types of spans.
setCorrelationId :: Text -> Span -> Span
setCorrelationId correlationId_ span_ =
case span_ of
Entry entry ->
Entry $ EntrySpan.setCorrelationId correlationId_ entry
Exit _ ->
span_
-- |The W3C Trace Context. An entry span only has an associated W3C trace
-- context, if W3C trace context headers have been received. In contrast,
-- exit spans always have an associated W3C trace context.
w3cTraceContext :: Span -> Maybe W3CTraceContext
w3cTraceContext span_ =
case span_ of
Entry entry -> EntrySpan.w3cTraceContext entry
Exit exit -> Just $ ExitSpan.w3cTraceContext exit
-- |Attaches a W3C trace context to the span.
setW3cTraceContext :: W3CTraceContext -> Span -> Span
setW3cTraceContext w3cTraceContext_ span_ =
case span_ of
Entry entry ->
Entry $ EntrySpan.setW3cTraceContext w3cTraceContext_ entry
Exit exit ->
Exit $ ExitSpan.setW3cTraceContext w3cTraceContext_ exit
-- |The span.tp flag. A span with span.tp = True has inherited the trace ID/
-- parent ID from W3C trace context instead of Instana headers. Only valid for
-- non-root entry spans.
tpFlag :: Span -> Bool
tpFlag span_ =
case span_ of
Entry entry -> EntrySpan.tpFlag entry
Exit _ -> False
-- |Set the span.tp flag. A span with span.tp = True has inherited the trace ID/
-- parent ID from W3C trace context instead of Instana headers. Only valid for
-- non-root entry spans, will be silently ignored for root entry spans and exit
-- spans.
setTpFlag :: Span -> Span
setTpFlag span_ =
case span_ of
Entry entry ->
Entry $ EntrySpan.setTpFlag entry
Exit _ ->
span_
-- |The synthetic flag.
synthetic :: Span -> Bool
synthetic span_ =
case span_ of
Entry entry -> EntrySpan.synthetic entry
Exit _ -> False
-- |Set the synthetic flag. This should only be set on entry spans. It will be
-- silently ignored for other types of spans.
setSynthetic :: Bool -> Span -> Span
setSynthetic synthetic_ span_ =
case span_ of
Entry entry ->
Entry $ EntrySpan.setSynthetic synthetic_ entry
Exit _ ->
span_
-- |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_