feat: replace db.statement.parameters with db.query.parameter.<key> per OTel semconv#1
Closed
feat: replace db.statement.parameters with db.query.parameter.<key> per OTel semconv#1
Conversation
Lotram
commented
Mar 6, 2026
b061a56 to
8157850
Compare
gregoiredx
reviewed
Mar 6, 2026
| yield | ||
|
|
||
|
|
||
| def db_query_parameter_attributes( |
There was a problem hiding this comment.
this should probably not be in opentelemetry/instrumentation/utils.py it's very dbapi related, here we are in the utils common to all instrumentations
gregoiredx
reviewed
Mar 6, 2026
|
|
||
| if parameters is not None and len(parameters) > 0: | ||
| span_attributes["db.statement.parameters"] = str(parameters) | ||
| span_attributes.update(db_query_parameter_attributes(parameters)) |
There was a problem hiding this comment.
I would keep it simple and
Suggested change
| span_attributes.update(db_query_parameter_attributes(parameters)) | |
| span_attributes["db.statement.parameters"] = str(parameters) | |
| for key, value in enumerate(parameters): | |
| attrs[f"{DB_QUERY_PARAMETER_TEMPLATE}.{key}"] = repr(value) |
gregoiredx
reviewed
Mar 6, 2026
Comment on lines
+16
to
+20
| - `opentelemetry-instrumentation-dbapi`, `opentelemetry-instrumentation-asyncpg`, | ||
| `opentelemetry-instrumentation-tortoiseorm`: Replace `db.statement.parameters` | ||
| attribute with individual `db.query.parameter.<key>` attributes following | ||
| [OTel database semantic conventions](https://opentelemetry.io/docs/specs/semconv/attributes-registry/db/). | ||
| This also affects instrumentations that delegate to dbapi (psycopg, psycopg2, aiopg, mysql, etc.). |
There was a problem hiding this comment.
I would try to avoid breaking change and make the new attribute optional
gregoiredx
reviewed
Mar 6, 2026
There was a problem hiding this comment.
This is asyncpg, that's not where we want the feature!
Owner
Author
There was a problem hiding this comment.
I simply wanted the change to be propagated everywhere
c0e508e to
f0e4aa6
Compare
…<key> Replace the single stringified db.statement.parameters attribute with individual db.query.parameter.<key> attributes following OTel semconv. For positional parameters (tuple/list): db.query.parameter.0, .1, etc. For named parameters (dict): db.query.parameter.<name>. Values use repr() to preserve type information. This also affects all instrumentations that delegate to dbapi: psycopg, psycopg2, aiopg, mysql, etc. BREAKING CHANGE: db.statement.parameters span attribute replaced by individual db.query.parameter.<key> attributes.
…r.<key> Replace db.statement.parameters with individual db.query.parameter.<key> attributes. asyncpg parameters are always positional (tuple from *args), so a simple indexed loop is used.
…meter.<key> Replace db.statement.parameters with individual db.query.parameter.<key> attributes. Tortoise parameters are always positional (tuple from args[1:]), so a simple indexed loop is used.
f0e4aa6 to
e65a740
Compare
Owner
Author
|
Closing for now, as db.operation.parameter.key is not stable yet |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replace the non-standard
db.statement.parametersspan attribute with individualdb.query.parameter.<key>attributes, following the OpenTelemetry database semantic conventions.Before
A single attribute containing the stringified tuple of all parameters:
After
Individual attributes, one per parameter:
For dict-style parameters (named placeholders, dbapi only):
Motivation
The
db.statement.parametersattribute was a non-standard, implementation-specific choice. The OTel semantic conventions definedb.query.parameter.<key>as individual per-parameter attributes with string values. This change aligns the instrumentation with that specification.Design choices
Inline logic per instrumentation (no shared helper)
Each instrumentation knows the shape of its parameters:
*args) — simple indexed loopargs[1:]) — simple indexed loopSince the logic is a simple for-loop in each case, it's inlined at each call site rather than abstracted into a shared utility function.
repr()instead ofstr()for parameter valuesThe old code used
str(args[1])on the entire tuple, which internally callsrepr()on each element (that's howtuple.__str__works). To preserve the same per-element representation — and to avoid ambiguity between e.g. the string"42"and the integer42— we userepr()on individual values. This means strings appear quoted ('param1Value') while numbers and booleans appear unquoted (42,False).DB_QUERY_PARAMETER_TEMPLATEconstantUses the existing
DB_QUERY_PARAMETER_TEMPLATEconstant fromopentelemetry.semconv._incubating.attributes.db_attributes(value:"db.query.parameter") rather than hardcoding the string, following the pattern used throughout the repo.tortoiseorm: parameters grouped under a single key
The tortoiseorm instrumentation wraps tortoise DB client methods (e.g.
execute_insert(query, values)). The existing code passesargs[1:](all arguments after the query) as theparametersvalue. This results in all query values being grouped underdb.query.parameter.0as a single repr'd list (e.g."['Alice', 'Engineer']"), rather than one attribute per parameter.We chose not to change this behavior in this PR (e.g. by unwrapping
args[1]instead ofargs[1:]) because the tortoise client methods have varying signatures across backends and operation types (execute_insert,execute_many,execute_query,execute_script), and we lack sufficient understanding of the ORM internals to safely flatten the parameters in all cases. This can be improved in a follow-up.Changes
opentelemetry-instrumentation-dbapi: Replaceddb.statement.parameterswith inlinedb.query.parameter.<key>logic inTracedCursor._populate_span; handles both positional (tuple/list) and named (dict) parameters; updated docstrings and tests (dbapi, aiopg, psycopg)opentelemetry-instrumentation-asyncpg: Replaceddb.statement.parameterswith inline indexed loop in_hydrate_span_from_args; updated docker functional testsopentelemetry-instrumentation-tortoiseorm: Replaceddb.statement.parameterswith inline indexed loop; added tests for multiple parameters and no parametersBreaking change
Consumers that relied on the
db.statement.parametersattribute will need to switch to reading individualdb.query.parameter.<key>attributes. This affects all DB instrumentations that supportcapture_parameters=True.Unlike the
db.statement→db.query.textmigration (which usesOTEL_SEMCONV_STABILITY_OPT_INfor a gradual transition), we don't provide a dual-emit feature flag here.db.statement.parameterswas never part of the OTel semantic conventions — it was a custom, non-standard attribute. A clean break is more appropriate than a transition period that would legitimize the old format.Related PRs
db.statement→db.query.text,db.name→db.namespace, etc. via theOTEL_SEMCONV_STABILITY_OPT_INmechanism using the existing_semconv.pyhelpers. Our PR is complementary: it handles thedb.statement.parameters→db.query.parameter.<key>migration, which DB semantic convention stability migration for DB-API and 7 inheriting db client instrumentors open-telemetry/opentelemetry-python-contrib#4109 does not cover. The two PRs will conflict on the same dbapi files and should be coordinated. Note thatdb.query.parameter.<key>is already the new semconv name, so it does not need the old/new dual-emit pattern.Follow-ups
db.statement→db.query.text: The OTel semantic conventions also deprecatedb.statementin favor ofdb.query.text. PR #4109 handles this for dbapi and its dependents. asyncpg and tortoiseorm still need the same migration.args[1]instead ofargs[1:]to emit one attribute per parameter instead of a single grouped list (see design choices above).