newrelic 9.14.1 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NEWS.md +61 -16
- package/README.md +0 -3
- package/THIRD_PARTY_NOTICES.md +3 -3
- package/esm-loader.mjs +12 -13
- package/lib/config/default.js +8 -1
- package/lib/config/index.js +7 -1
- package/lib/instrumentation/@hapi/vision.js +4 -6
- package/lib/instrumentation/mysql/mysql.js +19 -7
- package/lib/instrumentation/mysql/nr-hooks.js +5 -5
- package/lib/serverless/aws-lambda.js +1 -0
- package/lib/shim/conglomerate-shim.js +6 -2
- package/lib/shim/datastore-shim.js +63 -57
- package/lib/shim/index.js +4 -3
- package/lib/shim/message-shim.js +7 -10
- package/lib/shim/promise-shim.js +7 -8
- package/lib/shim/shim.js +101 -59
- package/lib/shim/transaction-shim.js +3 -2
- package/lib/shim/webframework-shim.js +11 -27
- package/lib/shimmer.js +118 -93
- package/lib/symbols.js +8 -1
- package/lib/transaction/index.js +161 -82
- package/lib/transaction/trace/index.js +63 -54
- package/lib/transaction/tracecontext.js +56 -44
- package/package.json +3 -2
package/NEWS.md
CHANGED
|
@@ -1,19 +1,64 @@
|
|
|
1
|
-
###
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
### v10.0.0 (2023-04-19)
|
|
2
|
+
|
|
3
|
+
* **BREAKING** - Updated the default of `config.transaction_tracer.record_sql` from `off` to `obfuscated`. This means that sql statements will be captured but obfuscated.
|
|
4
|
+
|
|
5
|
+
* **BREAKING** - Route (URL) parameters are now stored as `request.parameters.route.*` attributes on Transactions, root Segments and Spans.
|
|
6
|
+
|
|
7
|
+
After this change, the following becomes true:
|
|
8
|
+
|
|
9
|
+
- Query parameters will be available as attributes prefixed with request.parameters.* on Transactions and Spans.
|
|
10
|
+
|
|
11
|
+
- Route parameters will be available as attributes prefixed with request.parameters.route.* on Transactions and Spans.
|
|
12
|
+
|
|
13
|
+
- Route parameters (aka url parameters) are a common feature of various web frameworks, where you can create a placeholder as part of an API route definition.
|
|
14
|
+
|
|
15
|
+
For example, given the following Express route definition and request url:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
app.get('/api/users/:id', myMiddleware, myController)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
curl http://localhost:3000/api/users/abc123?id=true
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The route parameter is `id`, and has a value of `abc123`. This would become `request.parameters.route.id: abc123` on the Transaction, root Segment, and Span attributes. This example also has a query parameter of `id`, which has a value of true. This would become `request.parameters.id: true` on the Transaction, root Segment, and Span attributes.
|
|
26
|
+
|
|
27
|
+
* **BREAKING** - Removed `captureUrlParams` from `WebFrameworkShim` class.
|
|
28
|
+
|
|
29
|
+
* **DEPRECATION NOTICE**: `shim.unwrap` and `shim.unwrapOnce` will no longer function if you attempt to unwrap an item that has been wrapped multiple times.
|
|
30
|
+
* This is because since we now allow instrumenting the same module more than once, you cannot safely unwrap without breaking all registered instrumentation. We plan to remove `shim.unwrap` and `shim.unwrapOnce` in the next major release.
|
|
31
|
+
|
|
32
|
+
* Added the ability to register instrumentation multiple hooks (onRequire, onResolved) for the same resolved moduleName.
|
|
33
|
+
* This has been a limitation of the agent from the beginning.
|
|
34
|
+
* If you used the api to instrument `api.instrument`, `api.instrumentDatastore`, `api.instrumentWebframework`, `api.instrumentMessages`, or `api.instrumentConglomerate`, it would override existing instrumentation hooks. The effect was that the Node.js agent would not function as designed.
|
|
35
|
+
|
|
36
|
+
* Refactored lib/transaction/tracecontext.js to reduce cognitive complexity.
|
|
37
|
+
|
|
38
|
+
* Refactored lib/transaction/trace/index.js to reduce cognitive complexity.
|
|
39
|
+
|
|
40
|
+
* Upgraded devDependencies jsdoc, and lean-jsdoc-theme.
|
|
41
|
+
|
|
42
|
+
### v9.15.0 (2023-04-04)
|
|
43
|
+
|
|
44
|
+
* Added a new configuration option `heroku.use_dyno_names` to specify whether or not to use `process.env.DYNO` for naming the host name and display host. This option defaults to true. If you are on heroku and do not want this functionality set `heroku.use_dyno_names` to `false`. You can also control this configuration options with the environment variable of `NEW_RELIC_HEROKU_USE_DYNO_NAMES`. Thanks @benney-au-le for your contribution 🚀
|
|
45
|
+
|
|
46
|
+
### v9.14.1 (2023-03-23)
|
|
47
|
+
|
|
48
|
+
* Restored assigning loaded version of agent to require.cache as `__NR_cache` instead of a symbol to properly detect attempts at loading agent twice.
|
|
49
|
+
|
|
50
|
+
### v9.14.0 (2023-03-23)
|
|
51
|
+
|
|
52
|
+
* Added new API function called `setErrorGroupCallback`, which provides a way for you to customize the `error.group.name` attribute of errors that are captured by the agent. This attribute controls how the Errors Inbox functionality groups similar errors together. To learn more about this function, please refer to our [example app](https://github.com/newrelic/newrelic-node-examples).
|
|
53
|
+
|
|
54
|
+
### v9.13.0 (2023-03-20)
|
|
55
|
+
|
|
56
|
+
* Updated http instrumentation to no longer remove the `x-new-relic-disable-dt` header when using AWS SDK v3. This was done to prevent the "The request signature we calculated does not match the signature you provided. Check your key and signing method." error from AWS SDK.
|
|
57
|
+
|
|
58
|
+
* Added an API method `setUserID` to provide an ability to associate a unique identifier with a transaction event, transaction trace and errors within transaction. The attribute will be `enduser.id`.
|
|
59
|
+
|
|
60
|
+
* Added default configuration for security agent.
|
|
61
|
+
|
|
17
62
|
### v9.12.1 (2023-03-15)
|
|
18
63
|
|
|
19
64
|
* Added ability to mark errors as expected when using `newrelic.noticeError`, by adding an optional boolean:
|
package/README.md
CHANGED
|
@@ -133,9 +133,6 @@ For more information on getting started, [check the Node.js docs](https://docs.n
|
|
|
133
133
|
There are several modules that can be installed and configured to accompany the Node.js agent:
|
|
134
134
|
|
|
135
135
|
* [@newrelic/apollo-server-plugin](https://github.com/newrelic/newrelic-node-apollo-server-plugin): New Relic's official Apollo Server plugin for use with the Node.js agent.
|
|
136
|
-
* [@newrelic/winston-enricher](https://github.com/newrelic/newrelic-node-log-extensions/tree/main/packages/winston-log-enricher): Provides distributed trace and span information output as JSON-formatted log messages in Winston. This is most commonly used with the New Relic Logs product.
|
|
137
|
-
* [@newrelic/pino-enricher](https://github.com/newrelic/newrelic-node-log-extensions/tree/main/packages/pino-log-enricher): Provides distributed trace and span information output as JSON-formatted log messages in Pino. This is most commonly used with the New Relic Logs product.
|
|
138
|
-
* [@newrelic/mysql](https://github.com/newrelic/node-newrelic-mysql)(**Experimental**): Standalone instrumentation for [mysql2](https://github.com/sidorares/node-mysql2#readme) and [mysql2/promise](https://github.com/sidorares/node-mysql2/blob/master/documentation/Promise-Wrapper.md) as well as the same instrumentation for [mysql](https://github.com/mysqljs/mysql#readme) within the Node.js agent.
|
|
139
136
|
* [@newrelic/next](https://github.com/newrelic/newrelic-node-nextjs): Provides instrumentation for the [Next.js](https://github.com/vercel/next.js/) npm package.
|
|
140
137
|
|
|
141
138
|
There are several modules included within the Node.js agent to add more instrumentation for 3rd party modules:
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -1800,7 +1800,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
1800
1800
|
|
|
1801
1801
|
### @newrelic/test-utilities
|
|
1802
1802
|
|
|
1803
|
-
This product includes source derived from [@newrelic/test-utilities](https://github.com/newrelic/node-test-utilities) ([v7.
|
|
1803
|
+
This product includes source derived from [@newrelic/test-utilities](https://github.com/newrelic/node-test-utilities) ([v7.3.0](https://github.com/newrelic/node-test-utilities/tree/v7.3.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-test-utilities/blob/v7.3.0/LICENSE):
|
|
1804
1804
|
|
|
1805
1805
|
```
|
|
1806
1806
|
Apache License
|
|
@@ -2177,7 +2177,7 @@ SOFTWARE.
|
|
|
2177
2177
|
|
|
2178
2178
|
### clean-jsdoc-theme
|
|
2179
2179
|
|
|
2180
|
-
This product includes source derived from [clean-jsdoc-theme](https://github.com/ankitskvmdam/clean-jsdoc-theme) ([v4.2.
|
|
2180
|
+
This product includes source derived from [clean-jsdoc-theme](https://github.com/ankitskvmdam/clean-jsdoc-theme) ([v4.2.7](https://github.com/ankitskvmdam/clean-jsdoc-theme/tree/v4.2.7)), distributed under the [MIT License](https://github.com/ankitskvmdam/clean-jsdoc-theme/blob/v4.2.7/LICENSE):
|
|
2181
2181
|
|
|
2182
2182
|
```
|
|
2183
2183
|
MIT License
|
|
@@ -2709,7 +2709,7 @@ SOFTWARE.
|
|
|
2709
2709
|
|
|
2710
2710
|
### jsdoc
|
|
2711
2711
|
|
|
2712
|
-
This product includes source derived from [jsdoc](https://github.com/jsdoc/jsdoc) ([v4.0.
|
|
2712
|
+
This product includes source derived from [jsdoc](https://github.com/jsdoc/jsdoc) ([v4.0.2](https://github.com/jsdoc/jsdoc/tree/v4.0.2)), distributed under the [Apache-2.0 License](https://github.com/jsdoc/jsdoc/blob/v4.0.2/LICENSE.md):
|
|
2713
2713
|
|
|
2714
2714
|
```
|
|
2715
2715
|
# License
|
package/esm-loader.mjs
CHANGED
|
@@ -68,19 +68,18 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
68
68
|
|
|
69
69
|
if (format === 'commonjs') {
|
|
70
70
|
// ES Modules translate import statements into fully qualified filepaths, so we create a copy of our instrumentation under this filepath
|
|
71
|
-
const instrumentationDefinitionCopy =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
71
|
+
const instrumentationDefinitionCopy = [...instrumentationDefinition]
|
|
72
|
+
instrumentationDefinitionCopy.forEach((copy) => {
|
|
73
|
+
// Stripping the prefix is necessary because the code downstream gets this url without it
|
|
74
|
+
copy.moduleName = fileURLToPath(url)
|
|
75
|
+
|
|
76
|
+
// Added to keep our Supportability metrics from exploding/including customer info via full filepath
|
|
77
|
+
copy.specifier = specifier
|
|
78
|
+
shimmer.registerInstrumentation(copy)
|
|
79
|
+
logger.debug(
|
|
80
|
+
`Registered CommonJS instrumentation for ${specifier} under ${copy.moduleName}`
|
|
81
|
+
)
|
|
82
|
+
})
|
|
84
83
|
} else if (format === 'module') {
|
|
85
84
|
registeredSpecifiers.set(url, specifier)
|
|
86
85
|
const modifiedUrl = new URL(url)
|
package/lib/config/default.js
CHANGED
|
@@ -573,7 +573,7 @@ defaultConfig.definition = () => ({
|
|
|
573
573
|
*/
|
|
574
574
|
record_sql: {
|
|
575
575
|
formatter: allowList.bind(null, ['off', 'obfuscated', 'raw']),
|
|
576
|
-
default: '
|
|
576
|
+
default: 'obfuscated',
|
|
577
577
|
env: 'NEW_RELIC_RECORD_SQL'
|
|
578
578
|
},
|
|
579
579
|
|
|
@@ -1318,6 +1318,13 @@ defaultConfig.definition = () => ({
|
|
|
1318
1318
|
}
|
|
1319
1319
|
}
|
|
1320
1320
|
}
|
|
1321
|
+
},
|
|
1322
|
+
|
|
1323
|
+
heroku: {
|
|
1324
|
+
use_dyno_names: {
|
|
1325
|
+
default: true,
|
|
1326
|
+
formatter: boolean
|
|
1327
|
+
}
|
|
1321
1328
|
}
|
|
1322
1329
|
})
|
|
1323
1330
|
|
package/lib/config/index.js
CHANGED
|
@@ -914,11 +914,17 @@ Config.prototype.getIPAddresses = function getIPAddresses() {
|
|
|
914
914
|
|
|
915
915
|
function getHostnameSafe() {
|
|
916
916
|
let _hostname
|
|
917
|
+
const config = this
|
|
917
918
|
this.getHostnameSafe = function getCachedHostname() {
|
|
918
919
|
return _hostname
|
|
919
920
|
}
|
|
920
921
|
try {
|
|
921
|
-
|
|
922
|
+
if (config.heroku.use_dyno_names) {
|
|
923
|
+
const dynoName = process.env.DYNO
|
|
924
|
+
_hostname = dynoName || os.hostname()
|
|
925
|
+
} else {
|
|
926
|
+
_hostname = os.hostname()
|
|
927
|
+
}
|
|
922
928
|
return _hostname
|
|
923
929
|
} catch (e) {
|
|
924
930
|
const addresses = this.getIPAddresses()
|
|
@@ -20,13 +20,11 @@ module.exports = function initialize(agent, vision, moduleName, shim) {
|
|
|
20
20
|
|
|
21
21
|
shim.wrap(plugin, 'register', function wrapRegister(shim, register) {
|
|
22
22
|
return function wrappedRegister(server) {
|
|
23
|
-
shim.
|
|
23
|
+
if (!shim.isWrapped(server, 'decorate')) {
|
|
24
|
+
shim.wrap(server, 'decorate', wrapDecorate)
|
|
25
|
+
}
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
shim.unwrapOnce(server, 'decorate')
|
|
28
|
-
|
|
29
|
-
return ret
|
|
27
|
+
return register.apply(this, arguments)
|
|
30
28
|
}
|
|
31
29
|
})
|
|
32
30
|
}
|
|
@@ -11,40 +11,52 @@ const symbols = require('../../symbols')
|
|
|
11
11
|
|
|
12
12
|
exports.callbackInitialize = function callbackInitialize(shim, mysql) {
|
|
13
13
|
shim.setDatastore(shim.MYSQL)
|
|
14
|
-
shim.
|
|
14
|
+
shim[symbols.wrappedPoolConnection] = true
|
|
15
15
|
|
|
16
16
|
shim.wrapReturn(mysql, 'createConnection', wrapCreateConnection)
|
|
17
17
|
function wrapCreateConnection(shim, fn, fnName, connection) {
|
|
18
|
+
if (shim[symbols.unwrapConnection]) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
18
21
|
shim.logger.debug('Wrapping Connection#query')
|
|
19
22
|
if (wrapQueryable(shim, connection, false)) {
|
|
20
23
|
const connProto = Object.getPrototypeOf(connection)
|
|
21
24
|
connProto[symbols.storeDatabase] = true
|
|
22
|
-
shim.
|
|
25
|
+
shim[symbols.unwrapConnection] = true
|
|
23
26
|
}
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
shim.wrapReturn(mysql, 'createPool', wrapCreatePool)
|
|
27
30
|
function wrapCreatePool(shim, fn, fnName, pool) {
|
|
31
|
+
if (shim[symbols.unwrapPool]) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
28
34
|
shim.logger.debug('Wrapping Pool#query and Pool#getConnection')
|
|
29
35
|
if (wrapQueryable(shim, pool, true) && wrapGetConnection(shim, pool)) {
|
|
30
|
-
shim.
|
|
36
|
+
shim[symbols.unwrapPool] = true
|
|
31
37
|
}
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
shim.wrapReturn(mysql, 'createPoolCluster', wrapCreatePoolCluster)
|
|
35
41
|
function wrapCreatePoolCluster(shim, fn, fnName, poolCluster) {
|
|
42
|
+
if (shim[symbols.createPoolCluster]) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
36
45
|
shim.logger.debug('Wrapping PoolCluster#of')
|
|
37
46
|
const proto = Object.getPrototypeOf(poolCluster)
|
|
38
47
|
shim.wrapReturn(proto, 'of', wrapPoolClusterOf)
|
|
39
48
|
function wrapPoolClusterOf(shim, of, _n, poolNamespace) {
|
|
49
|
+
if (shim[symbols.clusterOf]) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
40
52
|
if (wrapGetConnection(shim, poolNamespace)) {
|
|
41
|
-
shim.
|
|
53
|
+
shim[symbols.clusterOf] = true
|
|
42
54
|
}
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
shim.logger.debug('Wrapping PoolCluster#getConnection')
|
|
46
58
|
if (wrapGetConnection(shim, poolCluster)) {
|
|
47
|
-
shim.
|
|
59
|
+
shim[symbols.createPoolCluster] = true
|
|
48
60
|
}
|
|
49
61
|
}
|
|
50
62
|
}
|
|
@@ -83,7 +95,7 @@ function wrapGetConnection(shim, connectable) {
|
|
|
83
95
|
'Wrapping callback with segment'
|
|
84
96
|
)
|
|
85
97
|
let cb = args[cbIdx]
|
|
86
|
-
if (!shim.
|
|
98
|
+
if (!shim[symbols.wrappedPoolConnection]) {
|
|
87
99
|
cb = shim.wrap(cb, wrapGetConnectionCallback)
|
|
88
100
|
}
|
|
89
101
|
args[cbIdx] = shim.bindSegment(cb)
|
|
@@ -102,7 +114,7 @@ function wrapGetConnectionCallback(shim, cb) {
|
|
|
102
114
|
if (!err && wrapQueryable(shim, conn, false)) {
|
|
103
115
|
// Leave getConnection wrapped in order to maintain TX state, but we can
|
|
104
116
|
// simplify the wrapping of its callback in future calls.
|
|
105
|
-
shim.
|
|
117
|
+
shim[symbols.wrappedPoolConnection] = true
|
|
106
118
|
}
|
|
107
119
|
} catch (_err) {
|
|
108
120
|
shim.logger.debug(
|
|
@@ -6,17 +6,17 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
const instrumentation = require('./mysql')
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* We only need to register the instrumentation once for both mysql and mysql2
|
|
11
|
-
* because there is some 🪄 in shimmer
|
|
12
|
-
* See: https://github.com/newrelic/node-newrelic/blob/main/lib/shimmer.js#L459
|
|
13
|
-
*/
|
|
14
9
|
module.exports = [
|
|
15
10
|
{
|
|
16
11
|
type: 'datastore',
|
|
17
12
|
moduleName: 'mysql',
|
|
18
13
|
onRequire: instrumentation.callbackInitialize
|
|
19
14
|
},
|
|
15
|
+
{
|
|
16
|
+
type: 'datastore',
|
|
17
|
+
moduleName: 'mysql2',
|
|
18
|
+
onRequire: instrumentation.callbackInitialize
|
|
19
|
+
},
|
|
20
20
|
{
|
|
21
21
|
type: 'datastore',
|
|
22
22
|
moduleName: 'mysql2/promise',
|
|
@@ -328,6 +328,7 @@ function setWebRequest(shim, transaction, request) {
|
|
|
328
328
|
|
|
329
329
|
transaction.port = request.url.port
|
|
330
330
|
|
|
331
|
+
// These are only query parameters, from lib/serverless/api-gateway.js
|
|
331
332
|
transaction.addRequestParameters(request.url.requestParameters)
|
|
332
333
|
|
|
333
334
|
// URL is sent as an agent attribute with transaction events
|
|
@@ -23,10 +23,14 @@ const SHIM_CLASSES = {
|
|
|
23
23
|
*
|
|
24
24
|
* @private
|
|
25
25
|
* @augments Shim
|
|
26
|
+
* @param {Agent} agent The agent this shim will use.
|
|
27
|
+
* @param {string} moduleName The name of the module being instrumented.
|
|
28
|
+
* @param {string} resolvedName The full path to the loaded module.
|
|
29
|
+
* @param {string} shimName Used to persist shim ids across different shim instances.
|
|
26
30
|
*/
|
|
27
31
|
class ConglomerateShim extends Shim {
|
|
28
|
-
constructor(agent, moduleName, resolvedName) {
|
|
29
|
-
super(agent, moduleName, resolvedName)
|
|
32
|
+
constructor(agent, moduleName, resolvedName, shimName) {
|
|
33
|
+
super(agent, moduleName, resolvedName, shimName)
|
|
30
34
|
this._logger = logger.child({ module: moduleName })
|
|
31
35
|
this._resolvedName = resolvedName
|
|
32
36
|
}
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
/* eslint sonarjs/cognitive-complexity: ["error", 57] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
|
-
|
|
10
8
|
const dbutil = require('../db/utils')
|
|
11
9
|
const hasOwnProperty = require('../util/properties').hasOwn
|
|
12
10
|
const logger = require('../logger').child({ component: 'DatastoreShim' })
|
|
@@ -16,7 +14,6 @@ const ParsedStatement = require('../db/parsed-statement')
|
|
|
16
14
|
const Shim = require('./shim')
|
|
17
15
|
const urltils = require('../util/urltils')
|
|
18
16
|
const util = require('util')
|
|
19
|
-
const symbols = require('../symbols')
|
|
20
17
|
|
|
21
18
|
/**
|
|
22
19
|
* An enumeration of well-known datastores so that new instrumentations can use
|
|
@@ -73,28 +70,17 @@ const QUERY_PARSERS = {
|
|
|
73
70
|
*
|
|
74
71
|
* @class
|
|
75
72
|
* @augments Shim
|
|
76
|
-
* @classdesc
|
|
77
|
-
*
|
|
78
|
-
* @param {
|
|
79
|
-
*
|
|
80
|
-
* @param {string}
|
|
81
|
-
* The name of the module being instrumented.
|
|
82
|
-
* @param {string} resolvedName
|
|
83
|
-
* The full path to the loaded module.
|
|
84
|
-
* @param {string} [datastoreId]
|
|
85
|
-
* The name of the datastore being instrumented. If available, use one of the
|
|
86
|
-
* values from {@link DatastoreShim.DATASTORE_NAMES}.
|
|
87
|
-
* Calls {@link DatastoreShim#setDatastore} if datastoreId is
|
|
88
|
-
* specified.
|
|
73
|
+
* @classdesc A helper class for wrapping datastore modules.
|
|
74
|
+
* @param {Agent} agent The agent this shim will use.
|
|
75
|
+
* @param {string} moduleName The name of the module being instrumented.
|
|
76
|
+
* @param {string} resolvedName The full path to the loaded module.
|
|
77
|
+
* @param {string} shimName Used to persist shim ids across different shim instances.
|
|
89
78
|
* @see Shim
|
|
90
79
|
* @see DatastoreShim.DATASTORE_NAMES
|
|
91
80
|
*/
|
|
92
|
-
function DatastoreShim(agent, moduleName, resolvedName,
|
|
93
|
-
Shim.call(this, agent, moduleName, resolvedName)
|
|
81
|
+
function DatastoreShim(agent, moduleName, resolvedName, shimName) {
|
|
82
|
+
Shim.call(this, agent, moduleName, resolvedName, shimName)
|
|
94
83
|
this._logger = logger.child({ module: moduleName })
|
|
95
|
-
if (datastoreId) {
|
|
96
|
-
this.setDatastore(datastoreId)
|
|
97
|
-
}
|
|
98
84
|
this.queryParser = defaultParsers[this.SQL_PARSER]
|
|
99
85
|
}
|
|
100
86
|
module.exports = DatastoreShim
|
|
@@ -357,19 +343,17 @@ function recordOperation(nodule, properties, opSpec) {
|
|
|
357
343
|
return this.record(nodule, properties, function opRecorder(shim, fn, fnName, args) {
|
|
358
344
|
shim.logger.trace('Recording datastore operation "%s"', fnName)
|
|
359
345
|
|
|
360
|
-
// Derive the segment information
|
|
346
|
+
// Derive the segment information, starting from some defaults
|
|
361
347
|
let segDesc = null
|
|
362
348
|
if (shim.isFunction(opSpec)) {
|
|
363
349
|
segDesc = opSpec.call(this, shim, fn, fnName, args)
|
|
364
350
|
} else {
|
|
365
351
|
segDesc = {
|
|
366
|
-
name:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
record: opSpec.record,
|
|
372
|
-
opaque: opSpec.opaque || false
|
|
352
|
+
name: fnName || 'other',
|
|
353
|
+
opaque: false,
|
|
354
|
+
after: null,
|
|
355
|
+
promise: null,
|
|
356
|
+
...opSpec
|
|
373
357
|
}
|
|
374
358
|
}
|
|
375
359
|
if (hasOwnProperty(segDesc, 'parameters')) {
|
|
@@ -549,8 +533,7 @@ function bindRowCallbackSegment(args, cbIdx, parentSegment) {
|
|
|
549
533
|
return shim.applySegment(cb, segment, true, this, arguments)
|
|
550
534
|
}, parentSegment)
|
|
551
535
|
|
|
552
|
-
|
|
553
|
-
wrapper[symbols.original] = cb
|
|
536
|
+
shim.assignOriginal(wrapper, cb, true)
|
|
554
537
|
args[idx] = wrapper
|
|
555
538
|
}
|
|
556
539
|
|
|
@@ -648,26 +631,31 @@ function _recordQuery(suffix, nodule, properties, querySpec) {
|
|
|
648
631
|
|
|
649
632
|
let queryDesc = querySpec
|
|
650
633
|
if (shim.isFunction(querySpec)) {
|
|
651
|
-
queryDesc = querySpec.call(this, shim, fn, fnName, args)
|
|
634
|
+
queryDesc = querySpec.call(this, shim, fn, fnName, args) || Object.create(null)
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Set some default values, in case they're missing.
|
|
638
|
+
queryDesc = {
|
|
639
|
+
name: fnName,
|
|
640
|
+
callback: null,
|
|
641
|
+
rowCallback: null,
|
|
642
|
+
stream: null,
|
|
643
|
+
after: null,
|
|
644
|
+
promise: null,
|
|
645
|
+
opaque: false,
|
|
646
|
+
inContext: null,
|
|
647
|
+
...queryDesc
|
|
652
648
|
}
|
|
653
649
|
|
|
650
|
+
const parameters = _normalizeParameters.call(shim, queryDesc.parameters || Object.create(null))
|
|
651
|
+
|
|
654
652
|
// If we're not actually recording this, then just return the segment
|
|
655
653
|
// descriptor now.
|
|
656
|
-
if (
|
|
657
|
-
const parameters = _normalizeParameters.call(
|
|
658
|
-
shim,
|
|
659
|
-
queryDesc.parameters || Object.create(null)
|
|
660
|
-
)
|
|
654
|
+
if (queryDesc?.record === false) {
|
|
661
655
|
return {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
rowCallback: 'rowCallback' in queryDesc ? queryDesc.rowCallback : null,
|
|
666
|
-
stream: 'stream' in queryDesc ? queryDesc.stream : null,
|
|
667
|
-
after: 'after' in queryDesc ? queryDesc.after : null,
|
|
668
|
-
promise: 'promise' in queryDesc ? queryDesc.promise : null,
|
|
669
|
-
internal: 'internal' in queryDesc ? queryDesc.internal : false,
|
|
670
|
-
opaque: 'opaque' in queryDesc ? queryDesc.opaque : false
|
|
656
|
+
internal: false,
|
|
657
|
+
...queryDesc,
|
|
658
|
+
parameters
|
|
671
659
|
}
|
|
672
660
|
}
|
|
673
661
|
|
|
@@ -683,18 +671,13 @@ function _recordQuery(suffix, nodule, properties, querySpec) {
|
|
|
683
671
|
shim.logger.trace('Found and parsed query %s -> %s', parsed.type, name)
|
|
684
672
|
|
|
685
673
|
// Return the segment descriptor.
|
|
686
|
-
const parameters = _normalizeParameters.call(shim, queryDesc.parameters || Object.create(null))
|
|
687
674
|
return {
|
|
675
|
+
internal: true,
|
|
676
|
+
...queryDesc,
|
|
677
|
+
// This name and parameters might override those in the original
|
|
678
|
+
// queryDesc.
|
|
688
679
|
name: shim._metrics.STATEMENT + name,
|
|
689
680
|
parameters,
|
|
690
|
-
callback: 'callback' in queryDesc ? queryDesc.callback : null,
|
|
691
|
-
rowCallback: 'rowCallback' in queryDesc ? queryDesc.rowCallback : null,
|
|
692
|
-
stream: 'stream' in queryDesc ? queryDesc.stream : null,
|
|
693
|
-
after: 'after' in queryDesc ? queryDesc.after : null,
|
|
694
|
-
promise: 'promise' in queryDesc ? queryDesc.promise : null,
|
|
695
|
-
internal: 'internal' in queryDesc ? queryDesc.internal : true,
|
|
696
|
-
opaque: 'opaque' in queryDesc ? queryDesc.opaque : false,
|
|
697
|
-
inContext: 'inContext' in queryDesc ? queryDesc.inContext : null,
|
|
698
681
|
recorder: function queryRecorder(segment, scope) {
|
|
699
682
|
if (segment) {
|
|
700
683
|
parsed.recordMetrics(segment, scope)
|
|
@@ -806,6 +789,20 @@ function _normalizeParameters(parameters) {
|
|
|
806
789
|
|
|
807
790
|
parameters.product = parameters.product || this._datastore
|
|
808
791
|
|
|
792
|
+
_normalizeDatabaseName(parameters, dsTracerConf)
|
|
793
|
+
_normalizeInstanceInformation(parameters, dsTracerConf, config)
|
|
794
|
+
|
|
795
|
+
return parameters
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Normalizes the database name from segment parameter values.
|
|
800
|
+
*
|
|
801
|
+
* @private
|
|
802
|
+
* @param {object} parameters - The segment parameters to clean up.
|
|
803
|
+
* @param {object} dsTracerConf - The datastore tracer configuration
|
|
804
|
+
*/
|
|
805
|
+
function _normalizeDatabaseName(parameters, dsTracerConf) {
|
|
809
806
|
// Add database name if provided and enabled.
|
|
810
807
|
if (!dsTracerConf.database_name_reporting.enabled) {
|
|
811
808
|
delete parameters.database_name
|
|
@@ -815,7 +812,18 @@ function _normalizeParameters(parameters) {
|
|
|
815
812
|
? String(parameters.database_name)
|
|
816
813
|
: parameters.database_name || INSTANCE_UNKNOWN
|
|
817
814
|
}
|
|
815
|
+
}
|
|
818
816
|
|
|
817
|
+
/**
|
|
818
|
+
* Normalizes the database instance information from segment parameter
|
|
819
|
+
* values: host and the port/path/id.
|
|
820
|
+
*
|
|
821
|
+
* @private
|
|
822
|
+
* @param {object} parameters - The segment parameters to clean up.
|
|
823
|
+
* @param {object} dsTracerConf - The datastore tracer configuration
|
|
824
|
+
* @param {object} config - The agent configuration
|
|
825
|
+
*/
|
|
826
|
+
function _normalizeInstanceInformation(parameters, dsTracerConf, config) {
|
|
819
827
|
// Add instance information if enabled.
|
|
820
828
|
if (!dsTracerConf.instance_reporting.enabled) {
|
|
821
829
|
delete parameters.host
|
|
@@ -836,6 +844,4 @@ function _normalizeParameters(parameters) {
|
|
|
836
844
|
}
|
|
837
845
|
}
|
|
838
846
|
}
|
|
839
|
-
|
|
840
|
-
return parameters
|
|
841
847
|
}
|
package/lib/shim/index.js
CHANGED
|
@@ -30,14 +30,15 @@ SHIM_TYPE_MAP[constants.MODULE_TYPE.WEB_FRAMEWORK] = WebFrameworkShim
|
|
|
30
30
|
* @param agent
|
|
31
31
|
* @param moduleName
|
|
32
32
|
* @param resolvedName
|
|
33
|
+
* @param shimName
|
|
33
34
|
*/
|
|
34
|
-
function createShimFromType(type, agent, moduleName, resolvedName) {
|
|
35
|
+
function createShimFromType(type, agent, moduleName, resolvedName, shimName) {
|
|
35
36
|
let shim = null
|
|
36
37
|
if (properties.hasOwn(SHIM_TYPE_MAP, type)) {
|
|
37
38
|
const ShimClass = SHIM_TYPE_MAP[type]
|
|
38
|
-
shim = new ShimClass(agent, moduleName, resolvedName)
|
|
39
|
+
shim = new ShimClass(agent, moduleName, resolvedName, shimName)
|
|
39
40
|
} else {
|
|
40
|
-
shim = new Shim(agent, moduleName, resolvedName)
|
|
41
|
+
shim = new Shim(agent, moduleName, resolvedName, shimName)
|
|
41
42
|
}
|
|
42
43
|
return shim
|
|
43
44
|
}
|
package/lib/shim/message-shim.js
CHANGED
|
@@ -66,19 +66,16 @@ const DESTINATION_TYPES = {
|
|
|
66
66
|
*
|
|
67
67
|
* @class
|
|
68
68
|
* @augments TransactionShim
|
|
69
|
-
* @classdesc
|
|
70
|
-
*
|
|
71
|
-
* @param {
|
|
72
|
-
*
|
|
73
|
-
* @param {string}
|
|
74
|
-
* The name of the module being instrumented.
|
|
75
|
-
* @param {string} resolvedName
|
|
76
|
-
* The full path to the loaded module.
|
|
69
|
+
* @classdesc Used for instrumenting message broker client libraries.
|
|
70
|
+
* @param {Agent} agent The agent this shim will use.
|
|
71
|
+
* @param {string} moduleName The name of the module being instrumented.
|
|
72
|
+
* @param {string} resolvedName The full path to the loaded module.
|
|
73
|
+
* @param {string} shimName Used to persist shim ids across different shim instances.
|
|
77
74
|
* @see Shim
|
|
78
75
|
* @see TransactionShim
|
|
79
76
|
*/
|
|
80
|
-
function MessageShim(agent, moduleName, resolvedName) {
|
|
81
|
-
TransactionShim.call(this, agent, moduleName, resolvedName)
|
|
77
|
+
function MessageShim(agent, moduleName, resolvedName, shimName) {
|
|
78
|
+
TransactionShim.call(this, agent, moduleName, resolvedName, shimName)
|
|
82
79
|
this._logger = logger.child({ module: moduleName })
|
|
83
80
|
this._metrics = null
|
|
84
81
|
this._transportType = TransactionShim.TRANSPORT_TYPES.UNKNOWN
|
package/lib/shim/promise-shim.js
CHANGED
|
@@ -22,16 +22,15 @@ class PromiseShim extends Shim {
|
|
|
22
22
|
* Constructs a shim associated with the given agent instance, specialized for
|
|
23
23
|
* instrumenting promise libraries.
|
|
24
24
|
*
|
|
25
|
-
* @param {Agent} agent
|
|
26
|
-
*
|
|
27
|
-
* @param {string}
|
|
28
|
-
*
|
|
29
|
-
* @param
|
|
30
|
-
* The full path to the loaded module.
|
|
25
|
+
* @param {Agent} agent The agent this shim will use.
|
|
26
|
+
* @param {string} moduleName The name of the module being instrumented.
|
|
27
|
+
* @param {string} resolvedName The full path to the loaded module.
|
|
28
|
+
* @param {string} shimName Used to persist shim ids across different shim instances.
|
|
29
|
+
* @param shimName
|
|
31
30
|
* @see Shim
|
|
32
31
|
*/
|
|
33
|
-
constructor(agent, moduleName, resolvedName) {
|
|
34
|
-
super(agent, moduleName, resolvedName)
|
|
32
|
+
constructor(agent, moduleName, resolvedName, shimName) {
|
|
33
|
+
super(agent, moduleName, resolvedName, shimName)
|
|
35
34
|
this._logger = logger.child({ module: moduleName })
|
|
36
35
|
this._class = null
|
|
37
36
|
}
|