packages feed

otel-effectful-1.0.0: src/Effectful/OpenTelemetry/Metrics/Sum.hs

module Effectful.OpenTelemetry.Metrics.Sum where

import Data.Aeson.Types (ToJSON (..), object, (.=))
import Data.Text (Text)
import Effectful.OpenTelemetry.Metrics.Measurement
    ( AggregationTemporality (..)
    , Measurement
    , Metric (..)
    , NumberDataPoint (..)
    )
import Effectful.OpenTelemetry.Metrics.Measurement qualified as Measurement
import Effectful.OpenTelemetry.Metrics.Metadata (Metadata (..))
import GHC.Generics (Generic)
import Proto3.Wire.Encode.Class qualified as Proto
import Prelude

-- | Whether a sum only ever increases.
data Monotonicity = Monotonic | NonMonotonic
    deriving stock (Eq)

-- | A cumulative sum 'Measurement' of a single data point.
--
-- See <https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums the OpenTelemetry spec>.
measurement :: Monotonicity -> Metadata -> Text -> NumberDataPoint -> Measurement
measurement monotonicity metadata name dataPoint =
    Measurement.create
        name
        metadata
        Payload
            { dataPoints = [dataPoint]
            , isMonotonic = monotonicity == Monotonic
            , aggregationTemporality = TemporalityCumulative
            }

data Payload = Payload
    { dataPoints :: [NumberDataPoint]
    , isMonotonic :: Bool
    , aggregationTemporality :: AggregationTemporality
    }
    deriving stock (Generic, Show, Eq)

instance ToJSON Payload where
    toJSON Payload{..} =
        object
            [ "dataPoints" .= dataPoints
            , "isMonotonic" .= isMonotonic
            , "aggregationTemporality" .= fromEnum aggregationTemporality
            ]

instance Proto.Encode Payload where
    encode Payload{..} =
        mconcat
            [ foldMap (Proto.encodeField 1) dataPoints
            , Proto.encodeField 2 aggregationTemporality
            , Proto.bool 3 isMonotonic
            ]

instance Metric Payload where
    metricJsonKey _ = "sum"
    metricProtoFieldNumber _ = 7