diff --git a/.chloggen/866.yaml b/.chloggen/866.yaml new file mode 100644 index 000000000..43ee49568 --- /dev/null +++ b/.chloggen/866.yaml @@ -0,0 +1,4 @@ +change_type: breaking +component: db +note: Rename `db.statement` to `db.query.text` and introduce `db.query.parameter.` +issues: [ 716 ] diff --git a/docs/attributes-registry/db.md b/docs/attributes-registry/db.md index ea89a0c93..7cbe0819f 100644 --- a/docs/attributes-registry/db.md +++ b/docs/attributes-registry/db.md @@ -25,11 +25,15 @@ | `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.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.query.parameter.` | string | The query parameters used in `db.query.text`, with `` being the parameter name, and the attribute value being the parameter value. [2] | `someval`; `55` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `db.query.text` | string | The database query being executed. | `SELECT * FROM wuser_table where username = ?`; `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) | **[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]:** Query parameters should only be captured when `db.query.text` is parameterized with placeholders. +If a parameter has no name and instead is referenced only by index, then `` SHOULD be the 0-based index. + `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 | @@ -101,7 +105,7 @@ | `db.cassandra.speculative_execution_count` | int | The number of times a query was speculatively executed. Not set or `0` if the query was not executed speculatively. | `0`; `2` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `db.cassandra.table` | string | The name of the primary Cassandra table that the operation is acting upon, including the keyspace name (if applicable). [1] | `mytable` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[1]:** This mirrors the db.sql.table attribute but references cassandra rather than sql. 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 mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of `db.query.text` 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. `db.cassandra.consistency_level` MUST be one of the following: @@ -206,7 +210,7 @@ |---|---|---|---|---| | `db.sql.table` | string | The name of the primary table that the operation is acting upon, including the database name (if applicable). [1] | `public.users`; `customers` | ![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]:** It is not recommended to attempt any client-side parsing of `db.query.text` 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. ## Deprecated DB Attributes @@ -218,5 +222,6 @@ | `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`. | +| `db.statement` | string | The database statement being executed. | `SELECT * FROM wuser_table`; `SET mykey "WuValue"` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `db.query.text`. | | `db.user` | string | Deprecated, no replacement at this time. | `readonly_user`; `reporting_user` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
No replacement at this time. | diff --git a/docs/database/cassandra.md b/docs/database/cassandra.md index 342fdc405..efcb9b591 100644 --- a/docs/database/cassandra.md +++ b/docs/database/cassandra.md @@ -30,7 +30,7 @@ described on this page. **[1]:** For Cassandra the `db.name` should be set to the Cassandra keyspace name. -**[2]:** This mirrors the db.sql.table attribute but references cassandra rather than sql. 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]:** This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of `db.query.text` 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. **[3]:** If a database operation involved multiple network calls (for example retries), the address of the last contacted node SHOULD be used. diff --git a/docs/database/database-spans.md b/docs/database/database-spans.md index 339313e28..9a1f2222f 100644 --- a/docs/database/database-spans.md +++ b/docs/database/database-spans.md @@ -77,10 +77,11 @@ These attributes will usually be the same for all operations performed over the | [`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) | +| [`db.query.text`](../attributes-registry/db.md) | string | The database query being executed. | `SELECT * FROM wuser_table where username = ?`; `SET mykey "WuValue"` | `Recommended` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`network.peer.address`](../attributes-registry/network.md) | string | Peer address of the database node where the operation was performed. [6] | `10.1.2.80`; `/tmp/my.sock` | `Recommended` If applicable for this database system. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`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. [7] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`db.query.parameter.`](../attributes-registry/db.md) | string | The query parameters used in `db.query.text`, with `` being the parameter name, and the attribute value being the parameter value. [8] | `someval`; `55` | `Opt-In` | ![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). @@ -97,6 +98,9 @@ If a database operation involved multiple network calls (for example retries), t **[7]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[8]:** Query parameters should only be captured when `db.query.text` is parameterized with placeholders. +If a parameter has no name and instead is referenced only by index, then `` SHOULD be the 0-based index. + `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 | diff --git a/docs/database/elasticsearch.md b/docs/database/elasticsearch.md index d700e4917..c04c894ca 100644 --- a/docs/database/elasticsearch.md +++ b/docs/database/elasticsearch.md @@ -33,7 +33,7 @@ If the endpoint id is not available, the span name SHOULD be the `http.request.m | [`server.port`](../attributes-registry/server.md) | int | Server port number. [5] | `80`; `8080`; `443` | `Conditionally Required` [6] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`db.elasticsearch.cluster.name`](../attributes-registry/db.md) | string | Represents the identifier of an Elasticsearch cluster. | `e9106fc68e3044f0b1475b04bf4ffd5f` | `Recommended` [7] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`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` [8] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`db.statement`](../attributes-registry/db.md) | string | The request body for a [search-type query](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html), as a json string. | `"{\"query\":{\"term\":{\"user.id\":\"kimchy\"}}}"` | `Recommended` [9] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.query.text`](../attributes-registry/db.md) | string | The request body for a [search-type query](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html), as a json string. | `"{\"query\":{\"term\":{\"user.id\":\"kimchy\"}}}"` | `Recommended` [9] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`network.peer.address`](../attributes-registry/network.md) | string | Peer address of the database node where the operation was performed. [10] | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`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) | diff --git a/docs/database/mssql.md b/docs/database/mssql.md index e7e1178c5..47ed5a001 100644 --- a/docs/database/mssql.md +++ b/docs/database/mssql.md @@ -28,7 +28,7 @@ In the case of `EXEC`, this SHOULD be the stored procedure name that is being ex **[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. +**[4]:** It is not recommended to attempt any client-side parsing of `db.query.text` 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/redis.md b/docs/database/redis.md index 6007bb57b..2011dc67e 100644 --- a/docs/database/redis.md +++ b/docs/database/redis.md @@ -18,11 +18,11 @@ described on this page. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| | [`db.redis.database_index`](../attributes-registry/db.md) | int | The index of the database being accessed as used in the [`SELECT` command](https://redis.io/commands/select), provided as an integer. To be used instead of the generic `db.name` attribute. | `0`; `1`; `15` | `Conditionally Required` If other than the default database (`0`). | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`db.statement`](../attributes-registry/db.md) | string | The full syntax of the Redis CLI command. [1] | `HMSET myhash field1 'Hello' field2 'World'` | `Recommended` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`db.query.text`](../attributes-registry/db.md) | string | The full syntax of the Redis CLI command. [1] | `HMSET myhash field1 'Hello' field2 'World'` | `Recommended` [2] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`network.peer.address`](../attributes-registry/network.md) | string | Peer address of the database node where the operation was performed. [3] | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`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) | -**[1]:** For **Redis**, the value provided for `db.statement` SHOULD correspond to the syntax of the Redis CLI. If, for example, the [`HMSET` command](https://redis.io/commands/hmset) is invoked, `"HMSET myhash field1 'Hello' field2 'World'"` would be a suitable value for `db.statement`. +**[1]:** For **Redis**, the value provided for `db.query.text` SHOULD correspond to the syntax of the Redis CLI. If, for example, the [`HMSET` command](https://redis.io/commands/hmset) is invoked, `"HMSET myhash field1 'Hello' field2 'World'"` would be a suitable value for `db.query.text`. **[2]:** Should be collected by default only if there is sanitization that excludes sensitive information. diff --git a/docs/database/sql.md b/docs/database/sql.md index 0427c2087..002fff4d0 100644 --- a/docs/database/sql.md +++ b/docs/database/sql.md @@ -23,7 +23,7 @@ In the case of `EXEC`, this SHOULD be the stored procedure name that is being ex **[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. +**[3]:** It is not recommended to attempt any client-side parsing of `db.query.text` 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 83b71d16a..f967fdbe6 100644 --- a/model/registry/db.yaml +++ b/model/registry/db.yaml @@ -86,7 +86,7 @@ groups: note: > This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of - `db.statement` just to get this property, but it should be set if + `db.query.text` 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. @@ -266,18 +266,31 @@ groups: brief: The name of the primary table that the operation is acting upon, including the database name (if applicable). note: > It is not recommended to attempt any client-side parsing of - `db.statement` just to get this property, but it should be set if + `db.query.text` 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. examples: ['public.users', 'customers'] tag: tech-specific-sql - - id: statement + - id: query.text type: string stability: experimental brief: > - The database statement being executed. - examples: ['SELECT * FROM wuser_table', 'SET mykey "WuValue"'] + The database query being executed. + examples: ['SELECT * FROM wuser_table where username = ?', 'SET mykey "WuValue"'] + tag: db-generic + - id: query.parameter + type: template[string] + stability: experimental + brief: > + The query parameters used in `db.query.text`, with `` being the parameter name, + and the attribute value being the parameter value. + note: > + Query parameters should only be captured when `db.query.text` is parameterized with placeholders. + + If a parameter has no name and instead is referenced only by index, + then `` SHOULD be the 0-based index. + examples: ['someval', '55'] tag: db-generic - id: system brief: An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers. diff --git a/model/registry/deprecated/db.yaml b/model/registry/deprecated/db.yaml index b861dd7fd..1fec703f8 100644 --- a/model/registry/deprecated/db.yaml +++ b/model/registry/deprecated/db.yaml @@ -36,3 +36,9 @@ groups: deprecated: "No replacement at this time." stability: experimental examples: ['readonly_user', 'reporting_user'] + - id: statement + type: string + brief: The database statement being executed. + deprecated: "Replaced by `db.query.text`." + stability: experimental + examples: ['SELECT * FROM wuser_table', 'SET mykey "WuValue"'] diff --git a/model/trace/database.yaml b/model/trace/database.yaml index 5ca47c4f9..8c6f973b3 100644 --- a/model/trace/database.yaml +++ b/model/trace/database.yaml @@ -8,10 +8,12 @@ groups: - ref: db.name requirement_level: conditionally_required: If applicable. - - ref: db.statement + - ref: db.query.text requirement_level: recommended: > Should be collected by default only if there is sanitization that excludes sensitive information. + - ref: db.query.parameter + requirement_level: opt_in - ref: db.operation.name requirement_level: conditionally_required: > @@ -136,14 +138,14 @@ groups: requirement_level: conditionally_required: If other than the default database (`0`). tag: tech-specific - - ref: db.statement + - ref: db.query.text tag: tech-specific brief: > The full syntax of the Redis CLI command. examples: ["HMSET myhash field1 'Hello' field2 'World'"] note: > - For **Redis**, the value provided for `db.statement` SHOULD correspond to the syntax of the Redis CLI. - If, for example, the [`HMSET` command](https://redis.io/commands/hmset) is invoked, `"HMSET myhash field1 'Hello' field2 'World'"` would be a suitable value for `db.statement`. + For **Redis**, the value provided for `db.query.text` SHOULD correspond to the syntax of the Redis CLI. + If, for example, the [`HMSET` command](https://redis.io/commands/hmset) is invoked, `"HMSET myhash field1 'Hello' field2 'World'"` would be a suitable value for `db.query.text`. - id: db.mongodb type: span @@ -180,7 +182,7 @@ groups: requirement_level: required examples: [ 'https://localhost:9200/index/_search?q=user.id:kimchy' ] tag: tech-specific - - ref: db.statement + - ref: db.query.text requirement_level: recommended: > Should be collected by default for search-type queries and only if there is sanitization that excludes diff --git a/schema-next.yaml b/schema-next.yaml index 638d717e8..6a217cea7 100644 --- a/schema-next.yaml +++ b/schema-next.yaml @@ -14,6 +14,10 @@ versions: - rename_attributes: attribute_map: db.operation: db.operation.name + # https://github.com/open-telemetry/semantic-conventions/pull/866 + - rename_attributes: + attribute_map: + db.statement: db.query.text metrics: changes: # https://github.com/open-telemetry/semantic-conventions/pull/484