diff --git a/.chloggen/815.yaml b/.chloggen/815.yaml new file mode 100644 index 0000000000..202d2713f9 --- /dev/null +++ b/.chloggen/815.yaml @@ -0,0 +1,8 @@ +change_type: breaking +component: messaging +note: > + Introduce common attributes for consumer group and subscription name instead of per-system ones: + - `messaging.consumer.group.name` instead of `messaging.kafka.consumer.group`, `messaging.rocketmq.client_group`, and `messaging.eventhubs.consumer.group`. + - `messaging.destination.subscription.name` instead of `messaging.servicebus.destination.subscription_name`. Use it in the Google Pub/Sub conventions. + +issues: [ 815 ] diff --git a/docs/attributes-registry/messaging.md b/docs/attributes-registry/messaging.md index 6333c54fae..dd69d0c13e 100644 --- a/docs/attributes-registry/messaging.md +++ b/docs/attributes-registry/messaging.md @@ -23,40 +23,46 @@ Attributes describing telemetry around messaging systems and messaging activitie | ----------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------- | ---------------------------------------------------------------- | | `messaging.batch.message_count` | int | The number of messages sent, received, or processed in the scope of the batching operation. [1] | `0`; `1`; `2` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.client.id` | string | A unique identifier for the client that consumes or produces a message. | `client-5`; `myhost@8742@s8083jm` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.consumer.group.name` | string | The name of the consumer group with which a consumer is associated. [2] | `my-group`; `indexer` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.destination.anonymous` | boolean | A boolean that is true if the message destination is anonymous (could be unnamed or have auto-generated name). | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.destination.name` | string | The message destination name [2] | `MyQueue`; `MyTopic` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.destination.name` | string | The message destination name [3] | `MyQueue`; `MyTopic` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.destination.partition.id` | string | The identifier of the partition messages are sent to or received from, unique within the `messaging.destination.name`. | `1` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.destination.template` | string | Low cardinality representation of the messaging destination name [3] | `/customers/{customerId}` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.destination.subscription.name` | string | The name of the destination subscription from which a message is consumed. [4] | `subscription-a` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.destination.template` | string | Low cardinality representation of the messaging destination name [5] | `/customers/{customerId}` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.destination.temporary` | boolean | A boolean that is true if the message destination is temporary and might not exist anymore after messages are processed. | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.destination_publish.anonymous` | boolean | A boolean that is true if the publish message destination is anonymous (could be unnamed or have auto-generated name). | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.destination_publish.name` | string | The name of the original destination the message was published to [4] | `MyQueue`; `MyTopic` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.message.body.size` | int | The size of the message body in bytes. [5] | `1439` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.destination_publish.name` | string | The name of the original destination the message was published to [6] | `MyQueue`; `MyTopic` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.message.body.size` | int | The size of the message body in bytes. [7] | `1439` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.message.conversation_id` | string | The conversation ID identifying the conversation to which the message belongs, represented as a string. Sometimes called "Correlation ID". | `MyConversationId` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.message.envelope.size` | int | The size of the message body and metadata in bytes. [6] | `2738` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.message.envelope.size` | int | The size of the message body and metadata in bytes. [8] | `2738` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.message.id` | string | A value used by the messaging system as an identifier for the message, represented as a string. | `452a7c7c7c7048c2f887f61572b18fc2` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.operation.name` | string | The system-specific name of the messaging operation. | `ack`; `nack`; `send` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.operation.type` | string | A string identifying the type of the messaging operation. [7] | `publish`; `create`; `receive` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.system` | string | The messaging system as identified by the client instrumentation. [8] | `activemq`; `aws_sqs`; `eventgrid` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.operation.type` | string | A string identifying the type of the messaging operation. [9] | `publish`; `create`; `receive` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.system` | string | The messaging system as identified by the client instrumentation. [10] | `activemq`; `aws_sqs`; `eventgrid` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** Instrumentations SHOULD NOT set `messaging.batch.message_count` on spans that operate with a single message. When a messaging client library supports both batch and single-message API for the same operation, instrumentations SHOULD use `messaging.batch.message_count` for batching APIs and SHOULD NOT use it for single-message APIs. -**[2]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If +**[2]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.consumer.group.name` is applicable and what it means in the context of that system. + +**[3]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If the broker doesn't have such notion, the destination name SHOULD uniquely identify the broker. -**[3]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. +**[4]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.destination.subscription.name` is applicable and what it means in the context of that system. + +**[5]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. -**[4]:** The name SHOULD uniquely identify a specific queue, topic, or other entity within the broker. If +**[6]:** The name SHOULD uniquely identify a specific queue, topic, or other entity within the broker. If the broker doesn't have such notion, the original destination name SHOULD uniquely identify the broker. -**[5]:** This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed +**[7]:** This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed body size should be used. -**[6]:** This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed +**[8]:** This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed size should be used. -**[7]:** If a custom value is used, it MUST be of low cardinality. +**[9]:** If a custom value is used, it MUST be of low cardinality. -**[8]:** The actual messaging system may differ from the one known by the client. For example, when using Kafka client libraries to communicate with Azure Event Hubs, the `messaging.system` is set to `kafka` based on the instrumentation's best knowledge. +**[10]:** The actual messaging system may differ from the one known by the client. For example, when using Kafka client libraries to communicate with Azure Event Hubs, the `messaging.system` is set to `kafka` based on the instrumentation's best knowledge. `messaging.operation.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. @@ -89,20 +95,23 @@ size should be used. Describes deprecated messaging attributes. -| Attribute | Type | Description | Examples | Stability | -| --------------------------------------- | ------ | ------------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -| `messaging.client_id` | string | Deprecated, use `messaging.client.id` instead. | `client-5`; `myhost@8742@s8083jm` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.client.id`. | -| `messaging.kafka.destination.partition` | int | Deprecated, use `messaging.destination.partition.id` instead. | `2` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.destination.partition.id`. | -| `messaging.operation` | string | Deprecated, use `messaging.operation.type` instead. | `publish`; `create`; `process` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.operation.type`. | +| Attribute | Type | Description | Examples | Stability | +| ---------------------------------------------------- | ------ | ----------------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `messaging.client_id` | string | Deprecated, use `messaging.client.id` instead. | `client-5`; `myhost@8742@s8083jm` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.client.id`. | +| `messaging.eventhubs.consumer.group` | string | Deprecated, use `messaging.consumer.group.name` instead. | `$Default` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.consumer.group.name`. | +| `messaging.kafka.consumer.group` | string | Deprecated, use `messaging.consumer.group.name` instead. | `my-group` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.consumer.group.name`. | +| `messaging.kafka.destination.partition` | int | Deprecated, use `messaging.destination.partition.id` instead. | `2` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.destination.partition.id`. | +| `messaging.operation` | string | Deprecated, use `messaging.operation.type` instead. | `publish`; `create`; `process` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.operation.type`. | +| `messaging.rocketmq.client_group` | string | Deprecated, use `messaging.consumer.group.name` instead. | `myConsumerGroup` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.consumer.group.name` on the consumer spans. No replacement for producer spans. | +| `messaging.servicebus.destination.subscription_name` | string | Deprecated, use `messaging.servicebus.destination.subscription_name` instead. | `subscription-a` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `messaging.servicebus.destination.subscription_name`. | ## Messaging Eventhubs Attributes This group describes attributes specific to Azure Event Hubs. -| Attribute | Type | Description | Examples | Stability | -| ------------------------------------------- | ------ | -------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------- | -| `messaging.eventhubs.consumer.group` | string | The name of the consumer group the event consumer is associated with. | `indexer` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.eventhubs.message.enqueued_time` | int | The UTC epoch seconds at which the message has been accepted and stored in the entity. | `1701393730` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| Attribute | Type | Description | Examples | Stability | +| ------------------------------------------- | ---- | -------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------- | +| `messaging.eventhubs.message.enqueued_time` | int | The UTC epoch seconds at which the message has been accepted and stored in the entity. | `1701393730` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | ## Messaging GCP Pubsub Attributes @@ -119,14 +128,13 @@ This group describes attributes specific to GCP Pub/Sub. This group describes attributes specific to Apache Kafka. -| Attribute | Type | Description | Examples | Stability | -| ----------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------- | -| `messaging.kafka.consumer.group` | string | Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not producers. | `my-group` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.kafka.message.key` | string | Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from `messaging.message.id` in that they're not unique. If the key is `null`, the attribute MUST NOT be set. [9] | `myKey` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.kafka.message.offset` | int | The offset of a record in the corresponding Kafka partition. | `42` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.kafka.message.tombstone` | boolean | A boolean that is true if the message is a tombstone. | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| Attribute | Type | Description | Examples | Stability | +| ----------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------- | +| `messaging.kafka.message.key` | string | Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from `messaging.message.id` in that they're not unique. If the key is `null`, the attribute MUST NOT be set. [11] | `myKey` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.kafka.message.offset` | int | The offset of a record in the corresponding Kafka partition. | `42` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.kafka.message.tombstone` | boolean | A boolean that is true if the message is a tombstone. | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[9]:** If the key type is not string, it's string representation has to be supplied for the attribute. If the key has no unambiguous, canonical string form, don't include its value. +**[11]:** If the key type is not string, it's string representation has to be supplied for the attribute. If the key has no unambiguous, canonical string form, don't include its value. ## Messaging RabbitMQ Attributes @@ -143,7 +151,6 @@ This group describes attributes specific to RocketMQ. | Attribute | Type | Description | Examples | Stability | | ----------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------- | ---------------------------------------------------------------- | -| `messaging.rocketmq.client_group` | string | Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind. | `myConsumerGroup` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.rocketmq.consumption_model` | string | Model of message consumption. This only applies to consumer spans. | `clustering`; `broadcasting` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.rocketmq.message.delay_time_level` | int | The delay time level for delay message, which determines the message delay time. | `3` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.rocketmq.message.delivery_timestamp` | int | The timestamp in milliseconds that the delay message is expected to be delivered to consumer. | `1665987217045` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | @@ -173,12 +180,11 @@ This group describes attributes specific to RocketMQ. This group describes attributes specific to Azure Service Bus. -| Attribute | Type | Description | Examples | Stability | -| ---------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------- | -| `messaging.servicebus.destination.subscription_name` | string | The name of the subscription in the topic messages are received from. | `mySubscription` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.servicebus.disposition_status` | string | Describes the [settlement type](https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock). | `complete`; `abandon`; `dead_letter` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.servicebus.message.delivery_count` | int | Number of deliveries that have been attempted for this message. | `2` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `messaging.servicebus.message.enqueued_time` | int | The UTC epoch seconds at which the message has been accepted and stored in the entity. | `1701393730` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| Attribute | Type | Description | Examples | Stability | +| --------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------- | +| `messaging.servicebus.disposition_status` | string | Describes the [settlement type](https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock). | `complete`; `abandon`; `dead_letter` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.servicebus.message.delivery_count` | int | Number of deliveries that have been attempted for this message. | `2` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.servicebus.message.enqueued_time` | int | The UTC epoch seconds at which the message has been accepted and stored in the entity. | `1701393730` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | `messaging.servicebus.disposition_status` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. diff --git a/docs/messaging/azure-messaging.md b/docs/messaging/azure-messaging.md index 32aed18ae1..5ea74c75f1 100644 --- a/docs/messaging/azure-messaging.md +++ b/docs/messaging/azure-messaging.md @@ -28,8 +28,8 @@ The following additional attributes are defined: | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `amqp:decode-error`; `KAFKA_STORAGE_ERROR`; `channel-error` | `Conditionally Required` If and only if the messaging operation has failed. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.batch.message_count`](/docs/attributes-registry/messaging.md) | int | The number of messages sent, received, or processed in the scope of the batching operation. [3] | `0`; `1`; `2` | `Conditionally Required` [4] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [5] | `MyQueue`; `MyTopic` | `Conditionally Required` [6] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.subscription.name`](/docs/attributes-registry/messaging.md) | string | Azure Service Bus [subscription name](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-queues-topics-subscriptions#topics-and-subscriptions). | `subscription-a` | `Conditionally Required` If messages are received from the subscription. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [7] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.servicebus.destination.subscription_name`](/docs/attributes-registry/messaging.md) | string | The name of the subscription in the topic messages are received from. | `mySubscription` | `Conditionally Required` If messages are received from the subscription. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.servicebus.disposition_status`](/docs/attributes-registry/messaging.md) | string | Describes the [settlement type](https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock). | `complete`; `abandon`; `dead_letter` | `Conditionally Required` if and only if `messaging.operation` is `settle`. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.servicebus.message.delivery_count`](/docs/attributes-registry/messaging.md) | int | Number of deliveries that have been attempted for this message. | `2` | `Conditionally Required` [8] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [9] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | @@ -141,9 +141,9 @@ The following additional attributes are defined: | [`messaging.operation.name`](/docs/attributes-registry/messaging.md) | string | Azure Event Hubs operation name. [1] | `send`; `receive`; `checkpoint` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `amqp:decode-error`; `KAFKA_STORAGE_ERROR`; `channel-error` | `Conditionally Required` If and only if the messaging operation has failed. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.batch.message_count`](/docs/attributes-registry/messaging.md) | int | The number of messages sent, received, or processed in the scope of the batching operation. [3] | `0`; `1`; `2` | `Conditionally Required` [4] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | Azure Event Hubs [consumer group name](https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-features#consumer-groups). | `my-group`; `indexer` | `Conditionally Required` On consumer spans. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [5] | `MyQueue`; `MyTopic` | `Conditionally Required` [6] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.partition.id`](/docs/attributes-registry/messaging.md) | string | String representation of the partition id messages are sent to or received from, unique within the Event Hub. | `1` | `Conditionally Required` If available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.eventhubs.consumer.group`](/docs/attributes-registry/messaging.md) | string | The name of the consumer group the event consumer is associated with. | `indexer` | `Conditionally Required` If not default ("$Default"). | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [7] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [8] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.eventhubs.message.enqueued_time`](/docs/attributes-registry/messaging.md) | int | The UTC epoch seconds at which the message has been accepted and stored in the entity. | `1701393730` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | diff --git a/docs/messaging/gcp-pubsub.md b/docs/messaging/gcp-pubsub.md index d2a9977bbc..30135a2db6 100644 --- a/docs/messaging/gcp-pubsub.md +++ b/docs/messaging/gcp-pubsub.md @@ -30,6 +30,7 @@ For Google Cloud Pub/Sub, the following additional attributes are defined: | [`messaging.gcp_pubsub.message.ordering_key`](/docs/attributes-registry/messaging.md) | string | The ordering key for a given message. If the attribute is not present, the message does not have an ordering key. | `ordering_key` | `Conditionally Required` If the message type has an ordering key set. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [7] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [8] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`messaging.destination.subscription.name`](/docs/attributes-registry/messaging.md) | string | Google Pub/Sub [subscription name](https://cloud.google.com/pubsub/docs/subscription-overview). | `subscription-a` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.gcp_pubsub.message.ack_deadline`](/docs/attributes-registry/messaging.md) | int | The ack deadline in seconds set for the modify ack deadline request. | `10` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.gcp_pubsub.message.ack_id`](/docs/attributes-registry/messaging.md) | string | The ack id for a given message. | `ack_id` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.gcp_pubsub.message.delivery_attempt`](/docs/attributes-registry/messaging.md) | int | The delivery attempt for a given message. | `2` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | diff --git a/docs/messaging/kafka.md b/docs/messaging/kafka.md index d66b9f6609..15b5b1258a 100644 --- a/docs/messaging/kafka.md +++ b/docs/messaging/kafka.md @@ -41,8 +41,8 @@ For Apache Kafka, the following additional attributes are defined: | [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [7] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [8] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.client.id`](/docs/attributes-registry/messaging.md) | string | A unique identifier for the client that consumes or produces a message. | `client-5`; `myhost@8742@s8083jm` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | Kafka [consumer group id](https://docs.confluent.io/platform/current/clients/consumer.html). | `my-group`; `indexer` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.partition.id`](/docs/attributes-registry/messaging.md) | string | String representation of the partition id the message (or batch) is sent to or received from. | `1` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.kafka.consumer.group`](/docs/attributes-registry/messaging.md) | string | Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not producers. | `my-group` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.kafka.message.key`](/docs/attributes-registry/messaging.md) | string | Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from `messaging.message.id` in that they're not unique. If the key is `null`, the attribute MUST NOT be set. [9] | `myKey` | `Recommended` If span describes operation on a single message. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.kafka.message.offset`](/docs/attributes-registry/messaging.md) | int | The offset of a record in the corresponding Kafka partition. | `42` | `Recommended` If span describes operation on a single message. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.message.body.size`](/docs/attributes-registry/messaging.md) | int | The size of the message body in bytes. [10] | `1439` | `Recommended` If span describes operation on a single message. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | diff --git a/docs/messaging/messaging-metrics.md b/docs/messaging/messaging-metrics.md index a4865c7330..a50c3f38d5 100644 --- a/docs/messaging/messaging-metrics.md +++ b/docs/messaging/messaging-metrics.md @@ -68,12 +68,14 @@ of `[ 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 | [`messaging.operation.name`](/docs/attributes-registry/messaging.md) | string | The system-specific name of the messaging operation. | `send`; `receive`; `ack` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.system`](/docs/attributes-registry/messaging.md) | string | The messaging system as identified by the client instrumentation. [1] | `activemq`; `aws_sqs`; `eventgrid` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `amqp:decode-error`; `KAFKA_STORAGE_ERROR`; `channel-error` | `Conditionally Required` If and only if the messaging operation has failed. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [3] | `MyQueue`; `MyTopic` | `Conditionally Required` [4] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [5] | `/customers/{customerId}` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [6] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [7] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | The name of the consumer group with which a consumer is associated. [3] | `my-group`; `indexer` | `Conditionally Required` if applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [4] | `MyQueue`; `MyTopic` | `Conditionally Required` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.subscription.name`](/docs/attributes-registry/messaging.md) | string | The name of the destination subscription from which a message is consumed. [6] | `subscription-a` | `Conditionally Required` if applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [7] | `/customers/{customerId}` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [8] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [9] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.destination.partition.id`](/docs/attributes-registry/messaging.md) | string | The identifier of the partition messages are sent to or received from, unique within the `messaging.destination.name`. | `1` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [8] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [10] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** The actual messaging system may differ from the one known by the client. For example, when using Kafka client libraries to communicate with Azure Event Hubs, the `messaging.system` is set to `kafka` based on the instrumentation's best knowledge. @@ -97,18 +99,22 @@ it's RECOMMENDED to: * Use a domain-specific attribute * Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. -**[3]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If +**[3]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.consumer.group.name` is applicable and what it means in the context of that system. + +**[4]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If the broker doesn't have such notion, the destination name SHOULD uniquely identify the broker. -**[4]:** if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated. +**[5]:** if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated. -**[5]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. +**[6]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.destination.subscription.name` is applicable and what it means in the context of that system. -**[6]:** If a custom value is used, it MUST be of low cardinality. +**[7]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. -**[7]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. +**[8]:** If a custom value is used, it MUST be of low cardinality. -**[8]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. +**[9]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. + +**[10]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. @@ -303,11 +309,13 @@ The metric SHOULD be reported once per message delivery. For example, if receivi | [`messaging.operation.name`](/docs/attributes-registry/messaging.md) | string | The system-specific name of the messaging operation. | `receive`; `peek`; `poll`; `consume` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.system`](/docs/attributes-registry/messaging.md) | string | The messaging system as identified by the client instrumentation. [1] | `activemq`; `aws_sqs`; `eventgrid` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `amqp:decode-error`; `KAFKA_STORAGE_ERROR`; `channel-error` | `Conditionally Required` If and only if the messaging operation has failed. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [3] | `MyQueue`; `MyTopic` | `Conditionally Required` [4] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [5] | `/customers/{customerId}` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [6] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | The name of the consumer group with which a consumer is associated. [3] | `my-group`; `indexer` | `Conditionally Required` if applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [4] | `MyQueue`; `MyTopic` | `Conditionally Required` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.subscription.name`](/docs/attributes-registry/messaging.md) | string | The name of the destination subscription from which a message is consumed. [6] | `subscription-a` | `Conditionally Required` if applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [7] | `/customers/{customerId}` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [8] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.destination.partition.id`](/docs/attributes-registry/messaging.md) | string | The identifier of the partition messages are sent to or received from, unique within the `messaging.destination.name`. | `1` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [7] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [9] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** The actual messaging system may differ from the one known by the client. For example, when using Kafka client libraries to communicate with Azure Event Hubs, the `messaging.system` is set to `kafka` based on the instrumentation's best knowledge. @@ -331,16 +339,20 @@ it's RECOMMENDED to: * Use a domain-specific attribute * Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. -**[3]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If +**[3]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.consumer.group.name` is applicable and what it means in the context of that system. + +**[4]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If the broker doesn't have such notion, the destination name SHOULD uniquely identify the broker. -**[4]:** if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated. +**[5]:** if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated. -**[5]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. +**[6]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.destination.subscription.name` is applicable and what it means in the context of that system. -**[6]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. +**[7]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. -**[7]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. +**[8]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. + +**[9]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. @@ -417,11 +429,13 @@ of `[ 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 | [`messaging.operation.name`](/docs/attributes-registry/messaging.md) | string | The system-specific name of the messaging operation. | `process`; `consume`; `handle` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.system`](/docs/attributes-registry/messaging.md) | string | The messaging system as identified by the client instrumentation. [1] | `activemq`; `aws_sqs`; `eventgrid` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `amqp:decode-error`; `KAFKA_STORAGE_ERROR`; `channel-error` | `Conditionally Required` If and only if the messaging operation has failed. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [3] | `MyQueue`; `MyTopic` | `Conditionally Required` [4] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [5] | `/customers/{customerId}` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [6] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | The name of the consumer group with which a consumer is associated. [3] | `my-group`; `indexer` | `Conditionally Required` if applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [4] | `MyQueue`; `MyTopic` | `Conditionally Required` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.subscription.name`](/docs/attributes-registry/messaging.md) | string | The name of the destination subscription from which a message is consumed. [6] | `subscription-a` | `Conditionally Required` if applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [7] | `/customers/{customerId}` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [8] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.destination.partition.id`](/docs/attributes-registry/messaging.md) | string | The identifier of the partition messages are sent to or received from, unique within the `messaging.destination.name`. | `1` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [7] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [9] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** The actual messaging system may differ from the one known by the client. For example, when using Kafka client libraries to communicate with Azure Event Hubs, the `messaging.system` is set to `kafka` based on the instrumentation's best knowledge. @@ -445,16 +459,20 @@ it's RECOMMENDED to: * Use a domain-specific attribute * Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. -**[3]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If +**[3]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.consumer.group.name` is applicable and what it means in the context of that system. + +**[4]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If the broker doesn't have such notion, the destination name SHOULD uniquely identify the broker. -**[4]:** if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated. +**[5]:** if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated. -**[5]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. +**[6]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.destination.subscription.name` is applicable and what it means in the context of that system. -**[6]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. +**[7]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. -**[7]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. +**[8]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. + +**[9]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. diff --git a/docs/messaging/messaging-spans.md b/docs/messaging/messaging-spans.md index 48b6743e9b..dfd4201a2e 100644 --- a/docs/messaging/messaging-spans.md +++ b/docs/messaging/messaging-spans.md @@ -13,6 +13,8 @@ - [Intermediary](#intermediary) - [Destinations](#destinations) - [Message consumption](#message-consumption) + - [Consumer groups](#consumer-groups) + - [Subscriptions](#subscriptions) - [Conversations](#conversations) - [Temporary and anonymous destinations](#temporary-and-anonymous-destinations) - [Conventions](#conventions) @@ -104,6 +106,23 @@ First, the lower-level receiving of a message at a consumer, and then the logica Often, the waiting for a message is not particularly interesting and hidden away in a framework that only invokes some handler function to process a message once one is received (in the same way that the listening on a TCP port for an incoming HTTP message is not particularly interesting). +#### Consumer groups + +Consumer groups provide a logical grouping for the message consumers. Messaging systems use them to +load balance message consumption within the group, broadcast messages to multiple types of the consumers, +manage offset for each group independently. +As a result, different groups of consumers can receive messages at a different pace +or using different settings. + +#### Subscriptions + +Subscriptions represent entities within messaging systems that allow multiple consumers +to receive messages from the topic following subscription-specific consumption behavior that includes +load balancing, durability, filtering, or other system-specific capabilities. + +Named subscriptions and consumers groups are semantically different mechanisms messaging systems use +for similar scenarios such as load-balancing or broadcasting. + ### Conversations In some messaging systems, a message can receive one or more reply messages that answers a particular other message that was sent earlier. All messages that are grouped together by such a reply-relationship are called a *conversation*. @@ -291,21 +310,23 @@ as described in [Attributes specific to certain messaging systems](#attributes-s | [`messaging.system`](/docs/attributes-registry/messaging.md) | string | The messaging system as identified by the client instrumentation. [1] | `activemq`; `aws_sqs`; `eventgrid` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `amqp:decode-error`; `KAFKA_STORAGE_ERROR`; `channel-error` | `Conditionally Required` If and only if the messaging operation has failed. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.batch.message_count`](/docs/attributes-registry/messaging.md) | int | The number of messages sent, received, or processed in the scope of the batching operation. [3] | `0`; `1`; `2` | `Conditionally Required` [4] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.anonymous`](/docs/attributes-registry/messaging.md) | boolean | A boolean that is true if the message destination is anonymous (could be unnamed or have auto-generated name). | | `Conditionally Required` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [6] | `MyQueue`; `MyTopic` | `Conditionally Required` [7] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [8] | `/customers/{customerId}` | `Conditionally Required` [9] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.temporary`](/docs/attributes-registry/messaging.md) | boolean | A boolean that is true if the message destination is temporary and might not exist anymore after messages are processed. | | `Conditionally Required` [10] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [11] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [12] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | The name of the consumer group with which a consumer is associated. [5] | `my-group`; `indexer` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.anonymous`](/docs/attributes-registry/messaging.md) | boolean | A boolean that is true if the message destination is anonymous (could be unnamed or have auto-generated name). | | `Conditionally Required` [6] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [7] | `MyQueue`; `MyTopic` | `Conditionally Required` [8] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.subscription.name`](/docs/attributes-registry/messaging.md) | string | The name of the destination subscription from which a message is consumed. [9] | `subscription-a` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.template`](/docs/attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [10] | `/customers/{customerId}` | `Conditionally Required` [11] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.temporary`](/docs/attributes-registry/messaging.md) | boolean | A boolean that is true if the message destination is temporary and might not exist anymore after messages are processed. | | `Conditionally Required` [12] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [13] | `publish`; `create`; `receive` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [14] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Conditionally Required` If available. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.client.id`](/docs/attributes-registry/messaging.md) | string | A unique identifier for the client that consumes or produces a message. | `client-5`; `myhost@8742@s8083jm` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.partition.id`](/docs/attributes-registry/messaging.md) | string | The identifier of the partition messages are sent to or received from, unique within the `messaging.destination.name`. | `1` | `Recommended` When applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.message.body.size`](/docs/attributes-registry/messaging.md) | int | The size of the message body in bytes. [13] | `1439` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.message.body.size`](/docs/attributes-registry/messaging.md) | int | The size of the message body in bytes. [15] | `1439` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.message.conversation_id`](/docs/attributes-registry/messaging.md) | string | The conversation ID identifying the conversation to which the message belongs, represented as a string. Sometimes called "Correlation ID". | `MyConversationId` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.message.envelope.size`](/docs/attributes-registry/messaging.md) | int | The size of the message body and metadata in bytes. [14] | `2738` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.message.envelope.size`](/docs/attributes-registry/messaging.md) | int | The size of the message body and metadata in bytes. [16] | `2738` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.message.id`](/docs/attributes-registry/messaging.md) | string | A value used by the messaging system as an identifier for the message, represented as a string. | `452a7c7c7c7048c2f887f61572b18fc2` | `Recommended` If span describes operation on a single message. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the messaging intermediary node where the operation was performed. [15] | `10.1.2.80`; `/tmp/my.sock` | `Recommended` If applicable for this messaging system. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the messaging intermediary node where the operation was performed. [17] | `10.1.2.80`; `/tmp/my.sock` | `Recommended` If applicable for this messaging system. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.port`](/docs/attributes-registry/network.md) | int | Peer port of the messaging intermediary node where the operation was performed. | `65123` | `Recommended` if and only if `network.peer.address` is set. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [16] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [18] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** The actual messaging system may differ from the one known by the client. For example, when using Kafka client libraries to communicate with Azure Event Hubs, the `messaging.system` is set to `kafka` based on the instrumentation's best knowledge. @@ -333,34 +354,38 @@ it's RECOMMENDED to: **[4]:** If the span describes an operation on a batch of messages. -**[5]:** If value is `true`. When missing, the value is assumed to be `false`. +**[5]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.consumer.group.name` is applicable and what it means in the context of that system. + +**[6]:** If value is `true`. When missing, the value is assumed to be `false`. -**[6]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If +**[7]:** Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If the broker doesn't have such notion, the destination name SHOULD uniquely identify the broker. -**[7]:** If span describes operation on a single message or if the value applies to all messages in the batch. +**[8]:** If span describes operation on a single message or if the value applies to all messages in the batch. + +**[9]:** Semantic conventions for individual messaging systems SHOULD document whether `messaging.destination.subscription.name` is applicable and what it means in the context of that system. -**[8]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. +**[10]:** Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation. -**[9]:** If available. Instrumentations MUST NOT use `messaging.destination.name` as template unless low-cardinality of destination name is guaranteed. +**[11]:** If available. Instrumentations MUST NOT use `messaging.destination.name` as template unless low-cardinality of destination name is guaranteed. -**[10]:** If value is `true`. When missing, the value is assumed to be `false`. +**[12]:** If value is `true`. When missing, the value is assumed to be `false`. -**[11]:** If a custom value is used, it MUST be of low cardinality. +**[13]:** If a custom value is used, it MUST be of low cardinality. -**[12]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. +**[14]:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. -**[13]:** This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed +**[15]:** This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed body size should be used. -**[14]:** This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed +**[16]:** This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed size should be used. -**[15]:** Semantic conventions for individual messaging systems SHOULD document whether `network.peer.*` attributes are applicable. +**[17]:** Semantic conventions for individual messaging systems SHOULD document whether `network.peer.*` attributes are applicable. Network peer address and port are important when the application interacts with individual intermediary nodes directly, If a messaging operation involved multiple network calls (for example retries), the address of the last contacted node SHOULD be used. -**[16]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. +**[18]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. diff --git a/docs/messaging/rocketmq.md b/docs/messaging/rocketmq.md index 5a1ef27f11..3c7d30f73c 100644 --- a/docs/messaging/rocketmq.md +++ b/docs/messaging/rocketmq.md @@ -25,8 +25,8 @@ Specific attributes for Apache RocketMQ are defined below. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| +| [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | RocketMQ [consumer group name](https://rocketmq.apache.org/docs/domainModel/07consumergroup). | `my-group`; `indexer` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.operation.name`](/docs/attributes-registry/messaging.md) | string | The system-specific name of the messaging operation. | `ack`; `nack`; `send` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.rocketmq.client_group`](/docs/attributes-registry/messaging.md) | string | Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind. | `myConsumerGroup` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.rocketmq.namespace`](/docs/attributes-registry/messaging.md) | string | Namespace of RocketMQ resources, resources in different namespaces are individual. | `myNamespace` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `amqp:decode-error`; `KAFKA_STORAGE_ERROR`; `channel-error` | `Conditionally Required` If and only if the messaging operation has failed. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.batch.message_count`](/docs/attributes-registry/messaging.md) | int | The number of messages sent, received, or processed in the scope of the batching operation. [2] | `0`; `1`; `2` | `Conditionally Required` [3] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | diff --git a/model/metrics/messaging-metrics.yaml b/model/metrics/messaging-metrics.yaml index 7696691375..5dd4891fb9 100644 --- a/model/metrics/messaging-metrics.yaml +++ b/model/metrics/messaging-metrics.yaml @@ -15,6 +15,19 @@ groups: requirement_level: conditionally_required: if available. + - id: metric.messaging.consumer.attributes + type: attribute_group + stability: experimental + brief: "Messaging consumer metrics attributes." + extends: metric.messaging.attributes + attributes: + - ref: messaging.consumer.group.name + requirement_level: + conditionally_required: if applicable. + - ref: messaging.destination.subscription.name + requirement_level: + conditionally_required: if applicable. + # durations - id: metric.messaging.client.operation.duration type: metric @@ -25,7 +38,7 @@ groups: stability: experimental instrument: histogram unit: "s" - extends: metric.messaging.attributes + extends: metric.messaging.consumer.attributes attributes: - ref: messaging.operation.type requirement_level: @@ -42,7 +55,7 @@ groups: stability: experimental instrument: histogram unit: "s" - extends: metric.messaging.attributes + extends: metric.messaging.consumer.attributes attributes: - ref: messaging.operation.name examples: ["process", "consume", "handle"] @@ -75,7 +88,7 @@ groups: stability: experimental instrument: counter unit: "{message}" - extends: metric.messaging.attributes + extends: metric.messaging.consumer.attributes attributes: - ref: messaging.operation.name examples: ["receive", "peek", "poll", "consume"] diff --git a/model/registry/deprecated/messaging.yaml b/model/registry/deprecated/messaging.yaml index 2b3c0aad78..5f477018ad 100644 --- a/model/registry/deprecated/messaging.yaml +++ b/model/registry/deprecated/messaging.yaml @@ -24,3 +24,35 @@ groups: Deprecated, use `messaging.client.id` instead. examples: ['client-5', 'myhost@8742@s8083jm'] deprecated: "Replaced by `messaging.client.id`." + - id: messaging.kafka.consumer.group + type: string + brief: > + Deprecated, use `messaging.consumer.group.name` instead. + deprecated: > + Replaced by `messaging.consumer.group.name`. + stability: experimental + examples: 'my-group' + - id: messaging.rocketmq.client_group + type: string + brief: > + Deprecated, use `messaging.consumer.group.name` instead. + stability: experimental + examples: 'myConsumerGroup' + deprecated: > + Replaced by `messaging.consumer.group.name` on the consumer spans. No replacement for producer spans. + - id: messaging.eventhubs.consumer.group + type: string + brief: > + Deprecated, use `messaging.consumer.group.name` instead. + stability: experimental + examples: '$Default' + deprecated: > + Replaced by `messaging.consumer.group.name`. + - id: messaging.servicebus.destination.subscription_name + type: string + brief: > + Deprecated, use `messaging.servicebus.destination.subscription_name` instead. + stability: experimental + examples: 'subscription-a' + deprecated: > + Replaced by `messaging.servicebus.destination.subscription_name`. diff --git a/model/registry/messaging.yaml b/model/registry/messaging.yaml index a2444e42a9..5c95891653 100644 --- a/model/registry/messaging.yaml +++ b/model/registry/messaging.yaml @@ -19,6 +19,15 @@ groups: brief: > A unique identifier for the client that consumes or produces a message. examples: ['client-5', 'myhost@8742@s8083jm'] + - id: consumer.group.name + type: string + stability: experimental + brief: > + The name of the consumer group with which a consumer is associated. + note: > + Semantic conventions for individual messaging systems SHOULD document whether `messaging.consumer.group.name` + is applicable and what it means in the context of that system. + examples: ['my-group', 'indexer'] - id: destination.name type: string stability: experimental @@ -27,6 +36,15 @@ groups: Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If the broker doesn't have such notion, the destination name SHOULD uniquely identify the broker. examples: ['MyQueue', 'MyTopic'] + tag: messaging-generic + - id: destination.subscription.name + type: string + stability: experimental + brief: 'The name of the destination subscription from which a message is consumed.' + note: > + Semantic conventions for individual messaging systems SHOULD document whether `messaging.destination.subscription.name` + is applicable and what it means in the context of that system. + examples: ['subscription-a'] - id: destination.template type: string stability: experimental @@ -202,13 +220,6 @@ groups: brief: > This group describes attributes specific to Apache Kafka. attributes: - - id: kafka.consumer.group - type: string - stability: experimental - brief: > - Name of the Kafka Consumer Group that is handling the message. - Only applies to consumers, not producers. - examples: 'my-group' - id: kafka.message.key type: string stability: experimental @@ -254,12 +265,6 @@ groups: brief: > This group describes attributes specific to RocketMQ. attributes: - - id: rocketmq.client_group - type: string - stability: experimental - brief: > - Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind. - examples: 'myConsumerGroup' - id: rocketmq.consumption_model type: allow_custom_values: false @@ -382,12 +387,6 @@ groups: brief: > The UTC epoch seconds at which the message has been accepted and stored in the entity. examples: 1701393730 - - id: servicebus.destination.subscription_name - type: string - stability: experimental - brief: > - The name of the subscription in the topic messages are received from. - examples: "mySubscription" - id: servicebus.disposition_status brief: > Describes the [settlement type](https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock). @@ -423,9 +422,3 @@ groups: brief: > The UTC epoch seconds at which the message has been accepted and stored in the entity. examples: 1701393730 - - id: eventhubs.consumer.group - type: string - stability: experimental - brief: > - The name of the consumer group the event consumer is associated with. - examples: 'indexer' diff --git a/model/trace/messaging.yaml b/model/trace/messaging.yaml index aa9ba22c2e..662d570f8d 100644 --- a/model/trace/messaging.yaml +++ b/model/trace/messaging.yaml @@ -89,6 +89,12 @@ groups: - ref: messaging.destination.anonymous requirement_level: conditionally_required: If value is `true`. When missing, the value is assumed to be `false`. + - ref: messaging.consumer.group.name + requirement_level: + conditionally_required: If applicable. + - ref: messaging.destination.subscription.name + requirement_level: + conditionally_required: If applicable. - ref: messaging.message.conversation_id - ref: messaging.message.envelope.size - ref: messaging.message.body.size @@ -145,6 +151,9 @@ groups: brief: > Attributes for Apache Kafka attributes: + - ref: messaging.consumer.group.name + brief: "Kafka [consumer group id](https://docs.confluent.io/platform/current/clients/consumer.html)." + note: "" - ref: messaging.destination.partition.id brief: > String representation of the partition id the message (or batch) is sent to or received from. @@ -152,7 +161,6 @@ groups: - ref: messaging.kafka.message.key requirement_level: recommended: If span describes operation on a single message. - - ref: messaging.kafka.consumer.group - ref: messaging.kafka.message.offset requirement_level: recommended: If span describes operation on a single message. @@ -173,9 +181,11 @@ groups: brief: > Attributes for Apache RocketMQ attributes: - - ref: messaging.rocketmq.namespace + - ref: messaging.consumer.group.name + brief: "RocketMQ [consumer group name](https://rocketmq.apache.org/docs/domainModel/07consumergroup)." + note: "" requirement_level: required - - ref: messaging.rocketmq.client_group + - ref: messaging.rocketmq.namespace requirement_level: required - ref: messaging.rocketmq.message.delivery_timestamp requirement_level: @@ -203,6 +213,9 @@ groups: brief: > Attributes for Google Cloud Pub/Sub attributes: + - ref: messaging.destination.subscription.name + brief: "Google Pub/Sub [subscription name](https://cloud.google.com/pubsub/docs/subscription-overview)." + note: "" - ref: messaging.gcp_pubsub.message.ordering_key requirement_level: conditionally_required: If the message type has an ordering key set. @@ -228,13 +241,15 @@ groups: brief: > Attributes for Azure Service Bus attributes: + - ref: messaging.destination.subscription.name + brief: "Azure Service Bus [subscription name](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-queues-topics-subscriptions#topics-and-subscriptions)." + note: "" + requirement_level: + conditionally_required: If messages are received from the subscription. - ref: messaging.servicebus.message.delivery_count requirement_level: conditionally_required: If delivery count is available and is bigger than 0. - ref: messaging.servicebus.message.enqueued_time - - ref: messaging.servicebus.destination.subscription_name - requirement_level: - conditionally_required: If messages are received from the subscription. - ref: messaging.servicebus.disposition_status requirement_level: conditionally_required: if and only if `messaging.operation` is `settle`. @@ -265,15 +280,17 @@ groups: brief: > Attributes for Azure Event Hubs attributes: + - ref: messaging.consumer.group.name + brief: "Azure Event Hubs [consumer group name](https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-features#consumer-groups)." + note: "" + requirement_level: + conditionally_required: On consumer spans. - ref: messaging.destination.partition.id brief: > String representation of the partition id messages are sent to or received from, unique within the Event Hub. requirement_level: conditionally_required: If available. - ref: messaging.eventhubs.message.enqueued_time - - ref: messaging.eventhubs.consumer.group - requirement_level: - conditionally_required: If not default ("$Default"). - ref: messaging.batch.message_count requirement_level: conditionally_required: If the span describes an operation on a batch of messages. diff --git a/schema-next.yaml b/schema-next.yaml index d9c151b35f..9469bc54eb 100644 --- a/schema-next.yaml +++ b/schema-next.yaml @@ -2,6 +2,15 @@ file_format: 1.1.0 schema_url: https://opentelemetry.io/schemas/next versions: next: + all: + changes: + # https://github.com/open-telemetry/semantic-conventions/pull/815 + - rename_attributes: + attribute_map: + messaging.kafka.consumer.group: messaging.consumer.group.name + messaging.rocketmq.client_group: messaging.consumer.group.name + messaging.evenhubs.consumer.group: messaging.consumer.group.name + message.servicebus.destination.subscription_name: messaging.destination.subscription.name spans: changes: # https://github.com/open-telemetry/semantic-conventions/pull/1002