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 { diff --git a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts index ef14d7d982..60fe5a9c66 100644 --- a/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts +++ b/plugins/node/opentelemetry-instrumentation-mysql2/test/mysql.test.ts @@ -48,57 +48,28 @@ const instrumentation = new MySQL2Instrumentation(); instrumentation.enable(); instrumentation.disable(); -import * as mysqlTypes from 'mysql2'; - -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; } 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,155 +81,222 @@ 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: Connection; + let rootConnection: Connection; + let pool: Pool; + let poolCluster: 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 = 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 = createConnection({ + port, + user, + host, + password, + database, + }); + pool = createPool({ + port, + user, + host, + password, + database, + }); + poolCluster = 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: 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: 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: 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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -266,213 +304,189 @@ describe('mysql2', () => { 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, 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: 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 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 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: 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 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 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 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 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 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 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(); + 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(); + }); }); }); }); - }); - 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 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(); + }); }); }); }); }); - }); - 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; - }); + 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('end', () => { - assert.strictEqual(rows, 1); - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 1); - assertSpan(spans[0], sql); - done(); - }); - }); - }); + query.on('result', (row: RowDataPacket) => { + assert.strictEqual(row.solution, 2); + rows += 1; + }); - 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(); + 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: 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[]) => { + 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: 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 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[]) => { + 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: 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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -480,90 +494,66 @@ describe('mysql2', () => { 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: 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: 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: 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) => { + query.on('result', (row: RowDataPacket) => { assert.strictEqual(row.solution, 2); rows += 1; }); @@ -577,30 +567,36 @@ 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; + + query.on('result', (row: 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.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[]) => { + 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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -611,15 +607,30 @@ describe('mysql2', () => { }); }); }); - }); - 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.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: 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.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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -627,170 +638,146 @@ describe('mysql2', () => { assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql, [1]); 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: 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: 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, 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.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: 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'; - 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: 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: 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), () => { - 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 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 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.*/); - 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 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 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.*/); + 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.*/); - 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(); + }); }); }); }); - }); - }); - 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 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.*/); + 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); + 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: RowDataPacket[]) => { + assert(!err); + assert.strictEqual(row[0].solution, 2); const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); assertSpan(spans[0], sql); @@ -798,30 +785,36 @@ describe('mysql2', () => { }); }); }); - }); - 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 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: 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.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[]) => { + 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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -832,15 +825,30 @@ describe('mysql2', () => { }); }); }); - }); - 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[]) => { + 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: 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.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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -848,200 +856,193 @@ describe('mysql2', () => { 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.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: 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, 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(); + 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: 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'; - 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(); + 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: 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('#PoolCluster', () => { - it('should intercept poolClusterConnection.query(text: string)', done => { - poolCluster.getConnection((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+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 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 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); + describe('#PoolCluster', () => { + it('should intercept poolClusterConnection.query(text: string)', 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'; + const query = poolClusterConnection.query(sql); + let rows = 0; + + query.on('result', (row: 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 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[]) => { + 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: 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 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(); - } - ); + 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: 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(); - } - ); + 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: 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); - 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[]) => { + 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: 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 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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 1); @@ -1049,131 +1050,109 @@ describe('mysql2', () => { 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); - 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 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 and selector', done => { - poolCluster.getConnection( - 'name', - 'ORDER', - (err, poolClusterConnection) => { + it('should get connection by name', done => { + poolCluster.getConnection('name', (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 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[]) => { + it('should get connection by name and selector', done => { + poolCluster.getConnection( + 'name', + 'ORDER', + (err, poolClusterConnection) => { assert.ifError(err); - assert.ok(res); - assert.strictEqual(res[0].solution, 2); - done(); - }); - }); + 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('valid response hook', () => { - beforeEach(() => { - const config: MySQL2InstrumentationConfig = { - responseHook: (span, responseHookInfo) => { - span.setAttribute( - queryResultAttribute, - JSON.stringify(responseHookInfo.queryResults) - ); - }, - }; - instrumentation.setConfig(config); - }); + 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 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) - ); - 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: RowDataPacket[]) => { + assert.ifError(err); + assert.ok(res); + assert.strictEqual(res[0].solution, 2); + 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[]) => { + 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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1188,17 +1167,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: RowDataPacket[]) => { assert.ifError(err); assert.ok(res); assert.strictEqual(res[0].solution, 2); @@ -1210,10 +1185,157 @@ 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: 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 memoryExporter = new InMemorySpanExporter(); + const provider = new BasicTracerProvider({ + spanProcessors: [new SimpleSpanProcessor(memoryExporter)], + }); + let connection: ConnectionAsync; + let rootConnection: ConnectionAsync; + let createConnection: typeof createConnectionAsync; + + before(async function () { + // 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/')) { + delete require.cache[key]; + } + }); + + const { MySQL2Instrumentation } = await import('../src'); + instrumentation = new MySQL2Instrumentation(); + instrumentation.enable(); + instrumentation.disable(); + + createConnection = (await import('mysql2/promise')).createConnection; + + if (!shouldTest) { + // this.skip() workaround + // https://github.com/mochajs/mocha/issues/2683#issuecomment-375629901 + this.test!.parent!.pending = true; + this.skip(); + } + rootConnection = await 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 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]); + }); }); }); }); @@ -1232,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);