From 3a1efc449d69ddef97b6a7562ae17db958de0403 Mon Sep 17 00:00:00 2001 From: Michele Azzolari Date: Fri, 17 Jan 2025 06:58:51 +0100 Subject: [PATCH 1/4] test(instrumentation-mysql2): add test suite for Promise API --- .../test/mysql.test.ts | 1826 +++++++++-------- 1 file changed, 984 insertions(+), 842 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts index ef14d7d982..f6b748bf0c 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts @@ -49,56 +49,18 @@ instrumentation.enable(); instrumentation.disable(); import * as mysqlTypes from 'mysql2'; +import * as mysqlTypesProm from 'mysql2/promise'; interface Result extends mysqlTypes.RowDataPacket { solution: number; } describe('mysql2', () => { - let contextManager: AsyncHooksContextManager; - let connection: mysqlTypes.Connection; - let rootConnection: mysqlTypes.Connection; - let pool: mysqlTypes.Pool; - let poolCluster: mysqlTypes.PoolCluster; - const provider = new BasicTracerProvider(); const testMysql = process.env.RUN_MYSQL_TESTS; // For CI: assumes local mysql db is already available const testMysqlLocally = process.env.RUN_MYSQL_TESTS_LOCAL; // For local: spins up local mysql db via docker const shouldTest = testMysql || testMysqlLocally; // Skips these tests if false (default) - const memoryExporter = new InMemorySpanExporter(); - - const getLastQueries = (count: number) => - new Promise(res => { - const queries: string[] = []; - const query = rootConnection.query({ - sql: "SELECT * FROM mysql.general_log WHERE command_type = 'Query' ORDER BY event_time DESC LIMIT ? OFFSET 1", - values: [count], - }); - - query.on('result', (row: { argument: string | Buffer }) => { - if (typeof row.argument === 'string') { - queries.push(row.argument); - } else { - queries.push(row.argument.toString('utf-8')); - } - }); - query.on('end', () => res(queries)); - }); before(function (done) { - if (!shouldTest) { - // this.skip() workaround - // https://github.com/mochajs/mocha/issues/2683#issuecomment-375629901 - this.test!.parent!.pending = true; - this.skip(); - } - provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); - rootConnection = mysqlTypes.createConnection({ - port, - user: 'root', - host, - password: rootPassword, - database, - }); if (testMysqlLocally) { testUtils.startDocker('mysql'); // wait 15 seconds for docker container to start @@ -110,457 +72,492 @@ describe('mysql2', () => { }); after(function (done) { - rootConnection.end(() => { - if (testMysqlLocally) { - this.timeout(5000); - testUtils.cleanUpDocker('mysql'); + if (testMysqlLocally) { + this.timeout(5000); + testUtils.cleanUpDocker('mysql'); + } + done(); + }); + + describe('callback API', () => { + let contextManager: AsyncHooksContextManager; + const provider = new BasicTracerProvider(); + const memoryExporter = new InMemorySpanExporter(); + + let connection: mysqlTypes.Connection; + let rootConnection: mysqlTypes.Connection; + let pool: mysqlTypes.Pool; + let poolCluster: mysqlTypes.PoolCluster; + + const getLastQueries = (count: number) => + new Promise(res => { + const queries: string[] = []; + const query = rootConnection.query({ + sql: "SELECT * FROM mysql.general_log WHERE command_type = 'Query' ORDER BY event_time DESC LIMIT ? OFFSET 1", + values: [count], + }); + + query.on('result', (row: { argument: string | Buffer }) => { + if (typeof row.argument === 'string') { + queries.push(row.argument); + } else { + queries.push(row.argument.toString('utf-8')); + } + }); + query.on('end', () => res(queries)); + }); + + before(function (done) { + if (!shouldTest) { + // this.skip() workaround + // https://github.com/mochajs/mocha/issues/2683#issuecomment-375629901 + this.test!.parent!.pending = true; + this.skip(); } + provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + rootConnection = mysqlTypes.createConnection({ + port, + user: 'root', + host, + password: rootPassword, + database, + }); done(); }); - }); - beforeEach(() => { - instrumentation.disable(); - contextManager = new AsyncHooksContextManager().enable(); - context.setGlobalContextManager(contextManager); - instrumentation.setTracerProvider(provider); - instrumentation.enable(); - connection = mysqlTypes.createConnection({ - port, - user, - host, - password, - database, - }); - pool = mysqlTypes.createPool({ - port, - user, - host, - password, - database, + after(function (done) { + rootConnection.end(() => { + done(); + }); }); - poolCluster = mysqlTypes.createPoolCluster(); - // the implementation actually accepts ConnectionConfig as well, - // but the types do not reflect that - poolCluster.add('name', { - port, - user, - host, - password, - database, + + beforeEach(() => { + instrumentation.disable(); + contextManager = new AsyncHooksContextManager().enable(); + context.setGlobalContextManager(contextManager); + instrumentation.setTracerProvider(provider); + instrumentation.enable(); + connection = mysqlTypes.createConnection({ + port, + user, + host, + password, + database, + }); + pool = mysqlTypes.createPool({ + port, + user, + host, + password, + database, + }); + poolCluster = mysqlTypes.createPoolCluster(); + // the implementation actually accepts ConnectionConfig as well, + // but the types do not reflect that + poolCluster.add('name', { + port, + user, + host, + password, + database, + }); }); - }); - afterEach(done => { - context.disable(); - memoryExporter.reset(); - instrumentation.setConfig({}); - instrumentation.disable(); - connection.end(() => { - pool.end(() => { - if (isPoolClusterEndIgnoreCallback()) { - poolCluster.end(); - done(); - } else { - // PoolCluster.end types in the package are invalid - // https://github.com/sidorares/node-mysql2/pull/1332 - (poolCluster as any).end(() => { + afterEach(done => { + context.disable(); + memoryExporter.reset(); + instrumentation.setConfig({}); + instrumentation.disable(); + connection.end(() => { + pool.end(() => { + if (isPoolClusterEndIgnoreCallback()) { + poolCluster.end(); done(); - }); - } + } else { + // PoolCluster.end types in the package are invalid + // https://github.com/sidorares/node-mysql2/pull/1332 + (poolCluster as any).end(() => { + done(); + }); + } + }); }); }); - }); - describe('when the query is a string', () => { - it('should name the span accordingly ', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - const query = connection.query(sql); + describe('when the query is a string', () => { + it('should name the span accordingly ', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + const query = connection.query(sql); - query.on('end', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans[0].name, 'SELECT'); - assert.strictEqual(spans[0].attributes[SEMATTRS_DB_STATEMENT], sql); - done(); + query.on('end', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans[0].name, 'SELECT'); + assert.strictEqual(spans[0].attributes[SEMATTRS_DB_STATEMENT], sql); + done(); + }); }); }); }); - }); - describe('when the query is an object', () => { - it('should name the span accordingly ', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - const query = connection.query({ sql, values: [1] }); + describe('when the query is an object', () => { + it('should name the span accordingly ', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + const query = connection.query({ sql, values: [1] }); - query.on('end', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans[0].name, 'SELECT'); - assert.strictEqual( - spans[0].attributes[SEMATTRS_DB_STATEMENT], - query.sql - ); - done(); + query.on('end', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans[0].name, 'SELECT'); + assert.strictEqual( + spans[0].attributes[SEMATTRS_DB_STATEMENT], + query.sql + ); + done(); + }); }); }); }); - }); - describe('#Connection.query', () => { - it('should intercept connection.query(text: string)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - const query = connection.query(sql); - let rows = 0; - - query.on('result', (row: mysqlTypes.RowDataPacket) => { - assert.strictEqual(row.solution, 2); - rows += 1; + describe('#Connection.query', () => { + it('should intercept connection.query(text: string)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + const query = connection.query(sql); + let rows = 0; + + query.on('result', (row: mysqlTypes.RowDataPacket) => { + assert.strictEqual(row.solution, 2); + rows += 1; + }); + + query.on('end', () => { + try { + assert.strictEqual(rows, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + } catch (e) { + done(e); + } + done(); + }); }); + }); - query.on('end', () => { - try { - assert.strictEqual(rows, 1); + it('should intercept connection.query(text: string, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql); - } catch (e) { - done(e); - } - done(); + done(); + }); }); }); - }); - it('should intercept connection.query(text: string, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + it('should intercept connection.query(text: options, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + connection.query( + { sql, values: [1] }, + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); }); }); - }); - it('should intercept connection.query(text: options, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - connection.query( - { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { + it('should intercept connection.query(text: options, values: [], callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + connection.query( + { sql }, + [1], + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); + }); + }); + + it('should intercept connection.query(text: string, values: [], callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + connection.query(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { assert.ifError(err); assert.ok(res); - assert.strictEqual(res[0].solution, 2); + assert.strictEqual(res[0].solution, 1); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql, [1]); done(); - } - ); + }); + }); }); - }); - it('should intercept connection.query(text: options, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - connection.query( - { sql }, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { + it('should intercept connection.query(text: string, value: any, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + connection.query(sql, 1, (err, res: mysqlTypes.RowDataPacket[]) => { assert.ifError(err); assert.ok(res); - assert.strictEqual(res[0].solution, 2); + assert.strictEqual(res[0].solution, 1); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql, [1]); done(); - } - ); + }); + }); }); - }); - it('should intercept connection.query(text: string, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - connection.query(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); + it('should attach error messages to spans', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + connection.query(sql, (err, res) => { + assert.ok(err); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, undefined, err!.message); + done(); + }); }); }); - }); - it('should intercept connection.query(text: string, value: any, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - connection.query(sql, 1, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); + it('should not add comment by default', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + connection.query('SELECT 1+1 as solution', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + getLastQueries(1).then(([query]) => { + try { + assert.doesNotMatch(query, /.*traceparent.*/); + done(); + } catch (e) { + done(e); + } + }); + }); }); }); - }); - it('should attach error messages to spans', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - connection.query(sql, (err, res) => { - assert.ok(err); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, undefined, err!.message); - done(); + it('should not add comment when specified if existing block comment', done => { + instrumentation.setConfig({ + addSqlCommenterCommentToQueries: true, + } as any); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + connection.query('SELECT 1+1 as solution /*block comment*/', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + getLastQueries(1).then(([query]) => { + assert.doesNotMatch(query, /.*traceparent.*/); + done(); + }); + }); }); }); - }); - it('should not add comment by default', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - connection.query('SELECT 1+1 as solution', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - try { + it('should not add comment when specified if existing line comment', done => { + instrumentation.setConfig({ + addSqlCommenterCommentToQueries: true, + } as any); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + connection.query('SELECT 1+1 as solution -- line comment', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + getLastQueries(1).then(([query]) => { assert.doesNotMatch(query, /.*traceparent.*/); done(); - } catch (e) { - done(e); - } + }); }); }); }); - }); - it('should not add comment when specified if existing block comment', done => { - instrumentation.setConfig({ - addSqlCommenterCommentToQueries: true, - } as any); - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - connection.query('SELECT 1+1 as solution /*block comment*/', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - assert.doesNotMatch(query, /.*traceparent.*/); - done(); + it('should add comment when specified if no existing comment', done => { + instrumentation.setConfig({ + addSqlCommenterCommentToQueries: true, + } as any); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + connection.query('SELECT 1+1 as solution', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + getLastQueries(1).then(([query]) => { + assert.match(query, /.*traceparent.*/); + done(); + }); }); }); }); }); - it('should not add comment when specified if existing line comment', done => { - instrumentation.setConfig({ - addSqlCommenterCommentToQueries: true, - } as any); - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - connection.query('SELECT 1+1 as solution -- line comment', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - assert.doesNotMatch(query, /.*traceparent.*/); + describe('#Connection.execute', () => { + it('should intercept connection.execute(text: string)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + const query = connection.execute(sql); + let rows = 0; + + query.on('result', (row: mysqlTypes.RowDataPacket) => { + assert.strictEqual(row.solution, 2); + rows += 1; + }); + + query.on('end', () => { + assert.strictEqual(rows, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); done(); }); }); }); - }); - it('should add comment when specified if no existing comment', done => { - instrumentation.setConfig({ - addSqlCommenterCommentToQueries: true, - } as any); - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - connection.query('SELECT 1+1 as solution', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - assert.match(query, /.*traceparent.*/); + it('should intercept connection.execute(text: string, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + connection.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); done(); }); }); }); - }); - }); - - describe('#Connection.execute', () => { - it('should intercept connection.execute(text: string)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - const query = connection.execute(sql); - let rows = 0; - - query.on('result', (row: mysqlTypes.RowDataPacket) => { - assert.strictEqual(row.solution, 2); - rows += 1; - }); - query.on('end', () => { - assert.strictEqual(rows, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); - }); - }); - }); - - it('should intercept connection.execute(text: string, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - connection.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + it('should intercept connection.execute(text: options, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + connection.execute( + { sql, values: [1] }, + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); }); }); - }); - it('should intercept connection.execute(text: options, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - connection.execute( - { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); - }); - }); - - it('should intercept connection.execute(text: options, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - connection.execute( - { sql }, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); - }); - }); - - it('should intercept connection.execute(text: string, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - connection.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); + it('should intercept connection.execute(text: options, values: [], callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + connection.execute( + { sql }, + [1], + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); }); }); - }); - it('should intercept connection.execute(text: string, value: any, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - connection.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); + it('should intercept connection.execute(text: string, values: [], callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + connection.execute( + sql, + [1], + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); }); }); - }); - it('should attach error messages to spans', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - connection.execute(sql, (err, res) => { - assert.ok(err); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, undefined, err!.message); - done(); + it('should intercept connection.execute(text: string, value: any, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + connection.execute( + sql, + [1], + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); }); }); - }); - }); - describe('#Pool.query', () => { - it('should intercept pool.query(text: string)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - const query = pool.query(sql); - let rows = 0; - - query.on('result', (row: mysqlTypes.RowDataPacket) => { - assert.strictEqual(row.solution, 2); - rows += 1; - }); - - query.on('end', () => { - assert.strictEqual(rows, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + it('should attach error messages to spans', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + connection.execute(sql, (err, res) => { + assert.ok(err); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, undefined, err!.message); + done(); + }); }); }); }); - it('should intercept pool.getConnection().query(text: string)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.getConnection((err, conn) => { - const query = conn.query(sql); + describe('#Pool.query', () => { + it('should intercept pool.query(text: string)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + const query = pool.query(sql); let rows = 0; query.on('result', (row: mysqlTypes.RowDataPacket) => { @@ -577,362 +574,260 @@ describe('mysql2', () => { }); }); }); - }); - it('should intercept pool.query(text: string, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); - }); - }); - }); + it('should intercept pool.getConnection().query(text: string)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + pool.getConnection((err, conn) => { + const query = conn.query(sql); + let rows = 0; - it('should intercept pool.getConnection().query(text: string, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.getConnection((err, conn) => { - conn.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + query.on('result', (row: mysqlTypes.RowDataPacket) => { + assert.strictEqual(row.solution, 2); + rows += 1; + }); + + query.on('end', () => { + assert.strictEqual(rows, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); }); }); }); - }); - it('should intercept pool.query(text: options, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - pool.query( - { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { + it('should intercept pool.query(text: string, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + pool.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); + assertSpan(spans[0], sql); done(); - } - ); - }); - }); - - it('should intercept pool.query(text: options, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - pool.query({ sql }, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - }); - }); - }); - - it('should intercept pool.query(text: string, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - pool.query(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); + }); }); }); - }); - it('should intercept pool.query(text: string, value: any, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - pool.query(sql, 1, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); + it('should intercept pool.getConnection().query(text: string, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + pool.getConnection((err, conn) => { + conn.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); + }); }); }); - }); - it('should attach error messages to spans', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - pool.query(sql, (err, res) => { - assert.ok(err); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, undefined, err!.message); - done(); + it('should intercept pool.query(text: options, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + pool.query( + { sql, values: [1] }, + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); }); }); - }); - it('should not add comment by default', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - pool.query('SELECT 1+1 as solution', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - assert.doesNotMatch(query, /.*traceparent.*/); + it('should intercept pool.query(text: options, values: [], callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + pool.query({ sql }, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); done(); }); }); }); - }); - it('should not add comment when specified if existing block comment', done => { - instrumentation.setConfig({ - addSqlCommenterCommentToQueries: true, - } as any); - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - pool.query('SELECT 1+1 as solution /*block comment*/', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - assert.doesNotMatch(query, /.*traceparent.*/); + it('should intercept pool.query(text: string, values: [], callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + pool.query(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); done(); }); }); }); - }); - it('should not add comment when specified if existing line comment', done => { - instrumentation.setConfig({ - addSqlCommenterCommentToQueries: true, - } as any); - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - pool.query('SELECT 1+1 as solution -- line comment', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - assert.doesNotMatch(query, /.*traceparent.*/); + it('should intercept pool.query(text: string, value: any, callback)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + pool.query(sql, 1, (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); done(); }); }); }); - }); - it('should add comment when specified if no existing comment', done => { - instrumentation.setConfig({ - addSqlCommenterCommentToQueries: true, - } as any); - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - pool.query('SELECT 1+1 as solution', () => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - getLastQueries(1).then(([query]) => { - assert.match(query, /.*traceparent.*/); + it('should attach error messages to spans', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + pool.query(sql, (err, res) => { + assert.ok(err); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, undefined, err!.message); done(); }); }); }); - }); - }); - describe('#Pool.execute', () => { - it('should intercept pool.execute(text: string)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.execute(sql, (err, row: mysqlTypes.RowDataPacket[]) => { - assert(!err); - assert.strictEqual(row[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + it('should not add comment by default', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + pool.query('SELECT 1+1 as solution', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + getLastQueries(1).then(([query]) => { + assert.doesNotMatch(query, /.*traceparent.*/); + done(); + }); + }); }); }); - }); - it('should intercept pool.getConnection().execute(text: string)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.getConnection((err, conn) => { - const query = conn.execute(sql); - let rows = 0; - - query.on('result', (row: mysqlTypes.RowDataPacket) => { - assert.strictEqual(row.solution, 2); - rows += 1; - }); - - query.on('end', () => { - assert.strictEqual(rows, 1); + it('should not add comment when specified if existing block comment', done => { + instrumentation.setConfig({ + addSqlCommenterCommentToQueries: true, + } as any); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + pool.query('SELECT 1+1 as solution /*block comment*/', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + getLastQueries(1).then(([query]) => { + assert.doesNotMatch(query, /.*traceparent.*/); + done(); + }); }); }); }); - }); - it('should intercept pool.execute(text: string, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + it('should not add comment when specified if existing line comment', done => { + instrumentation.setConfig({ + addSqlCommenterCommentToQueries: true, + } as any); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + pool.query('SELECT 1+1 as solution -- line comment', () => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + getLastQueries(1).then(([query]) => { + assert.doesNotMatch(query, /.*traceparent.*/); + done(); + }); + }); }); }); - }); - it('should intercept pool.getConnection().execute(text: string, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.getConnection((err, conn) => { - conn.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); + it('should add comment when specified if no existing comment', done => { + instrumentation.setConfig({ + addSqlCommenterCommentToQueries: true, + } as any); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + pool.query('SELECT 1+1 as solution', () => { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + getLastQueries(1).then(([query]) => { + assert.match(query, /.*traceparent.*/); + done(); + }); }); }); }); }); - it('should intercept pool.execute(text: options, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - pool.execute( - { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); + describe('#Pool.execute', () => { + it('should intercept pool.execute(text: string)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + pool.execute(sql, (err, row: mysqlTypes.RowDataPacket[]) => { + assert(!err); + assert.strictEqual(row[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql); done(); - } - ); - }); - }); - - it('should intercept pool.execute(text: options, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - pool.execute({ sql }, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); + }); }); }); - }); - it('should intercept pool.execute(text: string, values: [], callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - pool.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - }); - }); - }); + it('should intercept pool.getConnection().execute(text: string)', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + pool.getConnection((err, conn) => { + const query = conn.execute(sql); + let rows = 0; - it('should intercept pool.execute(text: string, value: any, callback)', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+? as solution'; - pool.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - }); - }); - }); + query.on('result', (row: mysqlTypes.RowDataPacket) => { + assert.strictEqual(row.solution, 2); + rows += 1; + }); - it('should attach error messages to spans', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - pool.execute(sql, (err, res) => { - assert.ok(err); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, undefined, err!.message); - done(); + query.on('end', () => { + assert.strictEqual(rows, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); + }); }); }); - }); - }); - describe('#PoolCluster', () => { - it('should intercept poolClusterConnection.query(text: string)', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); + it('should intercept pool.execute(text: string, callback)', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - const query = poolClusterConnection.query(sql); - let rows = 0; - - query.on('result', (row: mysqlTypes.RowDataPacket) => { - assert.strictEqual(row.solution, 2); - rows += 1; - }); - - query.on('end', () => { - assert.strictEqual(rows, 1); + pool.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql); @@ -940,17 +835,13 @@ describe('mysql2', () => { }); }); }); - }); - it('should intercept poolClusterConnection.query(text: string, callback)', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); + it('should intercept pool.getConnection().execute(text: string, callback)', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - poolClusterConnection.query( - sql, - (err, res: mysqlTypes.RowDataPacket[]) => { + pool.getConnection((err, conn) => { + conn.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -958,19 +849,16 @@ describe('mysql2', () => { assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql); done(); - } - ); + }); + }); }); }); - }); - it('should intercept poolClusterConnection.query(text: options, callback)', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); + it('should intercept pool.execute(text: options, callback)', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - poolClusterConnection.query( + pool.execute( { sql, values: [1] }, (err, res: mysqlTypes.RowDataPacket[]) => { assert.ifError(err); @@ -978,202 +866,313 @@ describe('mysql2', () => { assert.strictEqual(res[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); + assertSpan(spans[0], sql); done(); } ); }); }); - }); - it('should intercept poolClusterConnection.query(text: options, values: [], callback)', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); + it('should intercept pool.execute(text: options, values: [], callback)', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - poolClusterConnection.query( - { sql }, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); - }); - }); - }); - - it('should intercept poolClusterConnection.query(text: string, values: [], callback)', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - poolClusterConnection.query( - sql, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + pool.execute({ sql }, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); - }); - it('should intercept poolClusterConnection.query(text: string, value: any, callback)', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); + it('should intercept pool.execute(text: string, values: [], callback)', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - poolClusterConnection.query( - sql, - 1, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + const sql = 'SELECT 1+? as solution'; + pool.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); - }); - it('should attach error messages to spans', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); + it('should intercept pool.execute(text: string, value: any, callback)', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT ? as solution'; - poolClusterConnection.query(sql, (err, res) => { - assert.ok(err); + const sql = 'SELECT 1+? as solution'; + pool.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, undefined, err!.message); + assertSpan(spans[0], sql, [1]); done(); }); }); }); - }); - it('should get connection by name', done => { - poolCluster.getConnection('name', (err, poolClusterConnection) => { - assert.ifError(err); + it('should attach error messages to spans', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1 as solution'; - poolClusterConnection.query(sql, (err, res) => { - assert.ifError(err); + const sql = 'SELECT ? as solution'; + pool.execute(sql, (err, res) => { + assert.ok(err); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); + assertSpan(spans[0], sql, undefined, err!.message); done(); }); }); }); }); - it('should get connection by name and selector', done => { - poolCluster.getConnection( - 'name', - 'ORDER', - (err, poolClusterConnection) => { + describe('#PoolCluster', () => { + it('should intercept poolClusterConnection.query(text: string)', done => { + poolCluster.getConnection((err, poolClusterConnection) => { assert.ifError(err); - const sql = 'SELECT 1 as solution'; - poolClusterConnection.query(sql, (err, res) => { - assert.ifError(err); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + const query = poolClusterConnection.query(sql); + let rows = 0; + + query.on('result', (row: mysqlTypes.RowDataPacket) => { + assert.strictEqual(row.solution, 2); + rows += 1; + }); + + query.on('end', () => { + assert.strictEqual(rows, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); }); - } - ); - }); - }); + }); + }); - describe('#responseHook', () => { - const queryResultAttribute = 'query_result'; + it('should intercept poolClusterConnection.query(text: string, callback)', done => { + poolCluster.getConnection((err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + poolClusterConnection.query( + sql, + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + } + ); + }); + }); + }); - describe('invalid response hook', () => { - beforeEach(() => { - const config: MySQL2InstrumentationConfig = { - responseHook: (span, responseHookInfo) => { - throw new Error('random failure!'); - }, - }; - instrumentation.setConfig(config); + it('should intercept poolClusterConnection.query(text: options, callback)', done => { + poolCluster.getConnection((err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + poolClusterConnection.query( + { sql, values: [1] }, + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); + }); + }); }); - it('should not affect the behavior of the query', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - done(); + it('should intercept poolClusterConnection.query(text: options, values: [], callback)', done => { + poolCluster.getConnection((err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+? as solution'; + poolClusterConnection.query( + { sql }, + [1], + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } + ); }); }); }); - }); - describe('valid response hook', () => { - beforeEach(() => { - const config: MySQL2InstrumentationConfig = { - responseHook: (span, responseHookInfo) => { - span.setAttribute( - queryResultAttribute, - JSON.stringify(responseHookInfo.queryResults) + it('should intercept poolClusterConnection.query(text: string, values: [], callback)', done => { + poolCluster.getConnection((err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + poolClusterConnection.query( + sql, + [1], + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } ); - }, - }; - instrumentation.setConfig(config); + }); + }); }); - it('should extract data from responseHook - connection', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - assert.strictEqual( - spans[0].attributes[queryResultAttribute], - JSON.stringify(res) + it('should intercept poolClusterConnection.query(text: string, value: any, callback)', done => { + poolCluster.getConnection((err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + poolClusterConnection.query( + sql, + 1, + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + } ); - done(); }); }); }); - it('should extract data from responseHook - pool', done => { - const span = provider.getTracer('default').startSpan('test span'); - context.with(trace.setSpan(context.active(), span), () => { - const sql = 'SELECT 1+1 as solution'; - pool.getConnection((err, conn) => { - conn.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + it('should attach error messages to spans', done => { + poolCluster.getConnection((err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT ? as solution'; + poolClusterConnection.query(sql, (err, res) => { + assert.ok(err); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, undefined, err!.message); + done(); + }); + }); + }); + }); + + it('should get connection by name', done => { + poolCluster.getConnection('name', (err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1 as solution'; + poolClusterConnection.query(sql, (err, res) => { + assert.ifError(err); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); + }); + }); + }); + + it('should get connection by name and selector', done => { + poolCluster.getConnection( + 'name', + 'ORDER', + (err, poolClusterConnection) => { + assert.ifError(err); + const sql = 'SELECT 1 as solution'; + poolClusterConnection.query(sql, (err, res) => { + assert.ifError(err); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); + } + ); + }); + }); + + describe('#responseHook', () => { + const queryResultAttribute = 'query_result'; + + describe('invalid response hook', () => { + beforeEach(() => { + const config: MySQL2InstrumentationConfig = { + responseHook: (span, responseHookInfo) => { + throw new Error('random failure!'); + }, + }; + instrumentation.setConfig(config); + }); + + it('should not affect the behavior of the query', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + done(); + }); + }); + }); + }); + + describe('valid response hook', () => { + beforeEach(() => { + const config: MySQL2InstrumentationConfig = { + responseHook: (span, responseHookInfo) => { + span.setAttribute( + queryResultAttribute, + JSON.stringify(responseHookInfo.queryResults) + ); + }, + }; + instrumentation.setConfig(config); + }); + + it('should extract data from responseHook - connection', done => { + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1188,17 +1187,13 @@ describe('mysql2', () => { }); }); }); - }); - it('should extract data from responseHook - poolCluster', done => { - poolCluster.getConnection((err, poolClusterConnection) => { - assert.ifError(err); + it('should extract data from responseHook - pool', done => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - poolClusterConnection.query( - sql, - (err, res: mysqlTypes.RowDataPacket[]) => { + pool.getConnection((err, conn) => { + conn.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1210,13 +1205,160 @@ describe('mysql2', () => { JSON.stringify(res) ); done(); - } - ); + }); + }); + }); + }); + + it('should extract data from responseHook - poolCluster', done => { + poolCluster.getConnection((err, poolClusterConnection) => { + assert.ifError(err); + const span = provider.getTracer('default').startSpan('test span'); + context.with(trace.setSpan(context.active(), span), () => { + const sql = 'SELECT 1+1 as solution'; + poolClusterConnection.query( + sql, + (err, res: mysqlTypes.RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + assert.strictEqual( + spans[0].attributes[queryResultAttribute], + JSON.stringify(res) + ); + done(); + } + ); + }); }); }); }); }); }); + describe('promise API', () => { + let instrumentation: MySQL2Instrumentation; + + let contextManager: AsyncHooksContextManager; + const provider = new BasicTracerProvider(); + const memoryExporter = new InMemorySpanExporter(); + + let connection: mysqlTypesProm.Connection; + let rootConnection: mysqlTypesProm.Connection; + let mysqlTypesPromReload: typeof mysqlTypesProm; + + before(async function () { + // cleanup cache for mysql2 + delete require.cache[require.resolve('../src')]; + Object.keys(require.cache).forEach(key => { + if (key.includes('mysql2/')) { + delete require.cache[key]; + } + }); + + const { MySQL2Instrumentation } = await import('../src'); + instrumentation = new MySQL2Instrumentation(); + instrumentation.enable(); + instrumentation.disable(); + + mysqlTypesPromReload = await import('mysql2/promise'); + + if (!shouldTest) { + // this.skip() workaround + // https://github.com/mochajs/mocha/issues/2683#issuecomment-375629901 + this.test!.parent!.pending = true; + this.skip(); + } + provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + rootConnection = await mysqlTypesPromReload.createConnection({ + port, + user: 'root', + host, + password: rootPassword, + database, + }); + }); + + after(async function () { + await rootConnection.end(); + }); + + beforeEach(async () => { + instrumentation.disable(); + contextManager = new AsyncHooksContextManager().enable(); + context.setGlobalContextManager(contextManager); + instrumentation.setTracerProvider(provider); + instrumentation.enable(); + connection = await mysqlTypesPromReload.createConnection({ + port, + user, + host, + password, + database, + }); + }); + + afterEach(async () => { + context.disable(); + memoryExporter.reset(); + instrumentation.setConfig({}); + instrumentation.disable(); + await connection.end(); + }); + + it('should attach error messages to spans', async () => { + const span = provider.getTracer('default').startSpan('test span'); + await context.with(trace.setSpan(context.active(), span), async () => { + const sql = 'SELECT ? as solution'; + let err: Error; + await assert.rejects(async () => { + try { + await connection.execute(sql); + } catch (e) { + err = e instanceof Error ? e : new Error(e as string); + throw e; + } + }); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, undefined, err!.message); + }); + }); + + describe('#Connection.query', () => { + it('should intercept connection.query(text: string)', async () => { + const span = provider.getTracer('default').startSpan('test span'); + await context.with(trace.setSpan(context.active(), span), async () => { + const sql = 'SELECT 1+1 as solution'; + const result = await connection.query(sql); + const rows = result[0]; + assert.strictEqual(rows.length, 1); + assert.strictEqual(rows[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + }); + }); + }); + + describe('#Connection.execute', () => { + it('should intercept connection.execute(text: string, phs: [])', async () => { + const span = provider.getTracer('default').startSpan('test span'); + await context.with(trace.setSpan(context.active(), span), async () => { + const sql = 'SELECT 1+? as solution'; + const result = await connection.execute(sql, [1]); + const rows = result[0]; + assert.strictEqual(rows.length, 1); + assert.strictEqual(rows[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + }); + }); + }); + }); }); function assertSpan( From b9093ae3cfef4f8a656c4d5e11956409715b8479 Mon Sep 17 00:00:00 2001 From: Michele Azzolari Date: Thu, 16 Jan 2025 17:27:27 +0100 Subject: [PATCH 2/4] fix(instrumentation-mysql2): patch Connection class when imported (#2590) --- .../src/instrumentation.ts | 91 +++++++++++++------ .../src/utils.ts | 13 +-- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mysql2/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-mysql2/src/instrumentation.ts index 8c90080980..d22db9a020 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql2/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-mysql2/src/instrumentation.ts @@ -18,6 +18,7 @@ import * as api from '@opentelemetry/api'; import { InstrumentationBase, InstrumentationNodeModuleDefinition, + InstrumentationNodeModuleFile, isWrapped, safeExecuteInTheMiddle, } from '@opentelemetry/instrumentation'; @@ -41,6 +42,8 @@ import { PACKAGE_NAME, PACKAGE_VERSION } from './version'; type formatType = typeof mysqlTypes.format; +const supportedVersions = ['>=1.4.2 <4']; + export class MySQL2Instrumentation extends InstrumentationBase { static readonly COMMON_ATTRIBUTES = { [SEMATTRS_DB_SYSTEM]: DBSYSTEMVALUES_MYSQL, @@ -51,45 +54,75 @@ export class MySQL2Instrumentation extends InstrumentationBase { + if (isWrapped(ConnectionPrototype.query)) { + this._unwrap(ConnectionPrototype, 'query'); + } + this._wrap( + ConnectionPrototype, + 'query', + this._patchQuery(format, false) as any + ); + if (isWrapped(ConnectionPrototype.execute)) { + this._unwrap(ConnectionPrototype, 'execute'); + } + this._wrap( + ConnectionPrototype, + 'execute', + this._patchQuery(format, true) as any + ); + }; + const unpatch = (ConnectionPrototype: mysqlTypes.Connection) => { + this._unwrap(ConnectionPrototype, 'query'); + this._unwrap(ConnectionPrototype, 'execute'); + }; return [ new InstrumentationNodeModuleDefinition( 'mysql2', - ['>=1.4.2 <4'], + supportedVersions, (moduleExports: any) => { - const ConnectionPrototype: mysqlTypes.Connection = - getConnectionPrototypeToInstrument(moduleExports.Connection); - if (isWrapped(ConnectionPrototype.query)) { - this._unwrap(ConnectionPrototype, 'query'); - } - this._wrap( - ConnectionPrototype, - 'query', - this._patchQuery(moduleExports.format, false) as any - ); - - if (isWrapped(ConnectionPrototype.execute)) { - this._unwrap(ConnectionPrototype, 'execute'); - } - this._wrap( - ConnectionPrototype, - 'execute', - this._patchQuery(moduleExports.format, true) as any - ); - + setFormatFunction(moduleExports); return moduleExports; }, - (moduleExports: any) => { - if (moduleExports === undefined) return; - const ConnectionPrototype: mysqlTypes.Connection = - moduleExports.Connection.prototype; - this._unwrap(ConnectionPrototype, 'query'); - this._unwrap(ConnectionPrototype, 'execute'); - } + () => {}, + [ + new InstrumentationNodeModuleFile( + 'mysql2/promise.js', + supportedVersions, + (moduleExports: any) => { + setFormatFunction(moduleExports); + return moduleExports; + }, + () => {} + ), + new InstrumentationNodeModuleFile( + 'mysql2/lib/connection.js', + supportedVersions, + (moduleExports: any) => { + const ConnectionPrototype: mysqlTypes.Connection = + getConnectionPrototypeToInstrument(moduleExports); + patch(ConnectionPrototype); + return moduleExports; + }, + (moduleExports: any) => { + if (moduleExports === undefined) return; + const ConnectionPrototype: mysqlTypes.Connection = + getConnectionPrototypeToInstrument(moduleExports); + unpatch(ConnectionPrototype); + } + ), + ] ), ]; } - private _patchQuery(format: formatType, isPrepared: boolean) { + private _patchQuery(format: formatType | undefined, isPrepared: boolean) { return (originalQuery: Function): Function => { const thisPlugin = this; return function query( diff --git a/plugins/node/opentelemetry-instrumentation-mysql2/src/utils.ts b/plugins/node/opentelemetry-instrumentation-mysql2/src/utils.ts index bb0fb763d3..9e495a7d2c 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql2/src/utils.ts +++ b/plugins/node/opentelemetry-instrumentation-mysql2/src/utils.ts @@ -22,6 +22,9 @@ import { SEMATTRS_NET_PEER_NAME, SEMATTRS_NET_PEER_PORT, } from '@opentelemetry/semantic-conventions'; +import type * as mysqlTypes from 'mysql2'; + +type formatType = typeof mysqlTypes.format; /* Following types declare an expectation on mysql2 types and define a subset we @@ -103,14 +106,12 @@ function getJDBCString( */ export function getDbStatement( query: string | Query | QueryOptions, - format: ( - sql: string, - values: any[], - stringifyObjects?: boolean, - timeZone?: string - ) => string, + format?: formatType, values?: any[] ): string { + if (!format) { + return typeof query === 'string' ? query : query.sql; + } if (typeof query === 'string') { return values ? format(query, values) : query; } else { From 1f82b74e3e00e34b116024b5ad13d12748806ade Mon Sep 17 00:00:00 2001 From: Michele Azzolari Date: Mon, 20 Jan 2025 16:37:07 +0100 Subject: [PATCH 3/4] Update plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts Co-authored-by: Marc Pichler --- .../test/mysql.test.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts index f6b748bf0c..baa8c6ae5f 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts @@ -1242,15 +1242,19 @@ describe('mysql2', () => { let instrumentation: MySQL2Instrumentation; let contextManager: AsyncHooksContextManager; - const provider = new BasicTracerProvider(); const memoryExporter = new InMemorySpanExporter(); - + const provider = new BasicTracerProvider({ + spanProcessors: [new SimpleSpanProcessor(memoryExporter)], + }); let connection: mysqlTypesProm.Connection; let rootConnection: mysqlTypesProm.Connection; let mysqlTypesPromReload: typeof mysqlTypesProm; before(async function () { - // cleanup cache for mysql2 + // cleanup cache for 'mysql2' + // in previous iterations these tests would have passed since 'mysql2' was already loaded, + // but 'mysql2/promise' does not import 'mysql2'. Therefore, if used without ever loading 'mysql2', + // the relevant code would never get patched. delete require.cache[require.resolve('../src')]; Object.keys(require.cache).forEach(key => { if (key.includes('mysql2/')) { @@ -1271,7 +1275,6 @@ describe('mysql2', () => { this.test!.parent!.pending = true; this.skip(); } - provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); rootConnection = await mysqlTypesPromReload.createConnection({ port, user: 'root', From 56bd9dd2051b1e6c0d5236b4966b6d709ec567a1 Mon Sep 17 00:00:00 2001 From: Michele Azzolari Date: Tue, 21 Jan 2025 13:34:03 +0100 Subject: [PATCH 4/4] test(instrumentation-mysql2): import types and objects separately to improve readability Update plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts --- .../test/mysql.test.ts | 307 ++++++++---------- 1 file changed, 142 insertions(+), 165 deletions(-) diff --git a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts index baa8c6ae5f..60fe5a9c66 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts @@ -48,10 +48,19 @@ const instrumentation = new MySQL2Instrumentation(); instrumentation.enable(); instrumentation.disable(); -import * as mysqlTypes from 'mysql2'; -import * as mysqlTypesProm from 'mysql2/promise'; - -interface Result extends mysqlTypes.RowDataPacket { +import type { Connection, Pool, PoolCluster, RowDataPacket } from 'mysql2'; +import { + createConnection, + createPool, + createPoolCluster, + format, +} from 'mysql2'; +import type { + Connection as ConnectionAsync, + createConnection as createConnectionAsync, +} from 'mysql2/promise'; + +interface Result extends RowDataPacket { solution: number; } @@ -84,10 +93,10 @@ describe('mysql2', () => { const provider = new BasicTracerProvider(); const memoryExporter = new InMemorySpanExporter(); - let connection: mysqlTypes.Connection; - let rootConnection: mysqlTypes.Connection; - let pool: mysqlTypes.Pool; - let poolCluster: mysqlTypes.PoolCluster; + let connection: Connection; + let rootConnection: Connection; + let pool: Pool; + let poolCluster: PoolCluster; const getLastQueries = (count: number) => new Promise(res => { @@ -115,7 +124,7 @@ describe('mysql2', () => { this.skip(); } provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); - rootConnection = mysqlTypes.createConnection({ + rootConnection = createConnection({ port, user: 'root', host, @@ -137,21 +146,21 @@ describe('mysql2', () => { context.setGlobalContextManager(contextManager); instrumentation.setTracerProvider(provider); instrumentation.enable(); - connection = mysqlTypes.createConnection({ + connection = createConnection({ port, user, host, password, database, }); - pool = mysqlTypes.createPool({ + pool = createPool({ port, user, host, password, database, }); - poolCluster = mysqlTypes.createPoolCluster(); + poolCluster = createPoolCluster(); // the implementation actually accepts ConnectionConfig as well, // but the types do not reflect that poolCluster.add('name', { @@ -229,7 +238,7 @@ describe('mysql2', () => { const query = connection.query(sql); let rows = 0; - query.on('result', (row: mysqlTypes.RowDataPacket) => { + query.on('result', (row: RowDataPacket) => { assert.strictEqual(row.solution, 2); rows += 1; }); @@ -252,7 +261,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + connection.query(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -270,7 +279,7 @@ describe('mysql2', () => { const sql = 'SELECT 1+? as solution'; connection.query( { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { + (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -287,19 +296,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - connection.query( - { sql }, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + connection.query({ sql }, [1], (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); @@ -307,7 +312,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT ? as solution'; - connection.query(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + connection.query(sql, [1], (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 1); @@ -323,7 +328,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT ? as solution'; - connection.query(sql, 1, (err, res: mysqlTypes.RowDataPacket[]) => { + connection.query(sql, 1, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 1); @@ -427,7 +432,7 @@ describe('mysql2', () => { const query = connection.execute(sql); let rows = 0; - query.on('result', (row: mysqlTypes.RowDataPacket) => { + query.on('result', (row: RowDataPacket) => { assert.strictEqual(row.solution, 2); rows += 1; }); @@ -446,7 +451,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - connection.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + connection.execute(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -464,7 +469,7 @@ describe('mysql2', () => { const sql = 'SELECT 1+? as solution'; connection.execute( { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { + (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -481,19 +486,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - connection.execute( - { sql }, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + connection.execute({ sql }, [1], (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); @@ -501,19 +502,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - connection.execute( - sql, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + connection.execute(sql, [1], (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); @@ -521,19 +518,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - connection.execute( - sql, - [1], - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + connection.execute(sql, [1], (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); @@ -560,7 +553,7 @@ describe('mysql2', () => { const query = pool.query(sql); let rows = 0; - query.on('result', (row: mysqlTypes.RowDataPacket) => { + query.on('result', (row: RowDataPacket) => { assert.strictEqual(row.solution, 2); rows += 1; }); @@ -583,7 +576,7 @@ describe('mysql2', () => { const query = conn.query(sql); let rows = 0; - query.on('result', (row: mysqlTypes.RowDataPacket) => { + query.on('result', (row: RowDataPacket) => { assert.strictEqual(row.solution, 2); rows += 1; }); @@ -603,7 +596,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - pool.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + pool.query(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -620,7 +613,7 @@ describe('mysql2', () => { context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; pool.getConnection((err, conn) => { - conn.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + conn.query(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -637,18 +630,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - pool.query( - { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + pool.query({ sql, values: [1] }, (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); @@ -656,7 +646,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - pool.query({ sql }, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + pool.query({ sql }, [1], (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -672,7 +662,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT ? as solution'; - pool.query(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + pool.query(sql, [1], (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 1); @@ -688,7 +678,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT ? as solution'; - pool.query(sql, 1, (err, res: mysqlTypes.RowDataPacket[]) => { + pool.query(sql, 1, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 1); @@ -785,7 +775,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - pool.execute(sql, (err, row: mysqlTypes.RowDataPacket[]) => { + pool.execute(sql, (err, row: RowDataPacket[]) => { assert(!err); assert.strictEqual(row[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); @@ -804,7 +794,7 @@ describe('mysql2', () => { const query = conn.execute(sql); let rows = 0; - query.on('result', (row: mysqlTypes.RowDataPacket) => { + query.on('result', (row: RowDataPacket) => { assert.strictEqual(row.solution, 2); rows += 1; }); @@ -824,7 +814,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - pool.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + pool.execute(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -841,7 +831,7 @@ describe('mysql2', () => { context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; pool.getConnection((err, conn) => { - conn.execute(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + conn.execute(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -858,18 +848,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - pool.execute( - { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); - } - ); + pool.execute({ sql, values: [1] }, (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); }); }); @@ -877,7 +864,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - pool.execute({ sql }, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + pool.execute({ sql }, [1], (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -893,7 +880,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - pool.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + pool.execute(sql, [1], (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -909,7 +896,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+? as solution'; - pool.execute(sql, [1], (err, res: mysqlTypes.RowDataPacket[]) => { + pool.execute(sql, [1], (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -946,7 +933,7 @@ describe('mysql2', () => { const query = poolClusterConnection.query(sql); let rows = 0; - query.on('result', (row: mysqlTypes.RowDataPacket) => { + query.on('result', (row: RowDataPacket) => { assert.strictEqual(row.solution, 2); rows += 1; }); @@ -968,18 +955,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - poolClusterConnection.query( - sql, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); - } - ); + poolClusterConnection.query(sql, (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + done(); + }); }); }); }); @@ -992,7 +976,7 @@ describe('mysql2', () => { const sql = 'SELECT 1+? as solution'; poolClusterConnection.query( { sql, values: [1] }, - (err, res: mysqlTypes.RowDataPacket[]) => { + (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1015,7 +999,7 @@ describe('mysql2', () => { poolClusterConnection.query( { sql }, [1], - (err, res: mysqlTypes.RowDataPacket[]) => { + (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1038,7 +1022,7 @@ describe('mysql2', () => { poolClusterConnection.query( sql, [1], - (err, res: mysqlTypes.RowDataPacket[]) => { + (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 1); @@ -1058,19 +1042,15 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT ? as solution'; - poolClusterConnection.query( - sql, - 1, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql, [1]); - done(); - } - ); + poolClusterConnection.query(sql, 1, (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 1); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql, [1]); + done(); + }); }); }); }); @@ -1145,7 +1125,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + connection.query(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1172,7 +1152,7 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - connection.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + connection.query(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1193,7 +1173,7 @@ describe('mysql2', () => { context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; pool.getConnection((err, conn) => { - conn.query(sql, (err, res: mysqlTypes.RowDataPacket[]) => { + conn.query(sql, (err, res: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1216,22 +1196,19 @@ describe('mysql2', () => { const span = provider.getTracer('default').startSpan('test span'); context.with(trace.setSpan(context.active(), span), () => { const sql = 'SELECT 1+1 as solution'; - poolClusterConnection.query( - sql, - (err, res: mysqlTypes.RowDataPacket[]) => { - assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - assert.strictEqual( - spans[0].attributes[queryResultAttribute], - JSON.stringify(res) - ); - done(); - } - ); + poolClusterConnection.query(sql, (err, res: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assertSpan(spans[0], sql); + assert.strictEqual( + spans[0].attributes[queryResultAttribute], + JSON.stringify(res) + ); + done(); + }); }); }); }); @@ -1246,9 +1223,9 @@ describe('mysql2', () => { const provider = new BasicTracerProvider({ spanProcessors: [new SimpleSpanProcessor(memoryExporter)], }); - let connection: mysqlTypesProm.Connection; - let rootConnection: mysqlTypesProm.Connection; - let mysqlTypesPromReload: typeof mysqlTypesProm; + let connection: ConnectionAsync; + let rootConnection: ConnectionAsync; + let createConnection: typeof createConnectionAsync; before(async function () { // cleanup cache for 'mysql2' @@ -1267,7 +1244,7 @@ describe('mysql2', () => { instrumentation.enable(); instrumentation.disable(); - mysqlTypesPromReload = await import('mysql2/promise'); + createConnection = (await import('mysql2/promise')).createConnection; if (!shouldTest) { // this.skip() workaround @@ -1275,7 +1252,7 @@ describe('mysql2', () => { this.test!.parent!.pending = true; this.skip(); } - rootConnection = await mysqlTypesPromReload.createConnection({ + rootConnection = await createConnection({ port, user: 'root', host, @@ -1294,7 +1271,7 @@ describe('mysql2', () => { context.setGlobalContextManager(contextManager); instrumentation.setTracerProvider(provider); instrumentation.enable(); - connection = await mysqlTypesPromReload.createConnection({ + connection = await createConnection({ port, user, host, @@ -1377,7 +1354,7 @@ function assertSpan( assert.strictEqual(span.attributes[SEMATTRS_DB_USER], user); assert.strictEqual( span.attributes[SEMATTRS_DB_STATEMENT], - mysqlTypes.format(sql, values) + format(sql, values) ); if (errorMessage) { assert.strictEqual(span.status.message, errorMessage);