From 262271ffb3152b3b2442e376d6833dd3a355ca60 Mon Sep 17 00:00:00 2001 From: Alexandra Konrad <10500694+trisch-me@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:30:25 +0200 Subject: [PATCH 1/6] move rpc.message to the registry (#854) Co-authored-by: Liudmila Molkova Co-authored-by: Alexander Wert Co-authored-by: Joao Grassi <5938087+joaopgrassi@users.noreply.github.com> --- .chloggen/rpc_registry.yaml | 22 ++++++++++++++ docs/attributes-registry/rpc.md | 21 +++++++++++--- docs/rpc/rpc-spans.md | 14 ++++----- model/registry/deprecated/rpc.yaml | 32 +++++++++++++++++++++ model/registry/rpc.yaml | 24 ++++++++++++++++ model/trace/rpc.yaml | 46 ++++++++++++++---------------- schema-next.yaml | 9 ++++++ 7 files changed, 132 insertions(+), 36 deletions(-) create mode 100755 .chloggen/rpc_registry.yaml create mode 100644 model/registry/deprecated/rpc.yaml diff --git a/.chloggen/rpc_registry.yaml b/.chloggen/rpc_registry.yaml new file mode 100755 index 0000000000..1401a385e6 --- /dev/null +++ b/.chloggen/rpc_registry.yaml @@ -0,0 +1,22 @@ +# Use this changelog template to create an entry for release notes. +# +# If your change doesn't affect end users you should instead start +# your pull request title with [chore] or use the "Skip Changelog" label. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: breaking + +# The name of the area of concern in the attributes-registry, (e.g. http, cloud, db) +component: rpc + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Rename`message.*` attributes under `rpc` to `rpc.message.*`. Deprecate old `message.*` attributes. + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +# The values here must be integers. +issues: [854] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: diff --git a/docs/attributes-registry/rpc.md b/docs/attributes-registry/rpc.md index 0c904e3f48..25f7a29087 100644 --- a/docs/attributes-registry/rpc.md +++ b/docs/attributes-registry/rpc.md @@ -20,8 +20,12 @@ RPC attributes are intended to be used in the context of events related to remot | `rpc.jsonrpc.error_message` | string | `error.message` property of response if it is an error response. | `Parse error`; `User already exists` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `rpc.jsonrpc.request_id` | string | `id` property of request or response. Since protocol allows id to be int, string, `null` or missing (for notifications), value is expected to be cast to string for simplicity. Use empty string in case of `null` value. Omit entirely if this is a notification. | `10`; `request-7`; `` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `rpc.jsonrpc.version` | string | Protocol version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0 doesn't specify this, the value can be omitted. | `2.0`; `1.0` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `rpc.method` | string | The name of the (logical) method being called, must be equal to the $method part in the span name. [5] | `exampleMethod` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `rpc.service` | string | The full (logical) name of the service being called, including its package name, if applicable. [6] | `myservice.EchoService` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rpc.message.compressed_size` | int | Compressed size of the message in bytes. | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rpc.message.id` | int | MUST be calculated as two different counters starting from `1` one for sent messages and one for received message. [5] | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rpc.message.type` | string | Whether this is a received or sent message. | `SENT` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rpc.message.uncompressed_size` | int | Uncompressed size of the message in bytes. | | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rpc.method` | string | The name of the (logical) method being called, must be equal to the $method part in the span name. [6] | `exampleMethod` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `rpc.service` | string | The full (logical) name of the service being called, including its package name, if applicable. [7] | `myservice.EchoService` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `rpc.system` | string | A string identifying the remoting system. See below for a list of well-known identifiers. | `grpc` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** Instrumentations SHOULD require an explicit configuration of which metadata values are to be captured. Including all request metadata values can be a security risk - explicit configuration helps avoid leaking sensitive information. @@ -32,9 +36,11 @@ RPC attributes are intended to be used in the context of events related to remot **[4]:** Instrumentations SHOULD require an explicit configuration of which metadata values are to be captured. Including all response metadata values can be a security risk - explicit configuration helps avoid leaking sensitive information. -**[5]:** This is the logical name of the method from the RPC interface perspective, which can be different from the name of any implementing method/function. The `code.function` attribute may be used to store the latter (e.g., method actually executing the call on the server side, RPC client stub method on the client side). +**[5]:** This way we guarantee that the values will be consistent between different implementations. -**[6]:** This is the logical name of the service from the RPC interface perspective, which can be different from the name of any implementing class. The `code.namespace` attribute may be used to store the latter (despite the attribute name, it may include a class name; e.g., class with method actually executing the call on the server side, RPC client stub class on the client side). +**[6]:** This is the logical name of the method from the RPC interface perspective, which can be different from the name of any implementing method/function. The `code.function` attribute may be used to store the latter (e.g., method actually executing the call on the server side, RPC client stub method on the client side). + +**[7]:** This is the logical name of the service from the RPC interface perspective, which can be different from the name of any implementing class. The `code.namespace` attribute may be used to store the latter (despite the attribute name, it may include a class name; e.g., class with method actually executing the call on the server side, RPC client stub class on the client side). `rpc.connect_rpc.error_code` MUST be one of the following: @@ -79,6 +85,13 @@ RPC attributes are intended to be used in the context of events related to remot | `15` | DATA_LOSS | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `16` | UNAUTHENTICATED | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +`rpc.message.type` MUST be one of the following: + +| Value | Description | Stability | +|---|---|---| +| `SENT` | sent | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `RECEIVED` | received | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + `rpc.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 | diff --git a/docs/rpc/rpc-spans.md b/docs/rpc/rpc-spans.md index 20f1d09808..387f5b56b1 100644 --- a/docs/rpc/rpc-spans.md +++ b/docs/rpc/rpc-spans.md @@ -191,19 +191,19 @@ In the lifetime of an RPC stream, an event for each message sent/received on client and server spans SHOULD be created. In case of unary calls only one sent and one received message will be recorded for both client and server spans. - -The event name MUST be `message`. + +The event name MUST be `rpc.message`. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| `message.compressed_size` | int | Compressed size of the message in bytes. | | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `message.id` | int | MUST be calculated as two different counters starting from `1` one for sent messages and one for received message. [1] | | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `message.type` | string | Whether this is a received or sent message. | `SENT` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `message.uncompressed_size` | int | Uncompressed size of the message in bytes. | | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`rpc.message.compressed_size`](../attributes-registry/rpc.md) | int | Compressed size of the message in bytes. | | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`rpc.message.id`](../attributes-registry/rpc.md) | int | MUST be calculated as two different counters starting from `1` one for sent messages and one for received message. [1] | | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`rpc.message.type`](../attributes-registry/rpc.md) | string | Whether this is a received or sent message. | `SENT` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`rpc.message.uncompressed_size`](../attributes-registry/rpc.md) | int | Uncompressed size of the message in bytes. | | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** This way we guarantee that the values will be consistent between different implementations. -`message.type` MUST be one of the following: +`rpc.message.type` MUST be one of the following: | Value | Description | Stability | |---|---|---| diff --git a/model/registry/deprecated/rpc.yaml b/model/registry/deprecated/rpc.yaml new file mode 100644 index 0000000000..c6c36710fe --- /dev/null +++ b/model/registry/deprecated/rpc.yaml @@ -0,0 +1,32 @@ +groups: + - id: attributes.rpc.deprecated + type: attribute_group + brief: 'Deprecated rpc message attributes.' + attributes: + - id: message.type + type: + members: + - id: sent + value: "SENT" + stability: experimental + - id: received + value: "RECEIVED" + stability: experimental + stability: experimental + brief: "Deprecated, use `rpc.message.type` instead." + deprecated: "Replaced by `rpc.message.type`." + - id: message.id + type: int + stability: experimental + brief: "Deprecated, use `rpc.message.id` instead." + deprecated: "Replaced by `rpc.message.id`." + - id: message.compressed_size + type: int + stability: experimental + brief: "Deprecated, use `rpc.message.compressed_size` instead." + deprecated: "Replaced by `rpc.message.compressed_size`." + - id: message.uncompressed_size + type: int + stability: experimental + brief: "Deprecated, use `rpc.message.uncompressed_size` instead." + deprecated: "Replaced by `rpc.message.uncompressed_size`." diff --git a/model/registry/rpc.yaml b/model/registry/rpc.yaml index e7400d540e..d1e0aa05cf 100644 --- a/model/registry/rpc.yaml +++ b/model/registry/rpc.yaml @@ -239,3 +239,27 @@ groups: brief: 'Connect RPC' stability: experimental stability: experimental + - id: message.type + type: + members: + - id: sent + value: "SENT" + stability: experimental + - id: received + value: "RECEIVED" + stability: experimental + stability: experimental + brief: "Whether this is a received or sent message." + - id: message.id + type: int + stability: experimental + brief: "MUST be calculated as two different counters starting from `1` one for sent messages and one for received message." + note: "This way we guarantee that the values will be consistent between different implementations." + - id: message.compressed_size + type: int + stability: experimental + brief: "Compressed size of the message in bytes." + - id: message.uncompressed_size + type: int + stability: experimental + brief: "Uncompressed size of the message in bytes." diff --git a/model/trace/rpc.yaml b/model/trace/rpc.yaml index 7e259966f8..d578c6ba6a 100644 --- a/model/trace/rpc.yaml +++ b/model/trace/rpc.yaml @@ -8,9 +8,13 @@ groups: - ref: rpc.system requirement_level: required - ref: rpc.service + requirement_level: recommended - ref: rpc.method + requirement_level: recommended - ref: network.transport + requirement_level: recommended - ref: network.type + requirement_level: recommended - ref: server.address requirement_level: required brief: > @@ -29,6 +33,7 @@ groups: extends: rpc attributes: - ref: network.peer.address + requirement_level: recommended - ref: network.peer.port requirement_level: recommended: If `network.peer.address` is set. @@ -40,13 +45,18 @@ groups: brief: 'Semantic Convention for RPC server spans' attributes: - ref: client.address + requirement_level: recommended - ref: client.port + requirement_level: recommended - ref: network.peer.address + requirement_level: recommended - ref: network.peer.port requirement_level: recommended: If `network.peer.address` is set. - ref: network.transport + requirement_level: recommended - ref: network.type + requirement_level: recommended - id: rpc.grpc type: span @@ -75,12 +85,14 @@ groups: conditionally_required: If other than the default version (`1.0`) - ref: rpc.jsonrpc.request_id tag: jsonrpc-tech-specific + requirement_level: recommended - ref: rpc.jsonrpc.error_code tag: jsonrpc-tech-specific requirement_level: conditionally_required: If response is not successful. - ref: rpc.jsonrpc.error_message tag: jsonrpc-tech-specific + requirement_level: recommended - ref: rpc.method tag: jsonrpc-tech-specific requirement_level: required @@ -89,34 +101,18 @@ groups: RPC conventions for more information. - id: rpc.message - prefix: "message" # TODO: Change the prefix to rpc.message? + prefix: rpc.message type: event brief: "RPC received/sent message." attributes: - - id: type - type: - members: - - id: sent - value: "SENT" - stability: experimental - - id: received - value: "RECEIVED" - stability: experimental - stability: experimental - brief: "Whether this is a received or sent message." - - id: id - type: int - stability: experimental - brief: "MUST be calculated as two different counters starting from `1` one for sent messages and one for received message." - note: "This way we guarantee that the values will be consistent between different implementations." - - id: compressed_size - type: int - stability: experimental - brief: "Compressed size of the message in bytes." - - id: uncompressed_size - type: int - stability: experimental - brief: "Uncompressed size of the message in bytes." + - ref: rpc.message.type + requirement_level: recommended + - ref: rpc.message.id + requirement_level: recommended + - ref: rpc.message.compressed_size + requirement_level: recommended + - ref: rpc.message.uncompressed_size + requirement_level: recommended - id: rpc.connect_rpc type: span diff --git a/schema-next.yaml b/schema-next.yaml index 594dff735d..c36ffd7dc5 100644 --- a/schema-next.yaml +++ b/schema-next.yaml @@ -56,6 +56,15 @@ versions: type: process.paging.fault_type apply_to_metrics: - process.paging.faults + all: + changes: + # https://github.com/open-telemetry/semantic-conventions/pull/854 + - rename_attributes: + attribute_map: + message.type: rpc.message.type + message.id: rpc.message.id + message.compressed_size: rpc.message.compressed_size + message.uncompressed_size: rpc.message.uncompressed_size 1.24.0: metrics: From 14c8e5291e7b7006c5fa4a2cd8460a059fc07837 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 5 Apr 2024 12:57:13 -0400 Subject: [PATCH 2/6] [editorial] service.md: normalize link to process.md (#883) Co-authored-by: Joao Grassi <5938087+joaopgrassi@users.noreply.github.com> Co-authored-by: Liudmila Molkova --- docs/attributes-registry/service.md | 4 ++-- docs/resource/README.md | 2 +- model/registry/service.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/attributes-registry/service.md b/docs/attributes-registry/service.md index 9022d5ac94..ea291b8ac1 100644 --- a/docs/attributes-registry/service.md +++ b/docs/attributes-registry/service.md @@ -40,7 +40,7 @@ However, Collectors can set the `service.instance.id` if they can unambiguously for that telemetry. This is typically the case for scraping receivers, as they know the target address and port. -**[2]:** MUST be the same for all instances of horizontally scaled services. If the value was not specified, SDKs MUST fallback to `unknown_service:` concatenated with [`process.executable.name`](process.md#process), e.g. `unknown_service:bash`. If `process.executable.name` is not available, the value MUST be set to `unknown_service`. +**[2]:** MUST be the same for all instances of horizontally scaled services. If the value was not specified, SDKs MUST fallback to `unknown_service:` concatenated with [`process.executable.name`](process.md), e.g. `unknown_service:bash`. If `process.executable.name` is not available, the value MUST be set to `unknown_service`. **[3]:** A string value having a meaning that helps to distinguish a group of services, for example the team name that owns a group of services. `service.name` is expected to be unique within the same namespace. If `service.namespace` is not specified in the Resource then `service.name` is expected to be unique for all services that have no explicit namespace defined (so the empty/unspecified namespace is simply one more valid namespace). Zero-length namespace string is assumed equal to unspecified namespace. - \ No newline at end of file + diff --git a/docs/resource/README.md b/docs/resource/README.md index c00b0cbed8..c26eb9683b 100644 --- a/docs/resource/README.md +++ b/docs/resource/README.md @@ -85,7 +85,7 @@ as specified in the [Resource SDK specification](https://github.com/open-telemet | [`service.name`](../attributes-registry/service.md) | string | Logical name of the service. [1] | `shoppingcart` | `Required` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`service.version`](../attributes-registry/service.md) | string | The version string of the service API or implementation. The format is not defined by these conventions. | `2.0.0`; `a01dbef8a` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -**[1]:** MUST be the same for all instances of horizontally scaled services. If the value was not specified, SDKs MUST fallback to `unknown_service:` concatenated with [`process.executable.name`](process.md#process), e.g. `unknown_service:bash`. If `process.executable.name` is not available, the value MUST be set to `unknown_service`. +**[1]:** MUST be the same for all instances of horizontally scaled services. If the value was not specified, SDKs MUST fallback to `unknown_service:` concatenated with [`process.executable.name`](process.md), e.g. `unknown_service:bash`. If `process.executable.name` is not available, the value MUST be set to `unknown_service`. ## Service (Experimental) diff --git a/model/registry/service.yaml b/model/registry/service.yaml index 4e139da36b..5af22be57e 100644 --- a/model/registry/service.yaml +++ b/model/registry/service.yaml @@ -12,7 +12,7 @@ groups: note: > MUST be the same for all instances of horizontally scaled services. If the value was not specified, SDKs MUST fallback to `unknown_service:` concatenated - with [`process.executable.name`](process.md#process), e.g. `unknown_service:bash`. + with [`process.executable.name`](process.md), e.g. `unknown_service:bash`. If `process.executable.name` is not available, the value MUST be set to `unknown_service`. examples: ["shoppingcart"] stability: stable From f812621a9128462d1a2466c0d24abcb8a4bdf5fa Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 5 Apr 2024 10:04:26 -0700 Subject: [PATCH 3/6] Rename `db.operation` to `db.operation.name` (#875) Co-authored-by: Liudmila Molkova --- .chloggen/875.yaml | 4 ++++ docs/attributes-registry/db.md | 6 +++--- docs/database/couchdb.md | 6 ++++-- docs/database/database-spans.md | 4 ++-- docs/database/elasticsearch.md | 4 ++-- docs/database/mongodb.md | 5 +++++ docs/database/mssql.md | 14 ++++++++++---- docs/database/sql.md | 10 ++++++++-- model/registry/db.yaml | 12 ++---------- model/registry/deprecated/db.yaml | 6 ++++++ model/trace/database.yaml | 30 +++++++++++++++++++++++------- schema-next.yaml | 4 ++++ 12 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 .chloggen/875.yaml diff --git a/.chloggen/875.yaml b/.chloggen/875.yaml new file mode 100644 index 0000000000..8d75a96c85 --- /dev/null +++ b/.chloggen/875.yaml @@ -0,0 +1,4 @@ +change_type: breaking +component: db +note: Rename `db.operation` to `db.operation.name`. +issues: [ 884 ] diff --git a/docs/attributes-registry/db.md b/docs/attributes-registry/db.md index 63824a6024..e60c2d3741 100644 --- a/docs/attributes-registry/db.md +++ b/docs/attributes-registry/db.md @@ -25,15 +25,13 @@ |---|---|---|---|---| | `db.instance.id` | string | An identifier (address, unique name, or any other identifier) of the database instance that is executing queries or mutations on the current connection. This is useful in cases where the database is running in a clustered environment and the instrumentation is able to record the node executing the query. The client may obtain this value in databases like MySQL using queries like `select @@hostname`. | `mysql-e26b99z.example.com` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `db.name` | string | This attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails). [1] | `customers`; `main` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `db.operation` | string | The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`, or the SQL keyword. [2] | `findAndModify`; `HMSET`; `SELECT` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `db.operation.name` | string | The name of the operation or command being executed. | `findAndModify`; `HMSET`; `SELECT` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `db.statement` | string | The database statement being executed. | `SELECT * FROM wuser_table`; `SET mykey "WuValue"` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `db.system` | string | An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers. | `other_sql` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `db.user` | string | Username for accessing the database. | `readonly_user`; `reporting_user` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** In some SQL databases, the database name to be used is called "schema name". In case there are multiple layers that could be considered for database name (e.g. Oracle instance name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema name). -**[2]:** When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted. - `db.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 | @@ -221,6 +219,7 @@ | `db.connection_string` | string | Deprecated, use `server.address`, `server.port` attributes instead. | `Server=(localdb)\v11.0;Integrated Security=true;` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
"Replaced by `server.address` and `server.port`." | | `db.elasticsearch.node.name` | string | Deprecated, use `db.instance.id` instead. | `instance-0000000001` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `db.instance.id`. | | `db.jdbc.driver_classname` | string | Removed, no replacement at this time. | `org.postgresql.Driver`; `com.microsoft.sqlserver.jdbc.SQLServerDriver` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Removed as not used. | +| `db.operation` | string | Deprecated, use `db.operation.name` instead. | `findAndModify`; `HMSET`; `SELECT` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `db.operation.name`. | ### Deprecated Elasticsearch Attributes @@ -231,4 +230,5 @@ | `db.connection_string` | string | Deprecated, use `server.address`, `server.port` attributes instead. | `Server=(localdb)\v11.0;Integrated Security=true;` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
"Replaced by `server.address` and `server.port`." | | `db.elasticsearch.node.name` | string | Deprecated, use `db.instance.id` instead. | `instance-0000000001` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `db.instance.id`. | | `db.jdbc.driver_classname` | string | Removed, no replacement at this time. | `org.postgresql.Driver`; `com.microsoft.sqlserver.jdbc.SQLServerDriver` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Removed as not used. | +| `db.operation` | string | Deprecated, use `db.operation.name` instead. | `findAndModify`; `HMSET`; `SELECT` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `db.operation.name`. | diff --git a/docs/database/couchdb.md b/docs/database/couchdb.md index ebd42dd9b4..20d4963add 100644 --- a/docs/database/couchdb.md +++ b/docs/database/couchdb.md @@ -17,9 +17,11 @@ described on this page. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`db.operation`](../attributes-registry/db.md) | string | The HTTP method + the target REST route. [1] | `GET /{db}/{docid}` | `Conditionally Required` If `db.statement` is not applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.operation.name`](../attributes-registry/db.md) | string | The HTTP method + the target REST route. [1] | `GET /{db}/{docid}` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[1]:** In **CouchDB**, `db.operation` should be set to the HTTP method + the target REST route according to the API reference documentation. For example, when retrieving a document, `db.operation` would be set to (literally, i.e., without replacing the placeholders with concrete values): [`GET /{db}/{docid}`](https://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid). +**[1]:** In **CouchDB**, `db.operation.name` should be set to the HTTP method + the target REST route according to the API reference documentation. For example, when retrieving a document, `db.operation.name` would be set to (literally, i.e., without replacing the placeholders with concrete values): [`GET /{db}/{docid}`](https://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid). + +**[2]:** If readily available. Otherwise, if the instrumentation library parses `db.statement` to capture `db.operation.name`, then it SHOULD be the first operation name found in the query. [DocumentStatus]: https://github.com/open-telemetry/opentelemetry-specification/tree/v1.31.0/specification/document-status.md diff --git a/docs/database/database-spans.md b/docs/database/database-spans.md index 972635b38d..4b2f1d0d7a 100644 --- a/docs/database/database-spans.md +++ b/docs/database/database-spans.md @@ -75,7 +75,7 @@ Some database systems may allow a connection to switch to a different `db.user`, |---|---|---|---|---|---| | [`db.system`](../attributes-registry/db.md) | string | An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers. | `other_sql` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`db.name`](../attributes-registry/db.md) | string | This attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails). [1] | `customers`; `main` | `Conditionally Required` If applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`db.operation`](../attributes-registry/db.md) | string | The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`, or the SQL keyword. [2] | `findAndModify`; `HMSET`; `SELECT` | `Conditionally Required` If `db.statement` is not applicable. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.operation.name`](../attributes-registry/db.md) | string | The name of the operation or command being executed. | `findAndModify`; `HMSET`; `SELECT` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`server.port`](../attributes-registry/server.md) | int | Server port number. [3] | `80`; `8080`; `443` | `Conditionally Required` [4] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`db.instance.id`](../attributes-registry/db.md) | string | An identifier (address, unique name, or any other identifier) of the database instance that is executing queries or mutations on the current connection. This is useful in cases where the database is running in a clustered environment and the instrumentation is able to record the node executing the query. The client may obtain this value in databases like MySQL using queries like `select @@hostname`. | `mysql-e26b99z.example.com` | `Recommended` If different from the `server.address` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`db.statement`](../attributes-registry/db.md) | string | The database statement being executed. | `SELECT * FROM wuser_table`; `SET mykey "WuValue"` | `Recommended` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | @@ -86,7 +86,7 @@ Some database systems may allow a connection to switch to a different `db.user`, **[1]:** In some SQL databases, the database name to be used is called "schema name". In case there are multiple layers that could be considered for database name (e.g. Oracle instance name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema name). -**[2]:** When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted. +**[2]:** If readily available. Otherwise, if the instrumentation library parses `db.statement` to capture `db.operation.name`, then it SHOULD be the first operation name found in the query. **[3]:** 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/database/elasticsearch.md b/docs/database/elasticsearch.md index 50cbc3c273..d700e4917d 100644 --- a/docs/database/elasticsearch.md +++ b/docs/database/elasticsearch.md @@ -26,7 +26,7 @@ If the endpoint id is not available, the span name SHOULD be the `http.request.m | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`db.operation`](../attributes-registry/db.md) | string | The endpoint identifier for the request. [1] | `search`; `ml.close_job`; `cat.aliases` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.operation.name`](../attributes-registry/db.md) | string | The name of the operation or command being executed. [1] | `search`; `ml.close_job`; `cat.aliases` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`http.request.method`](../attributes-registry/http.md) | string | HTTP request method. [2] | `GET`; `POST`; `HEAD` | `Required` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`url.full`](../attributes-registry/url.md) | string | Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) [3] | `https://localhost:9200/index/_search?q=user.id:kimchy` | `Required` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`db.elasticsearch.path_parts.`](../attributes-registry/db.md) | string | A dynamic value in the url path. [4] | `db.elasticsearch.path_parts.index=test-index`; `db.elasticsearch.path_parts.doc_id=123` | `Conditionally Required` when the url has dynamic values | ![Experimental](https://img.shields.io/badge/-experimental-blue) | @@ -38,7 +38,7 @@ If the endpoint id is not available, the span name SHOULD be the `http.request.m | [`network.peer.port`](../attributes-registry/network.md) | int | Peer port number of the network connection. | `65123` | `Recommended` if and only if `network.peer.address` is set. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`server.address`](../attributes-registry/server.md) | string | Name of the database host. [11] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -**[1]:** When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted. +**[1]:** This SHOULD be the endpoint identifier for the request. **[2]:** HTTP request method value SHOULD be "known" to the instrumentation. By default, this convention defines "known" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods) diff --git a/docs/database/mongodb.md b/docs/database/mongodb.md index c733f4ffb0..7be3e0559e 100644 --- a/docs/database/mongodb.md +++ b/docs/database/mongodb.md @@ -18,6 +18,11 @@ described on this page. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| | [`db.mongodb.collection`](../attributes-registry/db.md) | string | The MongoDB collection being accessed within the database stated in `db.name`. | `customers`; `products` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.operation.name`](../attributes-registry/db.md) | string | The name of the command being executed. [1] | `findAndModify`; `getMore`; `update` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**[1]:** See [MongoDB database commands](https://www.mongodb.com/docs/manual/reference/command/). + +**[2]:** If readily available. Otherwise, if the instrumentation library parses `db.statement` to capture `db.operation.name`, then it SHOULD be the first operation name found in the query. ## Example diff --git a/docs/database/mssql.md b/docs/database/mssql.md index 20829283c2..e7e1178c55 100644 --- a/docs/database/mssql.md +++ b/docs/database/mssql.md @@ -17,12 +17,18 @@ described on this page. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`db.mssql.instance_name`](../attributes-registry/db.md) | string | The Microsoft SQL Server [instance name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance. [1] | `MSSQLSERVER` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`db.sql.table`](../attributes-registry/db.md) | string | The name of the primary table that the operation is acting upon, including the database name (if applicable). [2] | `public.users`; `customers` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.operation.name`](../attributes-registry/db.md) | string | The name of the operation or command being executed. [1] | `SELECT`; `INSERT`; `UPDATE`; `DELETE`; `CREATE`; `mystoredproc` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.mssql.instance_name`](../attributes-registry/db.md) | string | The Microsoft SQL Server [instance name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance. [3] | `MSSQLSERVER` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.sql.table`](../attributes-registry/db.md) | string | The name of the primary table that the operation is acting upon, including the database name (if applicable). [4] | `public.users`; `customers` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[1]:** If setting a `db.mssql.instance_name`, `server.port` is no longer required (but still recommended if non-standard). +**[1]:** This SHOULD be the SQL command such as `SELECT`, `INSERT`, `UPDATE`, `CREATE`, `DROP`. +In the case of `EXEC`, this SHOULD be the stored procedure name that is being executed. -**[2]:** It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set. +**[2]:** If readily available. Otherwise, if the instrumentation library parses `db.statement` to capture `db.operation.name`, then it SHOULD be the first operation name found in the query. + +**[3]:** If setting a `db.mssql.instance_name`, `server.port` is no longer required (but still recommended if non-standard). + +**[4]:** It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set. [DocumentStatus]: https://github.com/open-telemetry/opentelemetry-specification/tree/v1.31.0/specification/document-status.md diff --git a/docs/database/sql.md b/docs/database/sql.md index 1357ac2003..7c53a45e5d 100644 --- a/docs/database/sql.md +++ b/docs/database/sql.md @@ -15,9 +15,15 @@ described on this page. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`db.sql.table`](../attributes-registry/db.md) | string | The name of the primary table that the operation is acting upon, including the database name (if applicable). [1] | `public.users`; `customers` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.operation.name`](../attributes-registry/db.md) | string | The name of the operation or command being executed. [1] | `SELECT`; `INSERT`; `UPDATE`; `DELETE`; `CREATE`; `mystoredproc` | `Conditionally Required` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.sql.table`](../attributes-registry/db.md) | string | The name of the primary table that the operation is acting upon, including the database name (if applicable). [3] | `public.users`; `customers` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[1]:** It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set. +**[1]:** This SHOULD be the SQL command such as `SELECT`, `INSERT`, `UPDATE`, `CREATE`, `DROP`. +In the case of `EXEC`, this SHOULD be the stored procedure name that is being executed. + +**[2]:** If readily available. Otherwise, if the instrumentation library parses `db.statement` to capture `db.operation.name`, then it SHOULD be the first operation name found in the query. + +**[3]:** It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set. ## Example diff --git a/model/registry/db.yaml b/model/registry/db.yaml index f56a830fcb..ec67346e39 100644 --- a/model/registry/db.yaml +++ b/model/registry/db.yaml @@ -245,19 +245,11 @@ groups: the database name to be used is the more specific layer (e.g. Oracle schema name). examples: [ 'customers', 'main' ] tag: db-generic - - id: operation + - id: operation.name type: string stability: experimental brief: > - The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) - such as `findAndModify`, or the SQL keyword. - note: > - When setting this to an SQL keyword, it is not recommended to - attempt any client-side parsing of `db.statement` just to get this - property, but it should be set if the operation name is provided by - the library being instrumented. - If the SQL statement has an ambiguous operation, or performs more - than one operation, this value may be omitted. + The name of the operation or command being executed. examples: ['findAndModify', 'HMSET', 'SELECT'] tag: db-generic - id: redis.database_index diff --git a/model/registry/deprecated/db.yaml b/model/registry/deprecated/db.yaml index c2f94cfe22..3d384948c9 100644 --- a/model/registry/deprecated/db.yaml +++ b/model/registry/deprecated/db.yaml @@ -24,3 +24,9 @@ groups: deprecated: "Replaced by `db.instance.id`." stability: experimental examples: ["instance-0000000001"] + - id: operation + type: string + brief: 'Deprecated, use `db.operation.name` instead.' + stability: experimental + deprecated: "Replaced by `db.operation.name`." + examples: ['findAndModify', 'HMSET', 'SELECT'] diff --git a/model/trace/database.yaml b/model/trace/database.yaml index 7435d4e485..6b0dac762f 100644 --- a/model/trace/database.yaml +++ b/model/trace/database.yaml @@ -13,9 +13,11 @@ groups: requirement_level: recommended: > Should be collected by default only if there is sanitization that excludes sensitive information. - - ref: db.operation + - ref: db.operation.name requirement_level: - conditionally_required: If `db.statement` is not applicable. + conditionally_required: > + If readily available. Otherwise, if the instrumentation library parses `db.statement` to capture + `db.operation.name`, then it SHOULD be the first operation name found in the query. - ref: server.address brief: > Name of the database host. @@ -113,15 +115,15 @@ groups: brief: > Attributes for CouchDB attributes: - - ref: db.operation + - ref: db.operation.name tag: tech-specific brief: > The HTTP method + the target REST route. examples: ['GET /{db}/{docid}'] note: > - In **CouchDB**, `db.operation` should be set to the HTTP method + + In **CouchDB**, `db.operation.name` should be set to the HTTP method + the target REST route according to the API reference documentation. - For example, when retrieving a document, `db.operation` would be set to + For example, when retrieving a document, `db.operation.name` would be set to (literally, i.e., without replacing the placeholders with concrete values): [`GET /{db}/{docid}`](https://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid). @@ -150,6 +152,13 @@ groups: brief: > Attributes for MongoDB attributes: + - ref: db.operation.name + brief: > + The name of the command being executed. + note: > + See [MongoDB database commands](https://www.mongodb.com/docs/manual/reference/command/). + examples: ['findAndModify', 'getMore', 'update'] + tag: tech-specific - ref: db.mongodb.collection requirement_level: required tag: tech-specific @@ -163,9 +172,9 @@ groups: - ref: http.request.method requirement_level: required tag: tech-specific - - ref: db.operation + - ref: db.operation.name requirement_level: required - brief: The endpoint identifier for the request. + note: This SHOULD be the endpoint identifier for the request. examples: [ 'search', 'ml.close_job', 'cat.aliases' ] tag: tech-specific - ref: url.full @@ -205,6 +214,13 @@ groups: brief: > Attributes for SQL databases attributes: + - ref: db.operation.name + note: > + This SHOULD be the SQL command such as `SELECT`, `INSERT`, `UPDATE`, `CREATE`, `DROP`. + + In the case of `EXEC`, this SHOULD be the stored procedure name that is being executed. + examples: ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'mystoredproc'] + tag: tech-specific - ref: db.sql.table tag: tech-specific diff --git a/schema-next.yaml b/schema-next.yaml index c36ffd7dc5..638d717e8c 100644 --- a/schema-next.yaml +++ b/schema-next.yaml @@ -10,6 +10,10 @@ versions: - rename_attributes: attribute_map: messaging.kafka.destination.partition: messaging.destination.partition.id + # https://github.com/open-telemetry/semantic-conventions/pull/875 + - rename_attributes: + attribute_map: + db.operation: db.operation.name metrics: changes: # https://github.com/open-telemetry/semantic-conventions/pull/484 From a08fd23c2861135f96c18b1f91b11bad27f5b52c Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 5 Apr 2024 10:12:06 -0700 Subject: [PATCH 4/6] [chore] Add backward-compatibility check to ci (#764) --- .github/workflows/checks.yml | 7 +++++++ CONTRIBUTING.md | 13 +++++++++++++ Makefile | 10 ++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index a4e32cba18..d7a284a688 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -91,6 +91,13 @@ jobs: - name: verify semantic convention tables run: make table-check + semantic-conventions-compatibility: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: verify semantic convention compatibility with latest released version + run: make compatibility-check + schemas-check: runs-on: ubuntu-latest steps: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1435db2e45..f156a5ac4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,6 +30,7 @@ requirements and recommendations. - [Markdown style](#markdown-style) - [Misspell check](#misspell-check) - [Markdown link check](#markdown-link-check) + - [Version compatibility check](#version-compatibility-check) - [Updating the referenced specification version](#updating-the-referenced-specification-version) - [Making a Release](#making-a-release) - [Merging existing ECS conventions](#merging-existing-ecs-conventions) @@ -300,6 +301,18 @@ To check the validity of links in all markdown files, run the following command: make markdown-link-check ``` +### Version compatibility check + +Semantic conventions are validated for backward compatibility with last released versions. Here's [the full list of compatibility checks](https://github.com/open-telemetry/build-tools/blob/main/semantic-conventions/README.md#version-compatibility-check). +Removing attributes, metrics, or enum members is not allowed, they should be deprecated instead. +It applies to stable and experimental conventions and prevents semantic conventions auto-generated libraries from introducing breaking changes. + +You can run backward compatibility check in all yaml files with the following command: + +```bash +make compatibility-check +``` + ## Updating the referenced specification version 1. Open the `./internal/tools/update_specification_version.sh` script. diff --git a/Makefile b/Makefile index f330c83b3d..df33d8e6aa 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ SEMCONVGEN_VERSION=0.24.0 # TODO: add `yamllint` step to `all` after making sure it works on Mac. .PHONY: all -all: install-tools markdownlint markdown-link-check misspell table-check schema-check \ +all: install-tools markdownlint markdown-link-check misspell table-check compatibility-check schema-check \ check-file-and-folder-names-in-docs .PHONY: check-file-and-folder-names-in-docs @@ -103,6 +103,12 @@ table-check: docker run --rm -v $(PWD)/model:/source -v $(PWD)/docs:/spec \ otel/semconvgen:$(SEMCONVGEN_VERSION) -f /source markdown -md /spec --md-check +LATEST_RELEASED_SEMCONV_VERSION := $(shell git describe --tags --abbrev=0 | sed 's/v//g') +.PHONY: compatibility-check +compatibility-check: + docker run --rm -v $(PWD)/model:/source -v $(PWD)/docs:/spec \ + otel/semconvgen:$(SEMCONVGEN_VERSION) -f /source compatibility --previous-version $(LATEST_RELEASED_SEMCONV_VERSION) + .PHONY: schema-check schema-check: $(TOOLS_DIR)/schema_check.sh @@ -117,7 +123,7 @@ fix-format: # Run all checks in order of speed / likely failure. .PHONY: check -check: misspell markdownlint check-format markdown-toc markdown-link-check +check: misspell markdownlint check-format markdown-toc compatibility-check markdown-link-check git diff --exit-code ':*.md' || (echo 'Generated markdown Table of Contents is out of date, please run "make markdown-toc" and commit the changes in this PR.' && exit 1) @echo "All checks complete" From a00f5ae2430eeddd93805c805275532d300083ac Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 5 Apr 2024 10:19:45 -0700 Subject: [PATCH 5/6] [chore] Update contributing.md - add details on how to create release and push tag (#881) --- CONTRIBUTING.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f156a5ac4c..152f6ce462 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -336,7 +336,15 @@ make compatibility-check `.chloggen` folder automatically - Double check that `CHANGELOG.md` is updated with the proper `v{version}` - Send staging branch as PR for review. -- Create a tag `v{version}` on the merged PR and push remote. +- After the release PR is merged, create a [new release](https://github.com/open-telemetry/semantic-conventions/releases/new): + - Set title and tag to `v{version}` + - Set target to the commit of the merged release PR + - Copy changelog to the release notes + - Verify that the release looks like expected + - Publish release + +New release is then auto-discovered by [opentelemetry.io](https://github.com/open-telemetry/opentelemetry.io) pipelines which (via bot-generated PR) +eventually results in new version of schema file being published. ## Merging existing ECS conventions From 34edf1b967a99d58d516fcbc9438818012b1b9ef Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 5 Apr 2024 10:29:01 -0700 Subject: [PATCH 6/6] Replace constraints with requirement levels on exceptions (#862) Co-authored-by: Joao Grassi <5938087+joaopgrassi@users.noreply.github.com> --- .chloggen/862.yaml | 4 ++++ docs/exceptions/exceptions-logs.md | 9 ++++----- docs/exceptions/exceptions-spans.md | 17 ++++++++--------- model/logs/log-exception.yaml | 9 ++++----- model/trace/trace-exception.yaml | 8 ++++---- 5 files changed, 24 insertions(+), 23 deletions(-) create mode 100644 .chloggen/862.yaml diff --git a/.chloggen/862.yaml b/.chloggen/862.yaml new file mode 100644 index 0000000000..828a88899e --- /dev/null +++ b/.chloggen/862.yaml @@ -0,0 +1,4 @@ +change_type: enhancement +component: exception +note: Replace constraints with requirement levels on exceptions. +issues: [ 862 ] diff --git a/docs/exceptions/exceptions-logs.md b/docs/exceptions/exceptions-logs.md index e19e35330c..6f1d98f92c 100644 --- a/docs/exceptions/exceptions-logs.md +++ b/docs/exceptions/exceptions-logs.md @@ -38,14 +38,13 @@ The table below indicates which attributes should be added to the | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`exception.message`](../attributes-registry/exception.md) | string | The exception message. | `Division by zero`; `Can't convert 'int' object to str implicitly` | See below | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`exception.message`](../attributes-registry/exception.md) | string | The exception message. | `Division by zero`; `Can't convert 'int' object to str implicitly` | `Conditionally Required` [1] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`exception.type`](../attributes-registry/exception.md) | string | The type of the exception (its fully-qualified class name, if applicable). The dynamic type of the exception should be preferred over the static type in languages that support it. | `java.net.ConnectException`; `OSError` | `Conditionally Required` [2] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`exception.stacktrace`](../attributes-registry/exception.md) | string | A stacktrace as a string in the natural representation for the language runtime. The representation is to be determined and documented by each language SIG. | `Exception in thread "main" java.lang.RuntimeException: Test exception\n at com.example.GenerateTrace.methodB(GenerateTrace.java:13)\n at com.example.GenerateTrace.methodA(GenerateTrace.java:9)\n at com.example.GenerateTrace.main(GenerateTrace.java:5)` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`exception.type`](../attributes-registry/exception.md) | string | The type of the exception (its fully-qualified class name, if applicable). The dynamic type of the exception should be preferred over the static type in languages that support it. | `java.net.ConnectException`; `OSError` | See below | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -**Additional attribute requirements:** At least one of the following sets of attributes is required: +**[1]:** Required if `exception.type` is not set, recommended otherwise. -* [`exception.type`](../attributes-registry/exception.md) -* [`exception.message`](../attributes-registry/exception.md) +**[2]:** Required if `exception.message` is not set, recommended otherwise. ### Stacktrace Representation diff --git a/docs/exceptions/exceptions-spans.md b/docs/exceptions/exceptions-spans.md index c438e9951b..0dbb2e7313 100644 --- a/docs/exceptions/exceptions-spans.md +++ b/docs/exceptions/exceptions-spans.md @@ -48,12 +48,16 @@ The event name MUST be `exception`. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`exception.escaped`](../attributes-registry/exception.md) | boolean | SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span. [1] | | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`exception.message`](../attributes-registry/exception.md) | string | The exception message. | `Division by zero`; `Can't convert 'int' object to str implicitly` | See below | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`exception.message`](../attributes-registry/exception.md) | string | The exception message. | `Division by zero`; `Can't convert 'int' object to str implicitly` | `Conditionally Required` [1] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`exception.type`](../attributes-registry/exception.md) | string | The type of the exception (its fully-qualified class name, if applicable). The dynamic type of the exception should be preferred over the static type in languages that support it. | `java.net.ConnectException`; `OSError` | `Conditionally Required` [2] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`exception.escaped`](../attributes-registry/exception.md) | boolean | SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span. [3] | | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`exception.stacktrace`](../attributes-registry/exception.md) | string | A stacktrace as a string in the natural representation for the language runtime. The representation is to be determined and documented by each language SIG. | `Exception in thread "main" java.lang.RuntimeException: Test exception\n at com.example.GenerateTrace.methodB(GenerateTrace.java:13)\n at com.example.GenerateTrace.methodA(GenerateTrace.java:9)\n at com.example.GenerateTrace.main(GenerateTrace.java:5)` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`exception.type`](../attributes-registry/exception.md) | string | The type of the exception (its fully-qualified class name, if applicable). The dynamic type of the exception should be preferred over the static type in languages that support it. | `java.net.ConnectException`; `OSError` | See below | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -**[1]:** An exception is considered to have escaped (or left) the scope of a span, +**[1]:** Required if `exception.type` is not set, recommended otherwise. + +**[2]:** Required if `exception.message` is not set, recommended otherwise. + +**[3]:** An exception is considered to have escaped (or left) the scope of a span, if that span is ended while the exception is still logically "in flight". This may be actually "in flight" in some languages (e.g. if the exception is passed to a Context manager's `__exit__` method in Python) but will @@ -69,11 +73,6 @@ It follows that an exception may still escape the scope of the span even if the `exception.escaped` attribute was not set or set to false, since the event might have been recorded at a time where it was not clear whether the exception will escape. - -**Additional attribute requirements:** At least one of the following sets of attributes is required: - -* [`exception.type`](../attributes-registry/exception.md) -* [`exception.message`](../attributes-registry/exception.md) ### Stacktrace Representation diff --git a/model/logs/log-exception.yaml b/model/logs/log-exception.yaml index d0b251552a..ab20cb7250 100644 --- a/model/logs/log-exception.yaml +++ b/model/logs/log-exception.yaml @@ -7,10 +7,9 @@ groups: Records. attributes: - ref: exception.type + requirement_level: + conditionally_required: Required if `exception.message` is not set, recommended otherwise. - ref: exception.message + requirement_level: + conditionally_required: Required if `exception.type` is not set, recommended otherwise. - ref: exception.stacktrace - - constraints: - - any_of: - - "exception.type" - - "exception.message" diff --git a/model/trace/trace-exception.yaml b/model/trace/trace-exception.yaml index 8de3abb818..32c53f4b30 100644 --- a/model/trace/trace-exception.yaml +++ b/model/trace/trace-exception.yaml @@ -7,10 +7,10 @@ groups: report a single exception associated with a span. attributes: - ref: exception.type + requirement_level: + conditionally_required: Required if `exception.message` is not set, recommended otherwise. - ref: exception.message + requirement_level: + conditionally_required: Required if `exception.type` is not set, recommended otherwise. - ref: exception.stacktrace - ref: exception.escaped - constraints: - - any_of: - - "exception.type" - - "exception.message"