newrelic 11.8.0 → 11.10.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,32 +1,82 @@
1
- ### v11.8.0 (2024-01-03)
1
+ ### v11.10.0 (2024-01-22)
2
2
 
3
3
  #### Features
4
4
 
5
- * Removed `api.setLlmMetadata` ([#1918](https://github.com/newrelic/node-newrelic/pull/1918)) ([cc4a975](https://github.com/newrelic/node-newrelic/commit/cc4a975a3f020648d183ce620e244ba0a09c286d))
6
- * It will be assigned via `api.addCustomAttribute` with a prefix of `llm.` * The conversation_id will now be assigned from `llm.conversation_id` custom attribute
7
- * Updated SQL obfuscation tokenizer to better handle negative numbers and boolean values.
5
+ * Added llm attribute to all transactions that contain llm spans for openai ([#1946](https://github.com/newrelic/node-newrelic/pull/1946)) ([6312629](https://github.com/newrelic/node-newrelic/commit/6312629326c02fe3de4db91ee293eb71b7ddd042))
6
+ * Added transaction ID to ErrorTrace event ([#1954](https://github.com/newrelic/node-newrelic/pull/1954)) ([5d0ebcd](https://github.com/newrelic/node-newrelic/commit/5d0ebcd216cb60b3a488b2b5f7c20f71f8d5bbeb))
8
7
 
9
- #### Bug fixes
8
+ #### Security improvements
10
9
 
11
- * Ensure opts.headers is defined in http instrumentation ([#1926](https://github.com/newrelic/node-newrelic/pull/1926)) ([7ea31a3](https://github.com/newrelic/node-newrelic/commit/7ea31a3c3ff45567cf102da6bbec4b9e68af9602))
10
+ * **remote_method:** Redacted ingest key in trace level logs ([#1948](https://github.com/newrelic/node-newrelic/pull/1948)) ([04fee88](https://github.com/newrelic/node-newrelic/commit/04fee886bd2f479e568830ea03217d7c9aba87d9))
12
11
 
13
12
  #### Code refactoring
14
13
 
15
- * Updated `lib/instrumentation/core/http.js` to reduce the cognitive complexity to an allowable value ([#1922](https://github.com/newrelic/node-newrelic/pull/1922)) ([4c30d97](https://github.com/newrelic/node-newrelic/commit/4c30d977ca74421cfa396c2f86383212e40475e1))
16
- * Updated `lib/shim/promise-shim.js` to reduce the cognitive complexity ([#1924](https://github.com/newrelic/node-newrelic/pull/1924)) ([bd0a5dc](https://github.com/newrelic/node-newrelic/commit/bd0a5dc95c8077794c30c5ebe25f0e153aefb1b4))
17
- * Updated `lib/shim/webframework-shim.js` to reduce the cognitive complexity ([#1927](https://github.com/newrelic/node-newrelic/pull/1927)) ([1ce371e](https://github.com/newrelic/node-newrelic/commit/1ce371e69fd8db7306137c749b9e5486aaacd434))
14
+ * Updated `lib/shim/shim.js` to remove cognitive complexity violations ([#1950](https://github.com/newrelic/node-newrelic/pull/1950)) ([60e57a1](https://github.com/newrelic/node-newrelic/commit/60e57a10f038c1e70dfef2937592983b2bfd5613))
15
+ * Updated message-shim to remove cognitive complexity violations. ([#1958](https://github.com/newrelic/node-newrelic/pull/1958)) ([3d1caaf](https://github.com/newrelic/node-newrelic/commit/3d1caaf7d7f7de1c2e139eb7943f557b896fc1e2))
18
16
 
19
17
  #### Miscellaneous chores
20
18
 
21
- * **deps:** Updated @newrelic/security-agent to v0.6.0 ([#1929](https://github.com/newrelic/node-newrelic/pull/1929)) ([4e09927](https://github.com/newrelic/node-newrelic/commit/4e0992709f8bd07b941a8c7adf0aa51481b0282e))
22
-
23
- #### Tests
24
-
25
- * Refactored tests that were still using the tap mocha shim + chai to now use tap. ([#1919](https://github.com/newrelic/node-newrelic/pull/1919)) ([957529e](https://github.com/newrelic/node-newrelic/commit/957529e901115a16ed31c4663e460e4044d9a09d))
26
- * removed access to deprecated `req._headers` and instead use `req.headers` ([#1923](https://github.com/newrelic/node-newrelic/pull/1923)) ([0ec2f66](https://github.com/newrelic/node-newrelic/commit/0ec2f6669bf90e54af8eddad7b42aa029a7ef517))
27
- * updated the cross agent tests, made updates to tests based on fixture changes ([#1917](https://github.com/newrelic/node-newrelic/pull/1917)) ([2d666b6](https://github.com/newrelic/node-newrelic/commit/2d666b6e47d6ad7ecf14aa832a6ae1fbd15ee973))
28
- * Updated `helper.randomPort` to use `crypto.randomInt` instead of `Math.random` by using crypto lib ([#1921](https://github.com/newrelic/node-newrelic/pull/1921)) ([9003791](https://github.com/newrelic/node-newrelic/commit/9003791e934efb7ab284406735b334bd9ae4872c))
19
+ * **deps:** Updated @newrelic/aws-sdk to latest and removed aws_bedrock_instrumentation feature flag ([#1956](https://github.com/newrelic/node-newrelic/pull/1956)) ([9eae28c](https://github.com/newrelic/node-newrelic/commit/9eae28c7ca06f9287fe09a2d51ad61534d9e8b1d))
20
+ * **deps:** Updated @newrelic/security-agent to v0.7.0 ([#1955](https://github.com/newrelic/node-newrelic/pull/1955)) ([e156539](https://github.com/newrelic/node-newrelic/commit/e15653916f4614e17501202f6831459a8104e7a7))
21
+ * Migrated non-sensitive CI values to vars ([#1957](https://github.com/newrelic/node-newrelic/pull/1957)) ([1739378](https://github.com/newrelic/node-newrelic/commit/17393782a278fd3c3289332c78a88a5d6819be7c))
22
+ * updated contributors list to include james and svetlana 🎉 ([#1947](https://github.com/newrelic/node-newrelic/pull/1947)) ([33a59fd](https://github.com/newrelic/node-newrelic/commit/33a59fdcdeb3e4074b4611d88e2fe79a65168fe3))
29
23
 
24
+ ### v11.9.0 (2024-01-10)
25
+
26
+ #### Features
27
+
28
+ * Assign pkgVersion and id of all child shim instances when using shim.makeSpecializedShim with a ConglomerateShim instance ([#1941](https://github.com/newrelic/node-newrelic/pull/1941)) ([d3e393d](https://github.com/newrelic/node-newrelic/commit/d3e393da4ece46853b01f88878d487a1336634bf))
29
+
30
+ #### Bug fixes
31
+
32
+ * Dropped support for ElasticSearch < 7.16.0 ([#1940](https://github.com/newrelic/node-newrelic/pull/1940)) ([e017768](https://github.com/newrelic/node-newrelic/commit/e017768466c9ca80b16cf1b51155801c3ecf0cc4))
33
+ * Previously, New Relic's Node Agent instrumented ElasticSearch as early as v7.13.0, which was susceptible to crashing when using ElasticSearch's `.helper` API. ElasticSearch [fixed this bug in v7.16.0](https://github.com/elastic/elasticsearch-js/pull/1594), so we now support instrumentation from that version onward, and previous versions are noops.
34
+ * Removed extra / in openai framework metric name ([#1938](https://github.com/newrelic/node-newrelic/pull/1938)) ([7f586c3](https://github.com/newrelic/node-newrelic/commit/7f586c36f6fc119f4dac6e075468d90d43ff07fe))
35
+
36
+ #### Security improvements
37
+
38
+ * **deps:** bump follow-redirects from 1.15.2 to 1.15.4 ([#1942](https://github.com/newrelic/node-newrelic/pull/1942)) ([c1b04b6](https://github.com/newrelic/node-newrelic/commit/c1b04b69ce15173c88517b4baf920546e187ba07))
39
+
40
+ #### Miscellaneous chores
41
+
42
+ * Removed assigning unused metadata to LLM events ([#1932](https://github.com/newrelic/node-newrelic/pull/1932)) ([2f67d49](https://github.com/newrelic/node-newrelic/commit/2f67d496557d6192835e4b4b9cced8b7a2d932c0))
43
+
44
+ #### Tests
45
+
46
+ * Fix DNS lookup in remote-method test ([#1937](https://github.com/newrelic/node-newrelic/pull/1937)) ([4da2149](https://github.com/newrelic/node-newrelic/commit/4da2149f3c48137bc3a5005ff12d29b0c8bee1d7))
47
+ * removed console log ([#1939](https://github.com/newrelic/node-newrelic/pull/1939)) ([7d378aa](https://github.com/newrelic/node-newrelic/commit/7d378aa9ba7b0e529dc0da24b2ee767735631b16))
48
+ * updated abort controller test expected error message based on undici version ([#1935](https://github.com/newrelic/node-newrelic/pull/1935)) ([3e79cc7](https://github.com/newrelic/node-newrelic/commit/3e79cc77c8d10f84de71cf9a20c0c4f0642b7450))
49
+ * updated chat-completions tests to properly assert segments ([#1931](https://github.com/newrelic/node-newrelic/pull/1931)) ([10762a7](https://github.com/newrelic/node-newrelic/commit/10762a7c2c884c459af76d1877cd57641e572678))
50
+
51
+ ### v11.8.0 (2024-01-03)
52
+
53
+ #### Features
54
+
55
+ * Removed `api.setLlmMetadata` ([#1918](https://github.com/newrelic/node-newrelic/pull/1918)) ([cc4a975](https://github.com/newrelic/node-newrelic/commit/cc4a975a3f020648d183ce620e244ba0a09c286d))
56
+ * It will be assigned via `api.addCustomAttribute` with a prefix of `llm.` * The conversation_id will now be assigned from `llm.conversation_id` custom attribute
57
+ * Updated SQL obfuscation tokenizer to better handle negative numbers and boolean values.
58
+
59
+ #### Bug fixes
60
+
61
+ * Ensure opts.headers is defined in http instrumentation ([#1926](https://github.com/newrelic/node-newrelic/pull/1926)) ([7ea31a3](https://github.com/newrelic/node-newrelic/commit/7ea31a3c3ff45567cf102da6bbec4b9e68af9602))
62
+
63
+ #### Code refactoring
64
+
65
+ * Updated `lib/instrumentation/core/http.js` to reduce the cognitive complexity to an allowable value ([#1922](https://github.com/newrelic/node-newrelic/pull/1922)) ([4c30d97](https://github.com/newrelic/node-newrelic/commit/4c30d977ca74421cfa396c2f86383212e40475e1))
66
+ * Updated `lib/shim/promise-shim.js` to reduce the cognitive complexity ([#1924](https://github.com/newrelic/node-newrelic/pull/1924)) ([bd0a5dc](https://github.com/newrelic/node-newrelic/commit/bd0a5dc95c8077794c30c5ebe25f0e153aefb1b4))
67
+ * Updated `lib/shim/webframework-shim.js` to reduce the cognitive complexity ([#1927](https://github.com/newrelic/node-newrelic/pull/1927)) ([1ce371e](https://github.com/newrelic/node-newrelic/commit/1ce371e69fd8db7306137c749b9e5486aaacd434))
68
+
69
+ #### Miscellaneous chores
70
+
71
+ * **deps:** Updated @newrelic/security-agent to v0.6.0 ([#1929](https://github.com/newrelic/node-newrelic/pull/1929)) ([4e09927](https://github.com/newrelic/node-newrelic/commit/4e0992709f8bd07b941a8c7adf0aa51481b0282e))
72
+
73
+ #### Tests
74
+
75
+ * Refactored tests that were still using the tap mocha shim + chai to now use tap. ([#1919](https://github.com/newrelic/node-newrelic/pull/1919)) ([957529e](https://github.com/newrelic/node-newrelic/commit/957529e901115a16ed31c4663e460e4044d9a09d))
76
+ * removed access to deprecated `req._headers` and instead use `req.headers` ([#1923](https://github.com/newrelic/node-newrelic/pull/1923)) ([0ec2f66](https://github.com/newrelic/node-newrelic/commit/0ec2f6669bf90e54af8eddad7b42aa029a7ef517))
77
+ * updated the cross agent tests, made updates to tests based on fixture changes ([#1917](https://github.com/newrelic/node-newrelic/pull/1917)) ([2d666b6](https://github.com/newrelic/node-newrelic/commit/2d666b6e47d6ad7ecf14aa832a6ae1fbd15ee973))
78
+ * Updated `helper.randomPort` to use `crypto.randomInt` instead of `Math.random` by using crypto lib ([#1921](https://github.com/newrelic/node-newrelic/pull/1921)) ([9003791](https://github.com/newrelic/node-newrelic/commit/9003791e934efb7ab284406735b334bd9ae4872c))
79
+
30
80
  ### v11.7.0 (2023-12-14)
31
81
 
32
82
  #### Features
@@ -509,7 +509,7 @@ This product includes source derived from [@grpc/proto-loader](https://github.co
509
509
 
510
510
  ### @newrelic/aws-sdk
511
511
 
512
- This product includes source derived from [@newrelic/aws-sdk](https://github.com/newrelic/node-newrelic-aws-sdk) ([v7.0.3](https://github.com/newrelic/node-newrelic-aws-sdk/tree/v7.0.3)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-aws-sdk/blob/v7.0.3/LICENSE):
512
+ This product includes source derived from [@newrelic/aws-sdk](https://github.com/newrelic/node-newrelic-aws-sdk) ([v7.1.0](https://github.com/newrelic/node-newrelic-aws-sdk/tree/v7.1.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-aws-sdk/blob/v7.1.0/LICENSE):
513
513
 
514
514
  ```
515
515
  Apache License
@@ -926,7 +926,7 @@ Apache License
926
926
 
927
927
  ### @newrelic/security-agent
928
928
 
929
- This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v0.6.0](https://github.com/newrelic/csec-node-agent/tree/v0.6.0)), distributed under the [New Relic Pre-Release License](https://github.com/newrelic/csec-node-agent/blob/v0.6.0/LICENSE):
929
+ This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v0.7.0](https://github.com/newrelic/csec-node-agent/tree/v0.7.0)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v0.7.0/LICENSE):
930
930
 
931
931
  ```
932
932
  ## New Relic Pre-Release Software Notice
@@ -259,15 +259,19 @@ RemoteMethod.prototype._safeRequest = function _safeRequest(options) {
259
259
  level = 'info'
260
260
  }
261
261
 
262
- const logBody = Buffer.isBuffer(options.body) ? 'Buffer ' + options.body.length : options.body
263
- logger[level](
264
- { body: logBody },
265
- 'Posting to %s://%s:%s%s',
266
- protocol,
267
- options.host,
268
- options.port,
269
- options.path
270
- )
262
+ // check if trace is enabled or audit log(aka info in this case) before attemping
263
+ // to get the body length or parse the path with redacted key
264
+ if (logger.traceEnabled() || level === 'info') {
265
+ const logBody = Buffer.isBuffer(options.body) ? 'Buffer ' + options.body.length : options.body
266
+ logger[level](
267
+ { body: logBody },
268
+ 'Posting to %s://%s:%s%s',
269
+ protocol,
270
+ options.host,
271
+ options.port,
272
+ this._path({ redactLicenseKey: true })
273
+ )
274
+ }
271
275
 
272
276
  this._request(options)
273
277
  }
@@ -336,13 +340,14 @@ RemoteMethod.prototype._userAgent = function _userAgent() {
336
340
  /**
337
341
  * Generate a URL the collector understands.
338
342
  *
343
+ * @param {boolean} redactLicenseKey flag to redact license key in path
339
344
  * @returns {string} The URL path to be POSTed to.
340
345
  */
341
- RemoteMethod.prototype._path = function _path() {
346
+ RemoteMethod.prototype._path = function _path({ redactLicenseKey } = {}) {
342
347
  const query = {
343
348
  marshal_format: 'json',
344
349
  protocol_version: this._protocolVersion,
345
- license_key: this._config.license_key,
350
+ license_key: redactLicenseKey ? 'REDACTED' : this._config.license_key,
346
351
  method: this.name
347
352
  }
348
353
 
@@ -67,7 +67,8 @@ class Exception {
67
67
  * [1] -> name extracted from error info,
68
68
  * [2] -> extracted error message,
69
69
  * [3] -> extracted error type,
70
- * [4] -> attributes
70
+ * [4] -> attributes,
71
+ * [5] -> transaction id
71
72
  */
72
73
  function createError(transaction, exception, config) {
73
74
  const error = exception.error
@@ -111,7 +112,7 @@ function createError(transaction, exception, config) {
111
112
 
112
113
  maybeAddAgentAttributes(params, exception)
113
114
 
114
- return [0, name, message, type, params]
115
+ return [0, name, message, type, params, transaction?.id]
115
116
  }
116
117
 
117
118
  function isValidErrorGroupOutput(output) {
@@ -12,8 +12,7 @@ exports.prerelease = {
12
12
  reverse_naming_rules: false,
13
13
  undici_async_tracking: true,
14
14
  unresolved_promise_cleanup: true,
15
- legacy_context_manager: false,
16
- aws_bedrock_instrumentation: false
15
+ legacy_context_manager: false
17
16
  }
18
17
 
19
18
  // flags that are no longer used for released features
@@ -34,7 +33,8 @@ exports.released = [
34
33
  'await_support',
35
34
  'certificate_bundle',
36
35
  'async_local_context',
37
- 'undici_instrumentation'
36
+ 'undici_instrumentation',
37
+ 'aws_bedrock_instrumentation'
38
38
  ]
39
39
 
40
40
  // flags that are no longer used for unreleased features
@@ -20,10 +20,10 @@ const { isNotEmpty } = require('../../util/objects')
20
20
  */
21
21
  module.exports = function initialize(_agent, elastic, _moduleName, shim) {
22
22
  const pkgVersion = shim.pkgVersion
23
- if (semver.lt(pkgVersion, '7.13.0')) {
23
+ if (semver.lt(pkgVersion, '7.16.0')) {
24
24
  shim &&
25
25
  shim.logger.debug(
26
- `ElasticSearch support is for versions 7.13.0 and above. Not instrumenting ${pkgVersion}.`
26
+ `ElasticSearch support is for versions 7.16.0 and above. Not instrumenting ${pkgVersion}.`
27
27
  )
28
28
  return
29
29
  }
@@ -70,6 +70,7 @@ function queryParser(params) {
70
70
  } else if (Array.isArray(params.bulkBody) && params.bulkBody.length) {
71
71
  queryParam = params.bulkBody
72
72
  }
73
+ // The helper interface provides a simpler API:
73
74
 
74
75
  const query = JSON.stringify(queryParam)
75
76
 
@@ -19,6 +19,7 @@ const {
19
19
  AI: { OPENAI }
20
20
  } = require('../../lib/metrics/names')
21
21
  const semver = require('semver')
22
+ const { DESTINATIONS } = require('../config/attribute-filter')
22
23
 
23
24
  let TRACKING_METRIC = OPENAI.TRACKING_PREFIX
24
25
 
@@ -76,7 +77,6 @@ function decorateSegment({ shim, result, apiKey }) {
76
77
  */
77
78
  function recordEvent({ agent, type, msg }) {
78
79
  agent.metrics.getOrCreateMetric(TRACKING_METRIC).incrementCallCount()
79
- msg = agent?.llm?.metadata ? { ...agent.llm.metadata, ...msg } : msg
80
80
  agent.customEventAggregator.add([{ type, timestamp: Date.now() }, msg])
81
81
  }
82
82
 
@@ -283,6 +283,8 @@ module.exports = function initialize(agent, openai, moduleName, shim) {
283
283
  err
284
284
  })
285
285
  }
286
+
287
+ segment.transaction.trace.attributes.addAttribute(DESTINATIONS.TRANS_EVENT, 'llm', true)
286
288
  }
287
289
  }
288
290
  }
@@ -302,6 +304,8 @@ module.exports = function initialize(agent, openai, moduleName, shim) {
302
304
  promise: true,
303
305
  // eslint-disable-next-line max-params
304
306
  after(_shim, _fn, _name, err, response, segment) {
307
+ segment.transaction.trace.attributes.addAttribute(DESTINATIONS.TRANS_EVENT, 'llm', true)
308
+
305
309
  if (!response) {
306
310
  // If we get an error, it is possible that `response = null`.
307
311
  // In that case, we define it to be an empty object.
@@ -165,7 +165,7 @@ const EXPRESS = {
165
165
  }
166
166
 
167
167
  const AI = {
168
- TRACKING_PREFIX: 'Nodejs/ML/',
168
+ TRACKING_PREFIX: 'Nodejs/ML',
169
169
  EMBEDDING: 'Llm/embedding',
170
170
  COMPLETION: 'Llm/completion'
171
171
  }
@@ -65,7 +65,15 @@ class ConglomerateShim extends Shim {
65
65
  */
66
66
  makeSpecializedShim(type, submodule) {
67
67
  const ShimClass = SHIM_CLASSES[type]
68
- const shim = new ShimClass(this.agent, this.moduleName, this._resolvedName)
68
+ const shim = new ShimClass(
69
+ this.agent,
70
+ this.moduleName,
71
+ this._resolvedName,
72
+ null,
73
+ this.pkgVersion
74
+ )
75
+ // associate the parent shim.id with the new submodule
76
+ shim.id = this.id
69
77
  shim._logger = shim._logger.child({ submodule })
70
78
  return shim
71
79
  }
@@ -0,0 +1,34 @@
1
+ /*
2
+ * Copyright 2024 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const common = module.exports
8
+
9
+ /**
10
+ * Constructs a message segment name from the given message descriptor.
11
+ *
12
+ * @private
13
+ * @param {MessageShim} shim The shim the segment will be constructed by.
14
+ * @param {object} msgDesc The message descriptor.
15
+ * @param {string} action Produce or consume?
16
+ * @returns {string} The generated name of the message segment.
17
+ */
18
+ common._nameMessageSegment = function _nameMessageSegment(shim, msgDesc, action) {
19
+ let name =
20
+ shim._metrics.PREFIX +
21
+ shim._metrics.LIBRARY +
22
+ '/' +
23
+ (msgDesc.destinationType || shim.EXCHANGE) +
24
+ '/' +
25
+ action
26
+
27
+ if (msgDesc.destinationName) {
28
+ name += shim._metrics.NAMED + msgDesc.destinationName
29
+ } else {
30
+ name += shim._metrics.TEMP
31
+ }
32
+
33
+ return name
34
+ }
@@ -0,0 +1,167 @@
1
+ /*
2
+ * Copyright 2024 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const TraceSegment = require('../../transaction/trace/segment')
8
+ const genericRecorder = require('../../metrics/recorders/generic')
9
+ const { _nameMessageSegment } = require('./common')
10
+ const specs = require('../specs')
11
+ module.exports = createRecorder
12
+
13
+ /**
14
+ * Generates the spec for the consumer
15
+ *
16
+ * @private
17
+ * @param {object} params to function
18
+ * @param {MessageShim} params.shim instance of shim
19
+ * @param {Function} params.fn consumer function
20
+ * @param {string} params.fnName name of function
21
+ * @param {Array} params.args arguments passed to original consume function
22
+ * @param {specs.MessageSpec} params.spec spec for the wrapped consume function
23
+ * @returns {specs.MessageSpec} new spec
24
+ */
25
+ function updateSpecFromArgs({ shim, fn, fnName, args, spec }) {
26
+ let msgDesc = null
27
+ if (shim.isFunction(spec)) {
28
+ msgDesc = spec.call(this, shim, fn, fnName, args)
29
+ msgDesc = new specs.MessageSpec(msgDesc)
30
+ } else {
31
+ msgDesc = new specs.MessageSpec(spec)
32
+ const destIdx = shim.normalizeIndex(args.length, spec.destinationName)
33
+ if (destIdx !== null) {
34
+ msgDesc.destinationName = args[destIdx]
35
+ }
36
+ }
37
+
38
+ return msgDesc
39
+ }
40
+
41
+ /**
42
+ * Binds the consumer callback to the active segment.
43
+ *
44
+ * @private
45
+ * @param {object} params to function
46
+ * @param {MessageShim} params.shim instance of shim
47
+ * @param {Array} params.args arguments passed to original consume function
48
+ * @param {specs.MessageSpec} params.msgDesc spec for the wrapped consume function
49
+ * @param {TraceSegment} params.segment active segment to bind callback
50
+ * @param {boolean} params.getParams flag to copy message parameters to segment
51
+ * @param {Function} params.resHandler function to handle response from callback to obtain the message parameters
52
+ */
53
+ function bindCallback({ shim, args, msgDesc, segment, getParams, resHandler }) {
54
+ const cbIdx = shim.normalizeIndex(args.length, msgDesc.callback)
55
+ if (cbIdx !== null) {
56
+ shim.bindCallbackSegment(args, cbIdx, segment)
57
+
58
+ // If we have a callback and a results handler, then wrap the callback so
59
+ // we can call the results handler and get the message properties.
60
+ if (resHandler) {
61
+ shim.wrap(args, cbIdx, function wrapCb(shim, cb, cbName) {
62
+ if (shim.isFunction(cb)) {
63
+ return function cbWrapper() {
64
+ const cbArgs = shim.argsToArray.apply(shim, arguments)
65
+ const msgProps = resHandler.call(this, shim, cb, cbName, cbArgs)
66
+ if (getParams && msgProps && msgProps.parameters) {
67
+ shim.copySegmentParameters(segment, msgProps.parameters)
68
+ }
69
+
70
+ return cb.apply(this, arguments)
71
+ }
72
+ }
73
+ })
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Binds the consumer function to the async context and checks return to possibly
80
+ * bind the promise
81
+ *
82
+ * @private
83
+ * @param {object} params to function
84
+ * @param {MessageShim} params.shim instance of shim
85
+ * @param {Function} params.fn consumer function
86
+ * @param {string} params.fnName name of function
87
+ * @param {Array} params.args arguments passed to original consume function
88
+ * @param {specs.MessageSpec} params.msgDesc spec for the wrapped consume function
89
+ * @param {TraceSegment} params.segment active segment to bind callback
90
+ * @param {boolean} params.getParams flag to copy message parameters to segment
91
+ * @param {Function} params.resHandler function to handle response from callback to obtain the message parameters
92
+ * @returns {Promise|*} response from consume function
93
+ */
94
+ function bindConsumer({ shim, fn, fnName, args, msgDesc, segment, getParams, resHandler }) {
95
+ // Call the method in the context of our segment.
96
+ let ret = shim.applySegment(fn, segment, true, this, args)
97
+
98
+ if (ret && msgDesc.promise && shim.isPromise(ret)) {
99
+ ret = shim.bindPromise(ret, segment)
100
+
101
+ // Intercept the promise to handle the result.
102
+ if (resHandler) {
103
+ ret = ret.then(function interceptValue(res) {
104
+ const msgProps = resHandler.call(this, shim, fn, fnName, res)
105
+ if (getParams && msgProps && msgProps.parameters) {
106
+ shim.copySegmentParameters(segment, msgProps.parameters)
107
+ }
108
+ return res
109
+ })
110
+ }
111
+ }
112
+
113
+ return ret
114
+ }
115
+
116
+ /**
117
+ *
118
+ * @private
119
+ * @param {object} params to function
120
+ * @param {MessageShim} params.shim instance of shim
121
+ * @param {Function} params.fn function that is being wrapped
122
+ * @param {string} params.fnName name of function
123
+ * @param {specs.MessageSpec} params.spec spec for the wrapped consume function
124
+ * @returns {Function} recorder for consume function
125
+ */
126
+ function createRecorder({ shim, fn, fnName, spec }) {
127
+ return function consumeRecorder() {
128
+ const parent = shim.getSegment()
129
+ if (!parent || !parent.transaction.isActive()) {
130
+ shim.logger.trace('Not recording consume, no active transaction.')
131
+ return fn.apply(this, arguments)
132
+ }
133
+
134
+ // Process the message args.
135
+ const args = shim.argsToArray.apply(shim, arguments)
136
+ const msgDesc = updateSpecFromArgs.call(this, { shim, fn, fnName, args, spec })
137
+
138
+ // Make the segment if we can.
139
+ if (!msgDesc) {
140
+ shim.logger.trace('Not recording consume, no message descriptor.')
141
+ return fn.apply(this, args)
142
+ }
143
+
144
+ const name = _nameMessageSegment(shim, msgDesc, shim._metrics.CONSUME)
145
+
146
+ // Adds details needed by createSegment when used with a spec
147
+ msgDesc.name = name
148
+ msgDesc.recorder = genericRecorder
149
+ msgDesc.parent = parent
150
+
151
+ const segment = shim.createSegment(msgDesc)
152
+ const getParams = shim.agent.config.message_tracer.segment_parameters.enabled
153
+ const resHandler = shim.isFunction(msgDesc.messageHandler) ? msgDesc.messageHandler : null
154
+
155
+ bindCallback({ shim, args, msgDesc, segment, getParams, resHandler })
156
+ return bindConsumer.call(this, {
157
+ shim,
158
+ fn,
159
+ fnName,
160
+ args,
161
+ msgDesc,
162
+ segment,
163
+ getParams,
164
+ resHandler
165
+ })
166
+ }
167
+ }