Skip to content

Commit 2e5a9d6

Browse files
authored
fix(instrumentation-pg): preserve SQL template text property (#3259)
1 parent 73c7edc commit 2e5a9d6

File tree

2 files changed

+113
-13
lines changed

2 files changed

+113
-13
lines changed

packages/instrumentation-pg/src/instrumentation.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -333,19 +333,24 @@ export class PgInstrumentation extends InstrumentationBase<PgInstrumentationConf
333333
// TODO: remove the `as ...` casts below when the TS version is upgraded.
334334
// Newer TS versions will use the result of firstArgIsQueryObjectWithText
335335
// to properly narrow arg0, but TS 4.3.5 does not.
336-
const queryConfig = firstArgIsString
337-
? {
338-
text: arg0 as string,
339-
values: Array.isArray(args[1]) ? args[1] : undefined,
340-
}
341-
: firstArgIsQueryObjectWithText
342-
? {
343-
...(arg0 as any),
344-
values:
345-
(arg0 as any).values ??
346-
(Array.isArray(args[1]) ? args[1] : undefined),
347-
}
348-
: undefined;
336+
let queryConfig: any;
337+
338+
if (firstArgIsString) {
339+
queryConfig = {
340+
text: arg0 as string,
341+
values: Array.isArray(args[1]) ? args[1] : undefined,
342+
};
343+
} else if (firstArgIsQueryObjectWithText) {
344+
const q = arg0 as any;
345+
346+
if (q.values === undefined && Array.isArray(args[1])) {
347+
q.values = args[1];
348+
}
349+
350+
queryConfig = q;
351+
} else {
352+
queryConfig = undefined;
353+
}
349354

350355
const attributes: Attributes = {
351356
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,

packages/instrumentation-pg/test/pg.test.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,101 @@ describe('pg', () => {
10391039
done();
10401040
});
10411041
});
1042+
1043+
it('should generate traces for SQL template literal objects ', async () => {
1044+
const span = tracer.startSpan('test span');
1045+
await context.with(trace.setSpan(context.active(), span), async () => {
1046+
// Mock SQLStatement from sql-template-strings library
1047+
class SQLStatement {
1048+
strings: string[];
1049+
values: any[];
1050+
1051+
constructor(strings: string[], values: any[]) {
1052+
this.strings = strings;
1053+
this.values = values;
1054+
}
1055+
1056+
get text(): string {
1057+
return this.strings.reduce(
1058+
(prev: string, curr: string, i: number) => prev + '$' + i + curr
1059+
);
1060+
}
1061+
}
1062+
1063+
const name = 'pg_tables';
1064+
const sqlQuery = new SQLStatement(
1065+
['SELECT * FROM information_schema.tables WHERE table_name = ', ''],
1066+
[name]
1067+
);
1068+
const resPromise = await client.query(sqlQuery);
1069+
assert.ok(resPromise);
1070+
1071+
const spans = memoryExporter.getFinishedSpans();
1072+
assert.strictEqual(spans.length, 1);
1073+
const pgSpan = spans[0];
1074+
1075+
assert.strictEqual(pgSpan.name, 'pg.query:SELECT otel_pg_database');
1076+
assert.strictEqual(
1077+
pgSpan.attributes[ATTR_DB_STATEMENT],
1078+
'SELECT * FROM information_schema.tables WHERE table_name = $1'
1079+
);
1080+
1081+
const executedQueries = getExecutedQueries();
1082+
assert.ok(executedQueries.length > 0);
1083+
assert.strictEqual(
1084+
executedQueries[executedQueries.length - 1].text,
1085+
'SELECT * FROM information_schema.tables WHERE table_name = $1'
1086+
);
1087+
});
1088+
});
1089+
1090+
it('should generate traces for SQL template literals with added comments', async () => {
1091+
instrumentation.setConfig({
1092+
addSqlCommenterCommentToQueries: true,
1093+
});
1094+
1095+
const span = tracer.startSpan('test span');
1096+
1097+
await context.with(trace.setSpan(context.active(), span), async () => {
1098+
// Mock SQLStatement from sql-template-strings library
1099+
class SQLStatement {
1100+
strings: string[];
1101+
values: any[];
1102+
1103+
constructor(strings: string[], values: any[]) {
1104+
this.strings = strings;
1105+
this.values = values;
1106+
}
1107+
1108+
get text(): string {
1109+
return this.strings.reduce(
1110+
(prev: string, curr: string, i: number) => prev + '$' + i + curr
1111+
);
1112+
}
1113+
}
1114+
const tableName = 'pg_tables';
1115+
const sqlQuery = new SQLStatement(
1116+
['SELECT * FROM information_schema.tables WHERE table_name = ', ''],
1117+
[tableName]
1118+
);
1119+
1120+
const res = await client.query(sqlQuery);
1121+
assert.ok(res);
1122+
1123+
const spans = memoryExporter.getFinishedSpans();
1124+
assert.strictEqual(spans.length, 1);
1125+
const pgSpan = spans[0];
1126+
1127+
const commentedQuery = addSqlCommenterComment(
1128+
trace.wrapSpanContext(pgSpan.spanContext()),
1129+
sqlQuery.text
1130+
);
1131+
const executedQueries = getExecutedQueries();
1132+
assert.ok(executedQueries.length > 0);
1133+
const lastQuery = executedQueries[executedQueries.length - 1];
1134+
assert.strictEqual(lastQuery.text, commentedQuery);
1135+
});
1136+
});
10421137
});
10431138

10441139
describe('exception event recording', () => {

0 commit comments

Comments
 (0)