-
Notifications
You must be signed in to change notification settings - Fork 615
Description
What version of OpenTelemetry are you using?
@opentelemetry/instrumentation-pg:0.59.0@opentelemetry/auto-instrumentations-node:0.65.0@opentelemetry/sdk-node:0.206.0
What version of Node are you using?
v22.21.0
What did you do?
I'm using Drizzle ORM with PostgreSQL with prepared statements, which internally calls pg.Client.query() with the following signature:
client.query(
{ name: 'statement_name', text: 'SELECT * FROM users WHERE id = $1' },
[123] // values passed as second argument
)I enabled enhancedDatabaseReporting: true in the pg instrumentation config:
'@opentelemetry/instrumentation-pg': {
enabled: true,
enhancedDatabaseReporting: true,
}What did you expect to see?
I expected to see the db.postgresql.values attribute in my spans containing the query parameter values (e.g., ["123"]).
What did you see instead?
The db.postgresql.values attribute is not present in the spans. The span only contains:
db.statement: The SQL query textdb.postgresql.plan: The prepared statement name- Other connection attributes
But no parameter values.
Root Cause
The bug is in instrumentation.ts:
const queryConfig = firstArgIsString
? {
text: arg0 as string,
values: Array.isArray(args[1]) ? args[1] : undefined, // β
Checks args[1]
}
: firstArgIsQueryObjectWithText
? (arg0 as utils.ObjectWithText) // β Just casts arg0, ignores args[1]!
: undefined;When the first argument is a query config object (common with prepared statements), the code just casts arg0 without checking if values are passed as args[1]. This means queryConfig.values remains undefined even when values are provided.
Proposed Fix
const queryConfig = firstArgIsString
? {
text: arg0 as string,
values: Array.isArray(args[1]) ? args[1] : undefined,
}
: firstArgIsQueryObjectWithText
? {
...(arg0 as utils.ObjectWithText),
// Merge values from args[1] if not already in the config object
values: (arg0 as any).values ?? (Array.isArray(args[1]) ? args[1] : undefined),
}
: undefined;This would check for values in args[1] when using a query config object, just like it already does for string queries.
Workaround
As a temporary workaround, I'm patching pg.Client.prototype.query and pg.Pool.prototype.query before OpenTelemetry instruments them, to merge args[1] into args[0].values when this pattern is detected.
Additional context
This affects any ORM or library that uses prepared statements with the signature query(config, values) where values are passed separately from the config object. This includes:
- Drizzle ORM (when using
.prepare()) - Potentially other ORMs that use a similar pattern
The requestHook cannot work around this issue because by the time it's called, queryConfig.values is already undefined.
Tip: React with π to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.