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 CHANGED
@@ -1,19 +1,64 @@
1
- ### v9.14.1 (2023-03-23)
2
-
3
- * Restored assigning loaded version of agent to require.cache as `__NR_cache` instead of a symbol to properly detect attempts at loading agent twice.
4
-
5
- ### v9.14.0 (2023-03-23)
6
-
7
- * 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).
8
-
9
- ### v9.13.0 (2023-03-20)
10
-
11
- * 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.
12
-
13
- * 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`.
14
-
15
- * Added default configuration for security agent.
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:
@@ -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.2.0](https://github.com/newrelic/node-test-utilities/tree/v7.2.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-test-utilities/blob/v7.2.0/LICENSE):
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.4](https://github.com/ankitskvmdam/clean-jsdoc-theme/tree/v4.2.4)), distributed under the [MIT License](https://github.com/ankitskvmdam/clean-jsdoc-theme/blob/v4.2.4/LICENSE):
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.0](https://github.com/jsdoc/jsdoc/tree/v4.0.0)), distributed under the [Apache-2.0 License](https://github.com/jsdoc/jsdoc/blob/v4.0.0/LICENSE.md):
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 = Object.assign({}, instrumentationDefinition)
72
-
73
- // Stripping the prefix is necessary because the code downstream gets this url without it
74
- instrumentationDefinitionCopy.moduleName = fileURLToPath(url)
75
-
76
- // Added to keep our Supportability metrics from exploding/including customer info via full filepath
77
- instrumentationDefinitionCopy.specifier = specifier
78
-
79
- shimmer.registerInstrumentation(instrumentationDefinitionCopy)
80
-
81
- logger.debug(
82
- `Registered CommonJS instrumentation for ${specifier} under ${instrumentationDefinitionCopy.moduleName}`
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)
@@ -573,7 +573,7 @@ defaultConfig.definition = () => ({
573
573
  */
574
574
  record_sql: {
575
575
  formatter: allowList.bind(null, ['off', 'obfuscated', 'raw']),
576
- default: 'off',
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
 
@@ -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
- _hostname = os.hostname()
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.wrap(server, 'decorate', wrapDecorate)
23
+ if (!shim.isWrapped(server, 'decorate')) {
24
+ shim.wrap(server, 'decorate', wrapDecorate)
25
+ }
24
26
 
25
- const ret = register.apply(this, arguments)
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.__wrappedPoolConnection = false
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.unwrap(mysql, 'createConnection')
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.unwrap(mysql, 'createPool')
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.unwrap(proto, 'of')
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.unwrap(mysql, 'createPoolCluster')
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.__wrappedPoolConnection) {
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.__wrappedPoolConnection = true
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
- * A helper class for wrapping datastore modules.
78
- * @param {Agent} agent
79
- * The agent this shim will use.
80
- * @param {string} moduleName
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, datastoreId) {
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: opSpec.name || fnName || 'other',
367
- parameters: opSpec.parameters,
368
- callback: opSpec.callback,
369
- after: 'after' in opSpec ? opSpec.after : null,
370
- promise: 'promise' in opSpec ? opSpec.promise : null,
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
- // Mark this as wrapped and put it in the args array.
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 (hasOwnProperty(queryDesc, 'record') && queryDesc.record === false) {
657
- const parameters = _normalizeParameters.call(
658
- shim,
659
- queryDesc.parameters || Object.create(null)
660
- )
654
+ if (queryDesc?.record === false) {
661
655
  return {
662
- name: queryDesc.name || fnName,
663
- parameters,
664
- callback: 'callback' in queryDesc ? queryDesc.callback : null,
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
  }
@@ -66,19 +66,16 @@ const DESTINATION_TYPES = {
66
66
  *
67
67
  * @class
68
68
  * @augments TransactionShim
69
- * @classdesc
70
- * Used for instrumenting message broker client libraries.
71
- * @param {Agent} agent
72
- * The agent this shim will use.
73
- * @param {string} moduleName
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
@@ -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
- * The agent this shim will use.
27
- * @param {string} moduleName
28
- * The name of the module being instrumented.
29
- * @param {string} resolvedName
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
  }