diff --git a/dev-packages/node-integration-tests/suites/tracing-experimental/mongodb/scenario.js b/dev-packages/node-integration-tests/suites/tracing-experimental/mongodb/scenario.js index 74213908f8e0..360c943e0724 100644 --- a/dev-packages/node-integration-tests/suites/tracing-experimental/mongodb/scenario.js +++ b/dev-packages/node-integration-tests/suites/tracing-experimental/mongodb/scenario.js @@ -5,10 +5,12 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, - debug: true, transport: loggingTransport, }); +// Stop the process from exiting before the transaction is sent +setInterval(() => {}, 1000); + // Must be required after Sentry is initialized const { MongoClient } = require('mongodb'); @@ -40,8 +42,6 @@ async function run() { } }, ); - - Sentry.flush(2000); } // eslint-disable-next-line @typescript-eslint/no-floating-promises diff --git a/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withConnect.js b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withConnect.js new file mode 100644 index 000000000000..0d1b517209a0 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withConnect.js @@ -0,0 +1,40 @@ +const { loggingTransport } = require('@sentry-internal/node-integration-tests'); +const Sentry = require('@sentry/node-experimental'); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +// Stop the process from exiting before the transaction is sent +setInterval(() => {}, 1000); + +const mysql = require('mysql'); + +const connection = mysql.createConnection({ + user: 'root', + password: 'docker', +}); + +connection.connect(function (err) { + if (err) { + return; + } +}); + +Sentry.startSpanManual( + { + op: 'transaction', + name: 'Test Transaction', + }, + span => { + connection.query('SELECT 1 + 1 AS solution', function () { + connection.query('SELECT NOW()', ['1', '2'], () => { + span.end(); + connection.end(); + }); + }); + }, +); diff --git a/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withoutCallback.js b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withoutCallback.js new file mode 100644 index 000000000000..cd35953b0504 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withoutCallback.js @@ -0,0 +1,45 @@ +const { loggingTransport } = require('@sentry-internal/node-integration-tests'); +const Sentry = require('@sentry/node-experimental'); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +// Stop the process from exiting before the transaction is sent +setInterval(() => {}, 1000); + +const mysql = require('mysql'); + +const connection = mysql.createConnection({ + user: 'root', + password: 'docker', +}); + +connection.connect(function (err) { + if (err) { + return; + } +}); + +Sentry.startSpan( + { + op: 'transaction', + name: 'Test Transaction', + }, + span => { + const query = connection.query('SELECT 1 + 1 AS solution'); + const query2 = connection.query('SELECT NOW()', ['1', '2']); + + query.on('end', () => { + query2.on('end', () => { + // Wait a bit to ensure the queries completed + setTimeout(() => { + span.end(); + }, 500); + }); + }); + }, +); diff --git a/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withoutConnect.js b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withoutConnect.js new file mode 100644 index 000000000000..844b25d63f2d --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/scenario-withoutConnect.js @@ -0,0 +1,34 @@ +const { loggingTransport } = require('@sentry-internal/node-integration-tests'); +const Sentry = require('@sentry/node-experimental'); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +// Stop the process from exiting before the transaction is sent +setInterval(() => {}, 1000); + +const mysql = require('mysql'); + +const connection = mysql.createConnection({ + user: 'root', + password: 'docker', +}); + +Sentry.startSpanManual( + { + op: 'transaction', + name: 'Test Transaction', + }, + span => { + connection.query('SELECT 1 + 1 AS solution', function () { + connection.query('SELECT NOW()', ['1', '2'], () => { + span.end(); + connection.end(); + }); + }); + }, +); diff --git a/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/test.ts b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/test.ts new file mode 100644 index 000000000000..43c67c9c8b07 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing-experimental/mysql/test.ts @@ -0,0 +1,94 @@ +import { conditionalTest } from '../../../utils'; +import { createRunner } from '../../../utils/runner'; + +conditionalTest({ min: 14 })('mysql auto instrumentation', () => { + test('should auto-instrument `mysql` package when using connection.connect()', done => { + const EXPECTED_TRANSACTION = { + transaction: 'Test Transaction', + spans: expect.arrayContaining([ + expect.objectContaining({ + description: 'SELECT 1 + 1 AS solution', + op: 'db', + data: expect.objectContaining({ + 'db.system': 'mysql', + 'net.peer.name': 'localhost', + 'net.peer.port': 3306, + 'db.user': 'root', + }), + }), + expect.objectContaining({ + description: 'SELECT NOW()', + op: 'db', + data: expect.objectContaining({ + 'db.system': 'mysql', + 'net.peer.name': 'localhost', + 'net.peer.port': 3306, + 'db.user': 'root', + }), + }), + ]), + }; + + createRunner(__dirname, 'scenario-withConnect.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done); + }); + + test('should auto-instrument `mysql` package when using query without callback', done => { + const EXPECTED_TRANSACTION = { + transaction: 'Test Transaction', + spans: expect.arrayContaining([ + expect.objectContaining({ + description: 'SELECT 1 + 1 AS solution', + op: 'db', + data: expect.objectContaining({ + 'db.system': 'mysql', + 'net.peer.name': 'localhost', + 'net.peer.port': 3306, + 'db.user': 'root', + }), + }), + expect.objectContaining({ + description: 'SELECT NOW()', + op: 'db', + data: expect.objectContaining({ + 'db.system': 'mysql', + 'net.peer.name': 'localhost', + 'net.peer.port': 3306, + 'db.user': 'root', + }), + }), + ]), + }; + + createRunner(__dirname, 'scenario-withoutCallback.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done); + }); + + test('should auto-instrument `mysql` package without connection.connect()', done => { + const EXPECTED_TRANSACTION = { + transaction: 'Test Transaction', + spans: expect.arrayContaining([ + expect.objectContaining({ + description: 'SELECT 1 + 1 AS solution', + op: 'db', + data: expect.objectContaining({ + 'db.system': 'mysql', + 'net.peer.name': 'localhost', + 'net.peer.port': 3306, + 'db.user': 'root', + }), + }), + expect.objectContaining({ + description: 'SELECT NOW()', + op: 'db', + data: expect.objectContaining({ + 'db.system': 'mysql', + 'net.peer.name': 'localhost', + 'net.peer.port': 3306, + 'db.user': 'root', + }), + }), + ]), + }; + + createRunner(__dirname, 'scenario-withoutConnect.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done); + }); +});