# Semantic conventions for Azure messaging systems **Status**: [Development][DocumentStatus] The Semantic Conventions for [Azure Service Bus](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-messaging-overview) and [Azure Event Hubs](https://learn.microsoft.com/azure/event-hubs/event-hubs-about) extend and override the [Messaging Semantic Conventions](README.md). > [!Warning] > > Existing messaging instrumentations that are using > [v1.24.0 of this document](https://github.com/open-telemetry/semantic-conventions/blob/v1.24.0/docs/messaging/messaging-spans.md) > (or prior): > > * SHOULD NOT change the version of the messaging conventions that they emit by default > until the messaging semantic conventions are marked stable. > Conventions include, but are not limited to, attributes, > metric and span names, span kind and unit of measure. > * SHOULD introduce an environment variable `OTEL_SEMCONV_STABILITY_OPT_IN` > in the existing major version as a comma-separated list of category-specific values > (e.g., http, databases, messaging). The list of values includes: > * `messaging` - emit the new, stable messaging conventions, > and stop emitting the old experimental messaging conventions > that the instrumentation emitted previously. > * `messaging/dup` - emit both the old and the stable messaging conventions, > allowing for a seamless transition. > * The default behavior (in the absence of one of these values) is to continue > emitting whatever version of the old experimental messaging conventions > the instrumentation was emitting previously. > * Note: `messaging/dup` has higher precedence than `messaging` in case both values are present > * SHOULD maintain (security patching at a minimum) the existing major version > for at least six months after it starts emitting both sets of conventions. > * SHOULD drop the environment variable in the next major version. > * SHOULD emit the new, stable values for span name, span kind and similar "single" > valued concepts when `messaging/dup` is present in the list. ## Azure Service Bus `messaging.system` MUST be set to `"servicebus"` and SHOULD be provided **at span creation time**. ### Span attributes The following additional attributes are defined: | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| | [`messaging.operation.name`](/docs/attributes-registry/messaging.md) | string | Azure Service Bus operation name. [1] | `send`; `receive`; `complete`; `process`; `peek` | `Required` | ![Development](https://img.shields.io/badge/-development-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] | ![Development](https://img.shields.io/badge/-development-blue) | | [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [5] | `MyQueue`; `MyTopic` | `Conditionally Required` [6] | ![Development](https://img.shields.io/badge/-development-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. | ![Development](https://img.shields.io/badge/-development-blue) | | [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [7] | `create`; `send`; `receive` | `Conditionally Required` If applicable. | ![Development](https://img.shields.io/badge/-development-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`. | ![Development](https://img.shields.io/badge/-development-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] | ![Development](https://img.shields.io/badge/-development-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.message.conversation_id`](/docs/attributes-registry/messaging.md) | string | Message [correlation Id](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-messages-payloads#message-routing-and-correlation) property. | `MyConversationId` | `Recommended` | ![Development](https://img.shields.io/badge/-development-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. | ![Development](https://img.shields.io/badge/-development-blue) | | [`messaging.servicebus.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` | ![Development](https://img.shields.io/badge/-development-blue) | | [`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] `messaging.operation.name`:** The operation name SHOULD match one of the following values: - sender operations: `send`, `schedule`, `cancel_scheduled` - transaction operations: `create_transaction`, `commit_transaction`, `rollback_transaction` - receiver operation: `receive`, `peek`, `receive_deferred`, `renew_message_lock` - settlement operations: `abandon`, `complete`, `defer`, `dead_letter`, `delete` - session operations: `accept_session`, `get_session_state`, `set_session_state`, `renew_session_lock` If none of the above operation names apply, the attribute SHOULD be set to the name of the client method in snake_case. **[2] `error.type`:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. When `error.type` is set to a type (e.g., an exception type), its canonical class name identifying the type within the artifact SHOULD be used. 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. **[3] `messaging.batch.message_count`:** 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. **[4] `messaging.batch.message_count`:** If the span describes an operation on a batch of messages. **[5] `messaging.destination.name`:** 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. **[6] `messaging.destination.name`:** If span describes operation on a single message or if the value applies to all messages in the batch. **[7] `messaging.operation.type`:** If a custom value is used, it MUST be of low cardinality. **[8] `messaging.servicebus.message.delivery_count`:** If delivery count is available and is bigger than 0. **[9] `server.address`:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. **[10] `server.port`:** 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. The following attributes can be important for making sampling decisions and SHOULD be provided **at span creation time** (if provided at all): * [`messaging.destination.name`](/docs/attributes-registry/messaging.md) * [`messaging.destination.subscription.name`](/docs/attributes-registry/messaging.md) * [`messaging.operation.name`](/docs/attributes-registry/messaging.md) * [`messaging.operation.type`](/docs/attributes-registry/messaging.md) * [`server.address`](/docs/attributes-registry/server.md) * [`server.port`](/docs/attributes-registry/server.md) --- `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) | --- `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. | Value | Description | Stability | |---|---|---| | `create` | A message is created. "Create" spans always refer to a single message and are used to provide a unique creation context for messages in batch sending scenarios. | ![Development](https://img.shields.io/badge/-development-blue) | | `process` | One or more messages are processed by a consumer. | ![Development](https://img.shields.io/badge/-development-blue) | | `receive` | One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages. | ![Development](https://img.shields.io/badge/-development-blue) | | `send` | One or more messages are provided for sending to an intermediary. If a single message is sent, the context of the "Send" span can be used as the creation context and no "Create" span needs to be created. | ![Development](https://img.shields.io/badge/-development-blue) | | `settle` | One or more messages are settled. | ![Development](https://img.shields.io/badge/-development-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. | Value | Description | Stability | |---|---|---| | `abandon` | Message is abandoned | ![Development](https://img.shields.io/badge/-development-blue) | | `complete` | Message is completed | ![Development](https://img.shields.io/badge/-development-blue) | | `dead_letter` | Message is sent to dead letter queue | ![Development](https://img.shields.io/badge/-development-blue) | | `defer` | Message is deferred | ![Development](https://img.shields.io/badge/-development-blue) | ## Azure Event Hubs `messaging.system` MUST be set to `"eventhubs"` and SHOULD be provided **at span creation time**. ### Span attributes The following additional attributes are defined: | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| | [`messaging.operation.name`](/docs/attributes-registry/messaging.md) | string | Azure Event Hubs operation name. [1] | `send`; `receive`; `checkpoint` | `Required` | ![Development](https://img.shields.io/badge/-development-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] | ![Development](https://img.shields.io/badge/-development-blue) | | [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) | string | Azure Event Hubs [consumer group name](https://learn.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). | `my-group`; `indexer` | `Conditionally Required` On consumer spans. | ![Development](https://img.shields.io/badge/-development-blue) | | [`messaging.destination.name`](/docs/attributes-registry/messaging.md) | string | The message destination name [5] | `MyQueue`; `MyTopic` | `Conditionally Required` [6] | ![Development](https://img.shields.io/badge/-development-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. | ![Development](https://img.shields.io/badge/-development-blue) | | [`messaging.operation.type`](/docs/attributes-registry/messaging.md) | string | A string identifying the type of the messaging operation. [7] | `create`; `send`; `receive` | `Conditionally Required` If applicable. | ![Development](https://img.shields.io/badge/-development-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` | ![Development](https://img.shields.io/badge/-development-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. | ![Development](https://img.shields.io/badge/-development-blue) | | [`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] `messaging.operation.name`:** The operation name SHOULD match one of the following values: - `send` - `receive` - `process` - `checkpoint` - `get_partition_properties` - `get_event_hub_properties` If none of the above operation names apply, the attribute SHOULD be set to the name of the client method in snake_case. **[2] `error.type`:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. When `error.type` is set to a type (e.g., an exception type), its canonical class name identifying the type within the artifact SHOULD be used. 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. **[3] `messaging.batch.message_count`:** 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. **[4] `messaging.batch.message_count`:** If the span describes an operation on a batch of messages. **[5] `messaging.destination.name`:** 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. **[6] `messaging.destination.name`:** If span describes operation on a single message or if the value applies to all messages in the batch. **[7] `messaging.operation.type`:** If a custom value is used, it MUST be of low cardinality. **[8] `server.address`:** Server domain name of the broker if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. **[9] `server.port`:** 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. The following attributes can be important for making sampling decisions and SHOULD be provided **at span creation time** (if provided at all): * [`messaging.consumer.group.name`](/docs/attributes-registry/messaging.md) * [`messaging.destination.name`](/docs/attributes-registry/messaging.md) * [`messaging.destination.partition.id`](/docs/attributes-registry/messaging.md) * [`messaging.operation.name`](/docs/attributes-registry/messaging.md) * [`messaging.operation.type`](/docs/attributes-registry/messaging.md) * [`server.address`](/docs/attributes-registry/server.md) * [`server.port`](/docs/attributes-registry/server.md) --- `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) | --- `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. | Value | Description | Stability | |---|---|---| | `create` | A message is created. "Create" spans always refer to a single message and are used to provide a unique creation context for messages in batch sending scenarios. | ![Development](https://img.shields.io/badge/-development-blue) | | `process` | One or more messages are processed by a consumer. | ![Development](https://img.shields.io/badge/-development-blue) | | `receive` | One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages. | ![Development](https://img.shields.io/badge/-development-blue) | | `send` | One or more messages are provided for sending to an intermediary. If a single message is sent, the context of the "Send" span can be used as the creation context and no "Create" span needs to be created. | ![Development](https://img.shields.io/badge/-development-blue) | | `settle` | One or more messages are settled. | ![Development](https://img.shields.io/badge/-development-blue) | [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status