kafka-effectful-0.2.0.0: test/Kafka/Effectful/OpenTelemetry/ShibuyaCompatibilityTest.hs
module Kafka.Effectful.OpenTelemetry.ShibuyaCompatibilityTest (tests) where
import Data.HashMap.Strict qualified as HashMap
import Data.Int (Int64)
import Data.Text (Text)
import Kafka.Consumer.Types (
ConsumerRecord (..),
Offset (..),
Timestamp (NoTimestamp),
)
import Kafka.Effectful.OpenTelemetry.Semantic (consumerRecordAttributes)
import Kafka.Types (
PartitionId (..),
TopicName (..),
headersFromList,
)
import OpenTelemetry.Attributes (Attribute, toAttribute, unkey)
import OpenTelemetry.SemanticConventions (
messaging_kafka_destination_partition,
messaging_kafka_message_offset,
)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertEqual, testCase)
{- | Tests pinning @Kafka.Effectful.OpenTelemetry.Semantic@\'s
'consumerRecordAttributes' against the attribute set that
@shibuya-kafka-adapter@\'s
@Shibuya.Adapter.Kafka.Convert.kafkaSpanAttributes@ produces.
Both libraries depend on @hs-opentelemetry-semantic-conventions@,
so if upstream renames a key in a future release this test fails
together with shibuya — the desired failure mode for a
compatibility pin.
-}
tests :: TestTree
tests =
testGroup
"ShibuyaCompatibility"
[ testCase "consumerRecordAttributes agrees on messaging.system" $ do
let actual = HashMap.lookup "messaging.system" sampleAttrs
expected = HashMap.lookup "messaging.system" shibuyaAttrs
assertEqual "messaging.system attribute differs" expected actual
, testCase "consumerRecordAttributes agrees on messaging.kafka.destination.partition" $ do
let key = unkey messaging_kafka_destination_partition
actual = HashMap.lookup key sampleAttrs
expected = HashMap.lookup key shibuyaAttrs
assertEqual "partition attribute differs" expected actual
, testCase "consumerRecordAttributes agrees on messaging.kafka.message.offset" $ do
let key = unkey messaging_kafka_message_offset
actual = HashMap.lookup key sampleAttrs
expected = HashMap.lookup key shibuyaAttrs
assertEqual "offset attribute differs" expected actual
]
-- Sample inputs — partition 7, offset 42 — chosen so the resulting
-- attribute values are non-zero and easy to spot in failures.
samplePid :: PartitionId
samplePid = PartitionId 7
sampleOffset :: Offset
sampleOffset = Offset 42
sampleAttrs :: HashMap.HashMap Text Attribute
sampleAttrs =
consumerRecordAttributes
ConsumerRecord
{ crTopic = TopicName "orders"
, crPartition = samplePid
, crOffset = sampleOffset
, crTimestamp = NoTimestamp
, crHeaders = headersFromList []
, crKey = Nothing
, crValue = Just "value"
}
{- | Local replica of @shibuya-kafka-adapter@\'s
@Shibuya.Adapter.Kafka.Convert.kafkaSpanAttributes@. Mirrors the
exact source-level expression at
@shibuya-kafka-adapter\/src\/Shibuya\/Adapter\/Kafka\/Convert.hs:78-89@:
> kafkaSpanAttributes :: PartitionId -> Offset -> HashMap Text Attribute
> kafkaSpanAttributes (PartitionId pid) (Offset off) =
> HashMap.fromList
> [ (\"messaging.system\", toAttribute (\"kafka\" :: Text))
> , (unkey messaging_kafka_destination_partition, toAttribute (fromIntegral pid :: Int64))
> , (unkey messaging_kafka_message_offset, toAttribute (off :: Int64))
> ]
-}
shibuyaAttrs :: HashMap.HashMap Text Attribute
shibuyaAttrs =
let PartitionId pid = samplePid
Offset off = sampleOffset
in HashMap.fromList
[ ("messaging.system", toAttribute ("kafka" :: Text))
,
( unkey messaging_kafka_destination_partition
, toAttribute (fromIntegral pid :: Int64)
)
,
( unkey messaging_kafka_message_offset
, toAttribute (off :: Int64)
)
]