packages feed

otel-effectful-1.0.0: src/Effectful/OpenTelemetry/Protocol/Resource.hs

module Effectful.OpenTelemetry.Protocol.Resource where

import Data.Aeson.Types (ToJSON)
import Effectful.OpenTelemetry.Protocol.Attributes (Attributes)
import Effectful.OpenTelemetry.Protocol.Scope (Scope)
import Effectful.OpenTelemetry.Protocol.Scope qualified as Scope
import GHC.Generics (Generic)
import Proto3.Wire.Encode.Class qualified as Proto
import Prelude

-- | Represents the observed entity for which telemetry is produced.
-- Within OpenTelemetry, all signals are associated with a 'Resource',
-- enabling contextual correlation of data from the same source.
--
-- See <https://opentelemetry.io/docs/specs/otel/resource/ the OpenTelemetry spec>.
newtype Resource = Resource
    { attributes :: Attributes
    }
    deriving stock (Generic)
    deriving newtype (Semigroup, Monoid, Show, Eq)
    deriving anyclass (ToJSON)

-- https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/resource/v1/resource.proto
instance Proto.Encode Resource where
    encode Resource{..} =
        mconcat
            [ Proto.encodeField 1 attributes
            -- 2: dropped_attributes_count: Not supported
            -- 3: entity_refs: Not supported
            ]

-- | A batch of scoped items grouped by 'Resource'.
data Items a = Items
    { resource :: Resource
    , scopeItems :: [Scope.Items a]
    }
    deriving stock (Generic)

-- NOTE: The JSON encoding for Items depends on the wrapped item type,
-- so it is defined in the Export.Request class.

instance (Proto.Encode a) => Proto.Encode (Items a) where
    encode Items{..} =
        mconcat
            [ Proto.encodeField 1 resource
            , foldMap (Proto.encodeField 2) scopeItems
            ]

wrapItems :: Resource -> Scope -> [a] -> [Items a]
wrapItems resource scope items = [Items{resource, scopeItems = [Scope.Items{scope, items}]}]