From 353e7aeb46f3db8e85b502d3d5fcfb7091b8f042 Mon Sep 17 00:00:00 2001 From: Arya Date: Sat, 29 Nov 2025 16:48:58 +0530 Subject: [PATCH 1/3] fix(instrumentation-pg): preserve SQL template text property --- .../instrumentation-pg/src/instrumentation.ts | 14 +++--- packages/instrumentation-pg/test/pg.test.ts | 47 +++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/packages/instrumentation-pg/src/instrumentation.ts b/packages/instrumentation-pg/src/instrumentation.ts index 69bb080e9e..89cca90d1d 100644 --- a/packages/instrumentation-pg/src/instrumentation.ts +++ b/packages/instrumentation-pg/src/instrumentation.ts @@ -339,13 +339,15 @@ export class PgInstrumentation extends InstrumentationBase { + const query = arg0 as any; + // If the query object has no values yet, use the second argument as values + if (query.values === undefined && Array.isArray(args[1])) { + query.values = args[1]; } - : undefined; + return query; + })() + : undefined; const attributes: Attributes = { [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL, diff --git a/packages/instrumentation-pg/test/pg.test.ts b/packages/instrumentation-pg/test/pg.test.ts index d930dd263a..886bd06607 100644 --- a/packages/instrumentation-pg/test/pg.test.ts +++ b/packages/instrumentation-pg/test/pg.test.ts @@ -1039,6 +1039,53 @@ describe('pg', () => { done(); }); }); + + it('should handle SQL template literal objects', async () => { + const span = tracer.startSpan('test span'); + await context.with(trace.setSpan(context.active(), span), async () => { + // Mock SQLStatement from sql-template-strings library + class SQLStatement { + strings: string[]; + values: any[]; + + constructor(strings: string[], values: any[]) { + this.strings = strings; + this.values = values; + } + + get text(): string { + return this.strings.reduce( + (prev: string, curr: string, i: number) => prev + '$' + i + curr + ); + } + } + + const name = 'pg_tables'; + const sqlQuery = new SQLStatement( + ['SELECT * FROM information_schema.tables WHERE table_name = ', ''], + [name] + ); + const resPromise = await client.query(sqlQuery); + assert.ok(resPromise); + + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + const pgSpan = spans[0]; + + assert.strictEqual(pgSpan.name, 'pg.query:SELECT otel_pg_database'); + assert.strictEqual( + pgSpan.attributes[ATTR_DB_STATEMENT], + 'SELECT * FROM information_schema.tables WHERE table_name = $1' + ); + + const executedQueries = getExecutedQueries(); + assert.ok(executedQueries.length > 0); + assert.strictEqual( + executedQueries[executedQueries.length - 1].text, + 'SELECT * FROM information_schema.tables WHERE table_name = $1' + ); + }); + }); }); describe('exception event recording', () => { From 84db185a2febacf7cd09f06a6debb936ed41c359 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 1 Dec 2025 21:51:35 +0530 Subject: [PATCH 2/3] chore: removed the ternary condition --- .../instrumentation-pg/src/instrumentation.ts | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/instrumentation-pg/src/instrumentation.ts b/packages/instrumentation-pg/src/instrumentation.ts index 89cca90d1d..fc756c0c48 100644 --- a/packages/instrumentation-pg/src/instrumentation.ts +++ b/packages/instrumentation-pg/src/instrumentation.ts @@ -333,21 +333,24 @@ export class PgInstrumentation extends InstrumentationBase { - const query = arg0 as any; - // If the query object has no values yet, use the second argument as values - if (query.values === undefined && Array.isArray(args[1])) { - query.values = args[1]; - } - return query; - })() - : undefined; + let queryConfig: any; + + if (firstArgIsString) { + queryConfig = { + text: arg0 as string, + values: Array.isArray(args[1]) ? args[1] : undefined, + }; + } else if (firstArgIsQueryObjectWithText) { + const q = arg0 as any; + + if (q.values === undefined && Array.isArray(args[1])) { + q.values = args[1]; + } + + queryConfig = q; + } else { + queryConfig = undefined; + } const attributes: Attributes = { [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL, From b46fac4fef312fce3efd2ade184b779456962bc1 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 1 Dec 2025 23:11:06 +0530 Subject: [PATCH 3/3] test: extend test to cover SQL template literals with added comments --- packages/instrumentation-pg/test/pg.test.ts | 50 ++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/instrumentation-pg/test/pg.test.ts b/packages/instrumentation-pg/test/pg.test.ts index 886bd06607..9864568f5a 100644 --- a/packages/instrumentation-pg/test/pg.test.ts +++ b/packages/instrumentation-pg/test/pg.test.ts @@ -1040,7 +1040,7 @@ describe('pg', () => { }); }); - it('should handle SQL template literal objects', async () => { + it('should generate traces for SQL template literal objects ', async () => { const span = tracer.startSpan('test span'); await context.with(trace.setSpan(context.active(), span), async () => { // Mock SQLStatement from sql-template-strings library @@ -1086,6 +1086,54 @@ describe('pg', () => { ); }); }); + + it('should generate traces for SQL template literals with added comments', async () => { + instrumentation.setConfig({ + addSqlCommenterCommentToQueries: true, + }); + + const span = tracer.startSpan('test span'); + + await context.with(trace.setSpan(context.active(), span), async () => { + // Mock SQLStatement from sql-template-strings library + class SQLStatement { + strings: string[]; + values: any[]; + + constructor(strings: string[], values: any[]) { + this.strings = strings; + this.values = values; + } + + get text(): string { + return this.strings.reduce( + (prev: string, curr: string, i: number) => prev + '$' + i + curr + ); + } + } + const tableName = 'pg_tables'; + const sqlQuery = new SQLStatement( + ['SELECT * FROM information_schema.tables WHERE table_name = ', ''], + [tableName] + ); + + const res = await client.query(sqlQuery); + assert.ok(res); + + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + const pgSpan = spans[0]; + + const commentedQuery = addSqlCommenterComment( + trace.wrapSpanContext(pgSpan.spanContext()), + sqlQuery.text + ); + const executedQueries = getExecutedQueries(); + assert.ok(executedQueries.length > 0); + const lastQuery = executedQueries[executedQueries.length - 1]; + assert.strictEqual(lastQuery.text, commentedQuery); + }); + }); }); describe('exception event recording', () => {