forked from elastic/apm-agent-nodejs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmysql2.js
126 lines (110 loc) · 3.41 KB
/
mysql2.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
* Copyright Elasticsearch B.V. and other contributors where applicable.
* Licensed under the BSD 2-Clause License; you may not use this file except in
* compliance with the BSD 2-Clause License.
*/
'use strict';
var semver = require('semver');
var sqlSummary = require('sql-summary');
var shimmer = require('../shimmer');
var symbols = require('../../symbols');
var { getDBDestination } = require('../context');
module.exports = function (mysql2, agent, { version, enabled }) {
if (!enabled) {
return mysql2;
}
if (!semver.satisfies(version, '>=1 <4')) {
agent.logger.debug(
'mysql2 version %s not supported - aborting...',
version,
);
return mysql2;
}
var ins = agent._instrumentation;
shimmer.wrap(mysql2.Connection.prototype, 'query', wrapQuery);
shimmer.wrap(mysql2.Connection.prototype, 'execute', wrapQuery);
return mysql2;
function wrapQuery(original) {
return function wrappedQuery(sql, values, cb) {
agent.logger.debug('intercepted call to mysql2.%s', original.name);
var span = ins.createSpan(null, 'db', 'mysql', 'query', {
exitSpan: true,
});
if (!span) {
return original.apply(this, arguments);
}
if (this[symbols.knexStackObj]) {
span.customStackTrace(this[symbols.knexStackObj]);
this[symbols.knexStackObj] = null;
}
let hasCallback = false;
const wrapCallback = function (origCallback) {
hasCallback = true;
return ins.bindFunction(function wrappedCallback(_err) {
span.end();
return origCallback.apply(this, arguments);
});
};
let host, port, user, database;
if (typeof this.config === 'object') {
({ host, port, user, database } = this.config);
}
span._setDestinationContext(getDBDestination(host, port));
let sqlStr;
switch (typeof sql) {
case 'string':
sqlStr = sql;
break;
case 'object':
// `mysql2.{query,execute}` support the only arg being an instance
// of the internal mysql2 `Command` object.
if (typeof sql.onResult === 'function') {
sql.onResult = wrapCallback(sql.onResult);
}
sqlStr = sql.sql;
break;
case 'function':
arguments[0] = wrapCallback(sql);
break;
}
if (sqlStr) {
span.setDbContext({
type: 'sql',
instance: database,
user,
statement: sqlStr,
});
span.name = sqlSummary(sqlStr);
} else {
span.setDbContext({ type: 'sql', instance: database, user });
}
if (typeof values === 'function') {
arguments[1] = wrapCallback(values);
} else if (typeof cb === 'function') {
arguments[2] = wrapCallback(cb);
}
const spanRunContext = ins.currRunContext().enterSpan(span);
const result = ins.withRunContext(
spanRunContext,
original,
this,
...arguments,
);
if (result && !hasCallback) {
ins.bindEmitter(result);
shimmer.wrap(result, 'emit', function (origEmit) {
return function (event) {
switch (event) {
case 'error':
case 'close':
case 'end':
span.end();
}
return origEmit.apply(this, arguments);
};
});
}
return result;
};
}
};