Skip to content

Commit 45414f5

Browse files
feat: added support for mysql2 v3.11.5 (#1467)
ref INSTA-20850 Co-authored-by: Arya Mohanan <[email protected]>
1 parent e38a15a commit 45414f5

File tree

6 files changed

+115
-15
lines changed

6 files changed

+115
-15
lines changed

package-lock.json

Lines changed: 51 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@
195195
"mssql": "^11.0.1",
196196
"mssql-v10": "npm:mssql@^10.0.4",
197197
"mysql": "^2.18.1",
198-
"mysql2": "^3.11.4",
198+
"mysql2": "^3.11.5",
199+
"mysql2-v3114": "npm:[email protected]",
199200
"nan": "^2.22.0",
200201
"nats": "^2.28.2",
201202
"nats-v1": "npm:nats@^1.4.12",

packages/collector/test/tracing/database/mysql/app.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ process.on('SIGTERM', () => {
1414
});
1515

1616
const agentPort = process.env.INSTANA_AGENT_PORT;
17+
if (process.env.MYSQL2_VERSION) {
18+
require('./mockVersion');
19+
}
1720
const instana = require('../../../..')();
1821

1922
const accessFunction = process.env.USE_EXECUTE ? 'execute' : 'query';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* (c) Copyright IBM Corp. 2024
3+
*/
4+
5+
'use strict';
6+
7+
const mock = require('mock-require');
8+
const MYSQL2_VERSION = process.env.MYSQL2_VERSION;
9+
const MYSQL2_REQUIRE = process.env.MYSQL2_VERSION === 'latest' ? 'mysql2' : `mysql2-${MYSQL2_VERSION}`;
10+
11+
if (MYSQL2_REQUIRE !== 'mysql2') {
12+
mock('mysql2', MYSQL2_REQUIRE);
13+
}

packages/collector/test/tracing/database/mysql/test.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,39 @@ mochaSuiteFn('tracing/mysql', function () {
2323
globalAgent.setUpCleanUpHooks();
2424
const agentControls = globalAgent.instance;
2525

26-
['mysql', 'mysql-cluster', 'mysql2', 'mysql2/promises'].forEach(driverMode => {
27-
[false, true].forEach(function (useExecute) {
28-
// connection.query or connection.execute
29-
registerSuite.bind(this)(agentControls, driverMode, useExecute);
30-
});
26+
const drivers = ['mysql', 'mysql-cluster', 'mysql2', 'mysql2/promises'];
27+
const mysql2Versions = ['latest', 'v3114'];
28+
const executionModes = [false, true];
29+
30+
drivers.forEach(driverMode => {
31+
if (driverMode === 'mysql2') {
32+
// Handling for 'mysql2' with different versions
33+
mysql2Versions.forEach(version => {
34+
executionModes.forEach(useExecute => {
35+
registerSuite.call(this, agentControls, driverMode, useExecute, version);
36+
});
37+
});
38+
} else {
39+
// Generic handling for other drivers
40+
executionModes.forEach(useExecute => {
41+
registerSuite.call(this, agentControls, driverMode, useExecute);
42+
});
43+
}
3144
});
3245
});
3346

34-
function registerSuite(agentControls, driverMode, useExecute) {
47+
function registerSuite(agentControls, driverMode, useExecute, mysql2Version) {
3548
if ((driverMode === 'mysql' || driverMode === 'mysql-cluster') && useExecute) {
3649
// Not applicable, mysql does not provide an execute function, only the query function whereas mysql2 provides both.
3750
return;
3851
}
3952

40-
describe(`driver mode: ${driverMode}, access function: ${useExecute ? 'execute' : 'query'}`, () => {
53+
describe(`driver mode: ${driverMode} version: ${mysql2Version || 'default'}, access function: ${
54+
useExecute ? 'execute' : 'query'
55+
}`, () => {
4156
const env = {
42-
DRIVER_MODE: driverMode
57+
DRIVER_MODE: driverMode,
58+
MYSQL2_VERSION: mysql2Version
4359
};
4460

4561
if (useExecute) {
@@ -51,7 +67,8 @@ function registerSuite(agentControls, driverMode, useExecute) {
5167

5268
describe('suppressed', function () {
5369
const env = {
54-
DRIVER_MODE: driverMode
70+
DRIVER_MODE: driverMode,
71+
MYSQL2_VERSION: mysql2Version
5572
};
5673
if (useExecute) {
5774
env.USE_EXECUTE = 'true';

packages/core/src/tracing/instrumentation/database/mysql.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,26 @@ function instrumentMysql(mysql) {
2929
}
3030

3131
function instrumentMysql2(mysql) {
32-
instrumentConnection(mysql.Connection.prototype, true);
33-
if (mysql.Pool) {
34-
instrumentPool(mysql.Pool.prototype);
32+
/**
33+
* In mysql2 version 3.11.5 and later, the internal structure of the `Connection` and `Pool` classes was reorganized.
34+
* Methods like `query` and `execute` were moved into the `BaseConnection` class located in `lib/base/connection.js`,
35+
* and similar changes were applied to the `Pool` class. See: https://github.com/sidorares/node-mysql2/pull/3081
36+
*
37+
* Prior to v3.11.5, the `Connection` and `Pool` prototypes were directly used for instrumentation.
38+
*/
39+
const connectionPrototype =
40+
Object.getPrototypeOf(mysql.Connection.prototype)?.constructor?.name === 'BaseConnection'
41+
? Object.getPrototypeOf(mysql.Connection.prototype)
42+
: mysql.Connection.prototype;
43+
44+
const poolPrototype =
45+
mysql.Pool && Object.getPrototypeOf(mysql.Pool.prototype)?.constructor?.name === 'BasePool'
46+
? Object.getPrototypeOf(mysql.Pool.prototype)
47+
: mysql.Pool?.prototype;
48+
49+
instrumentConnection(connectionPrototype, true);
50+
if (poolPrototype) {
51+
instrumentPool(poolPrototype);
3552
}
3653
}
3754

0 commit comments

Comments
 (0)