From 49a03892c05dbeda98badeb07847240869442384 Mon Sep 17 00:00:00 2001 From: Haddas Bronfman <85441461+haddasbronfman@users.noreply.github.com> Date: Thu, 4 May 2023 15:02:53 +0300 Subject: [PATCH] fix(pg-values): values should be parsable when enhancedDatabaseRepoting:true (#1453) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(pg-values): values should be parsable when enhancedDatabaseReporting:true * fix(pg-values): add try catch * fix(pg-values): lint * fix(pg-values): fixes * fix(pg-values): fix * Update plugins/node/opentelemetry-instrumentation-pg/src/utils.ts Co-authored-by: Gerhard Stöbich * fix(pg-values): support buffer, object, null and undefined * Update plugins/node/opentelemetry-instrumentation-pg/src/utils.ts Co-authored-by: Gerhard Stöbich * fix(pg-values): fixes * fix(pg-values): lint * fix(pg-values): add test for 'toPostgres' * fix(pg-values): fix --------- Co-authored-by: Gerhard Stöbich --- .../src/utils.ts | 28 +++++++--- .../test/pg.test.ts | 54 +++++++++++++++++++ .../test/utils.test.ts | 2 +- 3 files changed, 75 insertions(+), 9 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-pg/src/utils.ts b/plugins/node/opentelemetry-instrumentation-pg/src/utils.ts index 2e4176817df..1565d6d03b7 100644 --- a/plugins/node/opentelemetry-instrumentation-pg/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-pg/src/utils.ts @@ -43,10 +43,6 @@ import type * as pgTypes from 'pg'; import { PgInstrumentation } from './'; import { safeExecuteInTheMiddle } from '@opentelemetry/instrumentation'; -function arrayStringifyHelper(arr: Array): string { - return '[' + arr.toString() + ']'; -} - /** * Helper function to get a low cardinality span name from whatever info we have * about the query. @@ -156,10 +152,26 @@ export function handleConfigQuery( instrumentationConfig.enhancedDatabaseReporting && Array.isArray(queryConfig.values) ) { - span.setAttribute( - AttributeNames.PG_VALUES, - arrayStringifyHelper(queryConfig.values) - ); + try { + const convertedValues = queryConfig.values.map(value => { + if (value == null) { + return 'null'; + } else if (value instanceof Buffer) { + return value.toString(); + } else if (typeof value === 'object') { + if (typeof value.toPostgres === 'function') { + return value.toPostgres(); + } + return JSON.stringify(value); + } else { + //string, number + return value.toString(); + } + }); + span.setAttribute(AttributeNames.PG_VALUES, convertedValues); + } catch (e) { + diag.error('failed to stringify ', queryConfig.values, e); + } } // Set plan name attribute, if present diff --git a/plugins/node/opentelemetry-instrumentation-pg/test/pg.test.ts b/plugins/node/opentelemetry-instrumentation-pg/test/pg.test.ts index b78e036ab6f..a6c368ad329 100644 --- a/plugins/node/opentelemetry-instrumentation-pg/test/pg.test.ts +++ b/plugins/node/opentelemetry-instrumentation-pg/test/pg.test.ts @@ -513,6 +513,60 @@ describe('pg', () => { }); }); + describe('Check configuration enhancedDatabaseReporting:true', () => { + const obj = { type: 'Fiat', model: '500', color: 'white' }; + const buf = Buffer.from('abc'); + const objWithToPostgres = { + toPostgres: () => { + return 'custom value'; + }, + }; + const query = + 'SELECT $1::text as msg1, $2::bytea as bufferParam, $3::integer as numberParam, $4::jsonb as objectParam, $5::text as objToPostgres, $6::text as msg2, $7::text as msg3'; + const values = [ + 'Hello,World', + buf, + 6, + obj, + objWithToPostgres, + null, + undefined, + ]; + + const events: TimedEvent[] = []; + + const attributes = { + ...DEFAULT_ATTRIBUTES, + [SemanticAttributes.DB_STATEMENT]: query, + [AttributeNames.PG_VALUES]: [ + 'Hello,World', + 'abc', + '6', + '{"type":"Fiat","model":"500","color":"white"}', + 'custom value', + 'null', + 'null', + ], + }; + beforeEach(async () => { + create({ + enhancedDatabaseReporting: true, + }); + }); + + it('When enhancedDatabaseReporting:true, values should appear as parsable array of strings', done => { + const span = tracer.startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + client.query(query, values, (err, res) => { + assert.strictEqual(err, null); + assert.ok(res); + runCallbackTest(span, attributes, events); + done(); + }); + }); + }); + }); + describe('when specifying a requestHook configuration', () => { const dataAttributeName = 'pg_data'; const query = 'SELECT 0::text'; diff --git a/plugins/node/opentelemetry-instrumentation-pg/test/utils.test.ts b/plugins/node/opentelemetry-instrumentation-pg/test/utils.test.ts index 2e6c8ca0d76..d7c4f1f6aa1 100644 --- a/plugins/node/opentelemetry-instrumentation-pg/test/utils.test.ts +++ b/plugins/node/opentelemetry-instrumentation-pg/test/utils.test.ts @@ -197,7 +197,7 @@ describe('utils.ts', () => { const readableSpan = getLatestSpan(); const pgValues = readableSpan.attributes[AttributeNames.PG_VALUES]; - assert.strictEqual(pgValues, '[0]'); + assert.deepStrictEqual(pgValues, ['0']); }); });