kafka-effectful-0.3.0.0: test/Kafka/Effectful/OpenTelemetry/SemanticTest.hs
module Kafka.Effectful.OpenTelemetry.SemanticTest (tests) where
import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.HashMap.Lazy qualified as HashMap
import Data.Int (Int64)
import Data.Text (Text)
import Kafka.Consumer.ConsumerProperties qualified as ConsumerProperties
import Kafka.Consumer.Types (
ConsumerGroupId (..),
ConsumerRecord (..),
Offset (..),
Timestamp (NoTimestamp),
)
import Kafka.Effectful.OpenTelemetry.Semantic (
consumerRecordAttributes,
consumerRecordAttributesWith,
producerRecordAttributes,
producerRecordAttributesWith,
)
import Kafka.Producer.Types (
ProducePartition (SpecifiedPartition, UnassignedPartition),
ProducerRecord (..),
)
import Kafka.Types (
ClientId (..),
PartitionId (..),
TopicName (..),
headersFromList,
)
import OpenTelemetry.Attributes.Attribute (
Attribute (AttributeValue),
PrimitiveAttribute (IntAttribute, TextAttribute),
)
import OpenTelemetry.SemanticsConfig (StabilityOpt (..))
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertFailure, testCase, (@?=))
tests :: TestTree
tests =
testGroup
"Semantic"
[ producerTests
, consumerTests
]
producerTests :: TestTree
producerTests =
testGroup
"producerRecordAttributes"
[ testCase "legacy helper keeps old operation key" $ do
let attrs = producerRecordAttributes (sampleProducerRecord (Just "k1"))
HashMap.lookup "messaging.system" attrs @?= Just (textAttr "kafka")
HashMap.lookup "messaging.destination.name" attrs @?= Just (textAttr "orders")
HashMap.lookup "messaging.operation" attrs @?= Just (textAttr "send")
assertAbsent "messaging.operation.name" attrs
assertAbsent "messaging.operation.type" attrs
, testCase "stable mode uses stable operation keys" $ do
let attrs = producerRecordAttributesWith Stable (sampleProducerRecord (Just "k1"))
HashMap.lookup "messaging.operation.name" attrs @?= Just (textAttr "send")
HashMap.lookup "messaging.operation.type" attrs @?= Just (textAttr "send")
assertAbsent "messaging.operation" attrs
, testCase "duplicate mode emits old and stable operation keys" $ do
let attrs = producerRecordAttributesWith StableAndOld (sampleProducerRecord (Just "k1"))
HashMap.lookup "messaging.operation" attrs @?= Just (textAttr "send")
HashMap.lookup "messaging.operation.name" attrs @?= Just (textAttr "send")
HashMap.lookup "messaging.operation.type" attrs @?= Just (textAttr "send")
, testCase "adds partition, key, and body size when available" $ do
let attrs = producerRecordAttributesWith Old (sampleProducerRecord (Just "hello"))
HashMap.lookup "messaging.kafka.destination.partition" attrs
@?= Just (intAttr 42)
HashMap.lookup "messaging.kafka.message.key" attrs
@?= Just (textAttr "hello")
HashMap.lookup "messaging.message.body.size" attrs
@?= Just (intAttr 5)
, testCase "omits partition for UnassignedPartition" $ do
let attrs =
producerRecordAttributesWith
Old
(sampleProducerRecord (Just "k1"))
{ prPartition = UnassignedPartition
}
assertAbsent "messaging.kafka.destination.partition" attrs
, testCase "omits invalid or absent keys" $ do
let invalidAttrs =
producerRecordAttributesWith
Old
(sampleProducerRecord (Just (BS.pack [0xC3, 0x28])))
missingAttrs =
producerRecordAttributesWith Old (sampleProducerRecord Nothing)
assertAbsent "messaging.kafka.message.key" invalidAttrs
assertAbsent "messaging.kafka.message.key" missingAttrs
]
consumerTests :: TestTree
consumerTests =
testGroup
"consumerRecordAttributes"
[ testCase "legacy helper keeps old operation key" $ do
let attrs = consumerRecordAttributes (sampleConsumerRecord (Just "k1"))
HashMap.lookup "messaging.system" attrs @?= Just (textAttr "kafka")
HashMap.lookup "messaging.destination.name" attrs @?= Just (textAttr "orders")
HashMap.lookup "messaging.operation" attrs @?= Just (textAttr "process")
assertAbsent "messaging.operation.name" attrs
assertAbsent "messaging.operation.type" attrs
, testCase "old mode uses legacy consumer group key" $ do
let attrs = consumerRecordAttributesWith Old sampleConsumerProps (sampleConsumerRecord (Just "k1"))
HashMap.lookup "messaging.kafka.consumer.group" attrs
@?= Just (textAttr "orders-group")
assertAbsent "messaging.consumer.group.name" attrs
, testCase "stable mode uses stable operation and consumer group keys" $ do
let attrs = consumerRecordAttributesWith Stable sampleConsumerProps (sampleConsumerRecord (Just "k1"))
HashMap.lookup "messaging.operation.name" attrs @?= Just (textAttr "process")
HashMap.lookup "messaging.operation.type" attrs @?= Just (textAttr "process")
HashMap.lookup "messaging.consumer.group.name" attrs
@?= Just (textAttr "orders-group")
assertAbsent "messaging.operation" attrs
assertAbsent "messaging.kafka.consumer.group" attrs
, testCase "duplicate mode emits old and stable operation and group keys" $ do
let attrs = consumerRecordAttributesWith StableAndOld sampleConsumerProps (sampleConsumerRecord (Just "k1"))
HashMap.lookup "messaging.operation" attrs @?= Just (textAttr "process")
HashMap.lookup "messaging.operation.name" attrs @?= Just (textAttr "process")
HashMap.lookup "messaging.operation.type" attrs @?= Just (textAttr "process")
HashMap.lookup "messaging.kafka.consumer.group" attrs
@?= Just (textAttr "orders-group")
HashMap.lookup "messaging.consumer.group.name" attrs
@?= Just (textAttr "orders-group")
, testCase "adds client id, partition, offset, key, and body size" $ do
let attrs = consumerRecordAttributesWith Old sampleConsumerProps (sampleConsumerRecord (Just "hello"))
HashMap.lookup "messaging.client.id" attrs
@?= Just (textAttr "orders-client")
HashMap.lookup "messaging.kafka.destination.partition" attrs
@?= Just (intAttr 7)
HashMap.lookup "messaging.kafka.message.offset" attrs
@?= Just (intAttr 42)
HashMap.lookup "messaging.kafka.message.key" attrs
@?= Just (textAttr "hello")
HashMap.lookup "messaging.message.body.size" attrs
@?= Just (intAttr 5)
, testCase "omits invalid or absent keys" $ do
let invalidAttrs =
consumerRecordAttributesWith
Old
sampleConsumerProps
(sampleConsumerRecord (Just (BS.pack [0xC3, 0x28])))
missingAttrs =
consumerRecordAttributesWith Old sampleConsumerProps (sampleConsumerRecord Nothing)
assertAbsent "messaging.kafka.message.key" invalidAttrs
assertAbsent "messaging.kafka.message.key" missingAttrs
]
sampleProducerRecord :: Maybe ByteString -> ProducerRecord
sampleProducerRecord key =
ProducerRecord
{ prTopic = TopicName "orders"
, prPartition = SpecifiedPartition 42
, prKey = key
, prValue = Just "value"
, prHeaders = headersFromList []
}
sampleConsumerRecord ::
Maybe ByteString ->
ConsumerRecord (Maybe ByteString) (Maybe ByteString)
sampleConsumerRecord key =
ConsumerRecord
{ crTopic = TopicName "orders"
, crPartition = PartitionId 7
, crOffset = Offset 42
, crTimestamp = NoTimestamp
, crHeaders = headersFromList []
, crKey = key
, crValue = Just "value"
}
sampleConsumerProps :: ConsumerProperties.ConsumerProperties
sampleConsumerProps =
ConsumerProperties.groupId (ConsumerGroupId "orders-group")
<> ConsumerProperties.clientId (ClientId "orders-client")
textAttr :: Text -> Attribute
textAttr = AttributeValue . TextAttribute
intAttr :: Int64 -> Attribute
intAttr = AttributeValue . IntAttribute
assertAbsent :: Text -> HashMap.HashMap Text Attribute -> IO ()
assertAbsent key attrs =
case HashMap.lookup key attrs of
Nothing -> pure ()
Just attr ->
assertFailure $
"expected "
<> show key
<> " to be absent, got "
<> show attr