From 2810697a958bcc7fdf155d5196f8614d5e0c5053 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 18 Apr 2024 16:57:37 -0700 Subject: [PATCH] add subscription name --- docs/attributes-registry/messaging.md | 33 ++++++----- docs/messaging/azure-messaging.md | 12 ++-- docs/messaging/messaging-metrics.md | 70 ++++++++++++++++++++++-- docs/messaging/messaging-spans.md | 59 +++++++++++++------- docs/messaging/rocketmq.md | 12 ++-- model/metrics/messaging.yaml | 3 + model/registry/deprecated/messaging.yaml | 16 ++++++ model/registry/messaging.yaml | 14 ++++- model/trace/messaging.yaml | 40 +++++++------- 9 files changed, 191 insertions(+), 68 deletions(-) diff --git a/docs/attributes-registry/messaging.md b/docs/attributes-registry/messaging.md index beb0555c73..e2b4c62f4e 100644 --- a/docs/attributes-registry/messaging.md +++ b/docs/attributes-registry/messaging.md @@ -23,39 +23,44 @@ |---|---|---|---|---| | `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 message or batch consumer is associated with. | `my-group`; `indexer` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.consumer.group.name` | string | The name of the group messaging consumer is associated with. [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 topic subscription message is consumed from. [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` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `messaging.operation.type` | string | A string identifying the type of the messaging operation. [9] | `publish` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `messaging.system` | string | An identifier for the messaging system being used. See below for a list of well-known identifiers. | `activemq` | ![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. `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. @@ -175,8 +180,10 @@ size should be used. | Attribute | Type | Description | Examples | Stability | |---|---|---|---|---| +| `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`. | \ No newline at end of file diff --git a/docs/messaging/azure-messaging.md b/docs/messaging/azure-messaging.md index 0ea386a653..75c6883a0b 100644 --- a/docs/messaging/azure-messaging.md +++ b/docs/messaging/azure-messaging.md @@ -18,12 +18,14 @@ The following additional attributes are defined: | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the Service Bus topic subscription. | `my-group`; `indexer` | `Conditionally Required` If messages are received from the subscription. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.subscription.name`](../attributes-registry/messaging.md) | string | The name of the topic subscription message is consumed from. [1] | `subscription-a` | `Conditionally Required` If messages are received from the subscription. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.servicebus.disposition_status`](../attributes-registry/messaging.md) | string | Describes the [settlement type](https://learn.microsoft.com/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock). | `complete` | `Conditionally Required` if and only if `messaging.operation` is `settle`. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.servicebus.message.delivery_count`](../attributes-registry/messaging.md) | int | Number of deliveries that have been attempted for this message. | `2` | `Conditionally Required` [1] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.servicebus.message.delivery_count`](../attributes-registry/messaging.md) | int | Number of deliveries that have been attempted for this message. | `2` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.servicebus.message.enqueued_time`](../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) | -**[1]:** If delivery count is available and is bigger than 0. +**[1]:** The `messaging.destination.subscription.name` SHOULD be set to the Azure Service Bus [subscription name](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-queues-topics-subscriptions#topics-and-subscriptions). + +**[2]:** If delivery count is available and is bigger than 0. ## Azure Event Hubs @@ -36,11 +38,11 @@ The following additional attributes are defined: | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the consumer group message or batch consumer is associated with. | `my-group`; `indexer` | `Conditionally Required` [1] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the group messaging consumer is associated with. [1] | `my-group`; `indexer` | `Conditionally Required` On consumer spans. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.partition.id`](../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.message.enqueued_time`](../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) | -**[1]:** On consumer spans and if not default (`$Default``). +**[1]:** The `messaging.consumer.group.name` SHOULD be set to the Azure Event Hubs [consumer group name](https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-features#consumer-groups). [DocumentStatus]: https://github.com/open-telemetry/opentelemetry-specification/tree/v1.31.0/specification/document-status.md diff --git a/docs/messaging/messaging-metrics.md b/docs/messaging/messaging-metrics.md index 800fa92128..e08b2c7523 100644 --- a/docs/messaging/messaging-metrics.md +++ b/docs/messaging/messaging-metrics.md @@ -11,7 +11,7 @@ - [Metric: `messaging.publish.duration`](#metric-messagingpublishduration) - [Metric: `messaging.publish.messages`](#metric-messagingpublishmessages) - [Consumer metrics](#consumer-metrics) - - [Consumer attributes](#consumer-attributes) +- [Consumer attributes](#consumer-attributes) - [Metric: `messaging.receive.duration`](#metric-messagingreceiveduration) - [Metric: `messaging.receive.messages`](#metric-messagingreceivemessages) - [Metric: `messaging.process.duration`](#metric-messagingprocessduration) @@ -126,12 +126,74 @@ This metric is [required][MetricRequired] when the messaging system supports bat ## Consumer attributes -The following attributes are reported in addition to [common attributes](#common-attributes) on consumer metrics. +The following attributes are reported on the consumer metrics. - + | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the consumer group message or batch consumer is associated with. | `my-group`; `indexer` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.system`](../attributes-registry/messaging.md) | string | An identifier for the messaging system being used. See below for a list of well-known identifiers. | `activemq` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`error.type`](../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` [2] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the group messaging consumer is associated with. [3] | `my-group`; `indexer` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.name`](../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`](../attributes-registry/messaging.md) | string | The name of the topic subscription message is consumed from. [6] | `subscription-a` | `Conditionally Required` if available. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.template`](../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`](../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`](../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`](../attributes-registry/server.md) | int | Server port number. [9] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + +**[1]:** The `error.type` SHOULD be predictable and SHOULD have low cardinality. +Instrumentations SHOULD document the list of errors they report. + +The cardinality of `error.type` within one instrumentation library SHOULD be low. +Telemetry consumers that aggregate data from multiple instrumentation libraries and applications +should be prepared for `error.type` to have high cardinality at query time when no +additional filters are applied. + +If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. + +If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), +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. + +**[2]:** If and only if the messaging operation has failed. + +**[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. + +**[5]:** if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated. + +**[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. + +**[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. + +**[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. + +`messaging.system` 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. + +| Value | Description | Stability | +|---|---|---| +| `activemq` | Apache ActiveMQ | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `aws_sqs` | Amazon Simple Queue Service (SQS) | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `eventgrid` | Azure Event Grid | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `eventhubs` | Azure Event Hubs | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `servicebus` | Azure Service Bus | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `gcp_pubsub` | Google Cloud Pub/Sub | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `jms` | Java Message Service | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `kafka` | Apache Kafka | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rabbitmq` | RabbitMQ | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rocketmq` | Apache RocketMQ | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +`error.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. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | ### Metric: `messaging.receive.duration` diff --git a/docs/messaging/messaging-spans.md b/docs/messaging/messaging-spans.md index 3564d8771e..066cf24659 100644 --- a/docs/messaging/messaging-spans.md +++ b/docs/messaging/messaging-spans.md @@ -104,6 +104,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*. @@ -290,22 +307,23 @@ as described in [Attributes specific to certain messaging systems](#attributes-s | [`messaging.system`](../attributes-registry/messaging.md) | string | An identifier for the messaging system being used. See below for a list of well-known identifiers. | `activemq` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`error.type`](../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` [3] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`messaging.batch.message_count`](../attributes-registry/messaging.md) | int | The number of messages sent, received, or processed in the scope of the batching operation. [4] | `0`; `1`; `2` | `Conditionally Required` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the consumer group message or batch consumer is associated with. [6] | `my-group`; `indexer` | `Conditionally Required` On consumer spans. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the group messaging consumer is associated with. [6] | `my-group`; `indexer` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.anonymous`](../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` [7] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.name`](../attributes-registry/messaging.md) | string | The message destination name [8] | `MyQueue`; `MyTopic` | `Conditionally Required` [9] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.destination.template`](../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`](../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) | -| [`server.address`](../attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [13] | `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`](../attributes-registry/messaging.md) | string | The name of the topic subscription message is consumed from. [10] | `subscription-a` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.template`](../attributes-registry/messaging.md) | string | Low cardinality representation of the messaging destination name [11] | `/customers/{customerId}` | `Conditionally Required` [12] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.destination.temporary`](../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` [13] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`server.address`](../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`](../attributes-registry/messaging.md) | string | A unique identifier for the client that consumes or produces a message. | `client-5`; `myhost@8742@s8083jm` | `Recommended` If a client id is available | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.destination.partition.id`](../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`](../attributes-registry/messaging.md) | int | The size of the message body in bytes. [14] | `1439` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.message.body.size`](../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`](../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`](../attributes-registry/messaging.md) | int | The size of the message body and metadata in bytes. [15] | `2738` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.message.envelope.size`](../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`](../attributes-registry/messaging.md) | string | A value used by the messaging system as an identifier for the message, represented as a string. | `452a7c7c7c7048c2f887f61572b18fc2` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.operation.name`](../attributes-registry/messaging.md) | string | The system-specific name of the messaging operation. | `ack`; `nack`; `send` | `Recommended` [16] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`network.peer.address`](../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) | +| [`messaging.operation.name`](../attributes-registry/messaging.md) | string | The system-specific name of the messaging operation. | `ack`; `nack`; `send` | `Recommended` [17] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`network.peer.address`](../attributes-registry/network.md) | string | Peer address of the messaging intermediary node where the operation was performed. [18] | `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`](../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`](../attributes-registry/server.md) | int | Server port number. [18] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](../attributes-registry/server.md) | int | Server port number. [19] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** If a custom value is used, it MUST be of low cardinality. @@ -331,8 +349,7 @@ it's RECOMMENDED to: **[5]:** If the span describes an operation on a batch of messages. -**[6]:** Consumer groups are used to distribute messages to one or more consumer instances and are commonly used in fan-out (aka one-to-many) scenarios. When multiple consumer groups are used, message is delivered to each group separately, allowing different applications to consume the same message at their own pace. -Some messaging systems such as Apache Pulsar, GCP PubSub or Azure Service Bus use the term "subscription" instead of "consumer group". +**[6]:** 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. **[7]:** If value is `true`. When missing, the value is assumed to be `false`. @@ -341,27 +358,29 @@ the broker doesn't have such notion, the destination name SHOULD uniquely identi **[9]:** If span describes operation on a single message or if the value applies to all messages in the batch. -**[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. +**[10]:** 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. + +**[11]:** 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. -**[11]:** If available. Instrumentations MUST NOT use `messaging.destination.name` as template unless low-cardinality of destination name is guaranteed. +**[12]:** If available. Instrumentations MUST NOT use `messaging.destination.name` as template unless low-cardinality of destination name is guaranteed. -**[12]:** If value is `true`. When missing, the value is assumed to be `false`. +**[13]:** If value is `true`. When missing, the value is assumed to be `false`. -**[13]:** 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. -**[14]:** 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. -**[15]:** 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. -**[16]:** If the operation is not sufficiently described by `messaging.operation.type`. +**[17]:** If the operation is not sufficiently described by `messaging.operation.type`. -**[17]:** Semantic conventions for individual messaging systems SHOULD document whether `network.peer.*` attributes are applicable. +**[18]:** 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. -**[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. +**[19]:** 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. `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. diff --git a/docs/messaging/rocketmq.md b/docs/messaging/rocketmq.md index b8ae5e9eaf..9ac0760950 100644 --- a/docs/messaging/rocketmq.md +++ b/docs/messaging/rocketmq.md @@ -20,18 +20,20 @@ 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.rocketmq.namespace`](../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) | -| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the consumer group message or batch consumer is associated with. | `my-group`; `indexer` | `Conditionally Required` On consumer spans. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.rocketmq.message.delay_time_level`](../attributes-registry/messaging.md) | int | The delay time level for delay message, which determines the message delay time. | `3` | `Conditionally Required` [1] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`messaging.rocketmq.message.delivery_timestamp`](../attributes-registry/messaging.md) | int | The timestamp in milliseconds that the delay message is expected to be delivered to consumer. | `1665987217045` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.consumer.group.name`](../attributes-registry/messaging.md) | string | The name of the group messaging consumer is associated with. [1] | `my-group`; `indexer` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.rocketmq.message.delay_time_level`](../attributes-registry/messaging.md) | int | The delay time level for delay message, which determines the message delay time. | `3` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`messaging.rocketmq.message.delivery_timestamp`](../attributes-registry/messaging.md) | int | The timestamp in milliseconds that the delay message is expected to be delivered to consumer. | `1665987217045` | `Conditionally Required` [3] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.rocketmq.message.group`](../attributes-registry/messaging.md) | string | It is essential for FIFO message. Messages that belong to the same message group are always processed one by one within the same consumer group. | `myMessageGroup` | `Conditionally Required` If the message type is FIFO. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.rocketmq.consumption_model`](../attributes-registry/messaging.md) | string | Model of message consumption. This only applies to consumer spans. | `clustering` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.rocketmq.message.keys`](../attributes-registry/messaging.md) | string[] | Key(s) of message, another way to mark message besides message id. | `[keyA, keyB]` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.rocketmq.message.tag`](../attributes-registry/messaging.md) | string | The secondary classifier of message besides topic. | `tagA` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`messaging.rocketmq.message.type`](../attributes-registry/messaging.md) | string | Type of message. | `normal` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[1]:** If the message type is delay and delivery timestamp is not specified. +**[1]:** The `messaging.consumer.group.name` SHOULD be set to the RocketMQ [consumer group name](https://rocketmq.apache.org/docs/domainModel/07consumergroup). -**[2]:** If the message type is delay and delay time level is not specified. +**[2]:** If the message type is delay and delivery timestamp is not specified. + +**[3]:** If the message type is delay and delay time level is not specified. `messaging.rocketmq.consumption_model` MUST be one of the following: diff --git a/model/metrics/messaging.yaml b/model/metrics/messaging.yaml index d7ab8841d6..72dba14331 100644 --- a/model/metrics/messaging.yaml +++ b/model/metrics/messaging.yaml @@ -21,6 +21,9 @@ groups: - ref: messaging.consumer.group.name requirement_level: conditionally_required: if available. + - ref: messaging.destination.subscription.name + requirement_level: + conditionally_required: if available. # durations - id: metric.messaging.publish.duration diff --git a/model/registry/deprecated/messaging.yaml b/model/registry/deprecated/messaging.yaml index e313a43ae9..8f96871dcf 100644 --- a/model/registry/deprecated/messaging.yaml +++ b/model/registry/deprecated/messaging.yaml @@ -34,4 +34,20 @@ groups: 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 2418943bac..0abb0df8f8 100644 --- a/model/registry/messaging.yaml +++ b/model/registry/messaging.yaml @@ -25,7 +25,10 @@ groups: type: string stability: experimental brief: > - The name of the consumer group message or batch consumer is associated with. + The name of the group messaging consumer is associated with. + 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'] tag: messaging-generic - id: destination.name @@ -37,6 +40,15 @@ groups: 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 topic subscription message is consumed from.' + 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'] + tag: messaging-generic - id: destination.template type: string stability: experimental diff --git a/model/trace/messaging.yaml b/model/trace/messaging.yaml index 3f34cffc4d..b07a6bcd20 100644 --- a/model/trace/messaging.yaml +++ b/model/trace/messaging.yaml @@ -61,7 +61,7 @@ groups: recommended: If the operation is not sufficiently described by `messaging.operation.type`. - ref: messaging.consumer.group.name requirement_level: - conditionally_required: On consumer spans. + conditionally_required: If applicable. - ref: messaging.batch.message_count requirement_level: conditionally_required: If the span describes an operation on a batch of messages. @@ -85,6 +85,9 @@ groups: - ref: messaging.destination.anonymous requirement_level: conditionally_required: If value is `true`. When missing, the value is assumed to be `false`. + - ref: messaging.destination.subscription.name + requirement_level: + conditionally_required: If applicable. - ref: messaging.message.id - ref: messaging.message.conversation_id - ref: messaging.message.envelope.size @@ -122,19 +125,7 @@ groups: This document defines general attributes used in messaging systems. extends: messaging.span.attributes - attributes: - # TODO: merge messaging group with messaging.span.attributes - # and move the note to the registry once - # https://github.com/open-telemetry/build-tools/issues/299 is resolved - - ref: messaging.consumer.group.name - note: - Consumer groups are used to distribute messages to one or more consumer instances and - are commonly used in fan-out (aka one-to-many) scenarios. - When multiple consumer groups are used, message is delivered to each group separately, allowing different applications - to consume the same message at their own pace. - Some messaging systems such as Apache Pulsar, GCP PubSub or Azure Service Bus use the term "subscription" - instead of "consumer group". - id: messaging.rabbitmq type: attribute_group @@ -162,6 +153,8 @@ groups: Attributes for Apache Kafka attributes: - ref: messaging.consumer.group.name + note: > + The `messaging.consumer.group.name` SHOULD be set to the Kafka [consumer group id](https://docs.confluent.io/platform/current/clients/consumer.html). tag: tech-specific-kafka - ref: messaging.destination.partition.id brief: > @@ -184,6 +177,8 @@ groups: Attributes for Apache RocketMQ attributes: - ref: messaging.consumer.group.name + note: > + The `messaging.consumer.group.name` SHOULD be set to the RocketMQ [consumer group name](https://rocketmq.apache.org/docs/domainModel/07consumergroup). tag: tech-specific - ref: messaging.rocketmq.namespace requirement_level: required @@ -214,9 +209,10 @@ groups: brief: > Attributes for Google Cloud Pub/Sub attributes: - - ref: messaging.consumer.group.name - brief: > - The name of the Pub/Sub topic subscription. + - ref: messaging.destination.subscription.name + note: > + The `messaging.destination.subscription.name` SHOULD be set to the Google Pub/Sub + [subscription name](https://cloud.google.com/pubsub/docs/subscription-overview). tag: tech-specific-gcp-pubsub - ref: messaging.gcp_pubsub.message.ordering_key tag: tech-specific @@ -228,9 +224,10 @@ groups: brief: > Attributes for Azure Service Bus attributes: - - ref: messaging.consumer.group.name - brief: > - The name of the Service Bus topic subscription. + - ref: messaging.destination.subscription.name + note: > + The `messaging.destination.subscription.name` SHOULD be set to the Azure Service Bus + [subscription name](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-queues-topics-subscriptions#topics-and-subscriptions). requirement_level: conditionally_required: If messages are received from the subscription. - ref: messaging.servicebus.message.delivery_count @@ -247,8 +244,11 @@ groups: Attributes for Azure Event Hubs attributes: - ref: messaging.consumer.group.name + note: > + The `messaging.consumer.group.name` SHOULD be set to the Azure Event Hubs + [consumer group name](https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-features#consumer-groups). requirement_level: - conditionally_required: On consumer spans and if not default (`$Default``). + 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.