newrelic 13.5.0 → 13.6.1

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.
Files changed (100) hide show
  1. package/NEWS.md +51 -0
  2. package/api.js +3 -3
  3. package/lib/agent.js +2 -2
  4. package/lib/aggregators/log-aggregator.js +2 -2
  5. package/lib/collector/api.js +6 -6
  6. package/lib/collector/remote-method.js +1 -1
  7. package/lib/config/attribute-filter.js +7 -7
  8. package/lib/config/default.js +5 -5
  9. package/lib/config/hsm.js +1 -1
  10. package/lib/config/index.js +28 -26
  11. package/lib/config/merge-server-config.js +6 -6
  12. package/lib/core-instrumentation.js +4 -0
  13. package/lib/db/query-parsers/elasticsearch.js +5 -4
  14. package/lib/db/query-parsers/sql.js +1 -1
  15. package/lib/environment.js +16 -16
  16. package/lib/errors/index.js +1 -1
  17. package/lib/harvester.js +7 -5
  18. package/lib/header-attributes.js +3 -3
  19. package/lib/instrumentation/@google/genai.js +6 -9
  20. package/lib/instrumentation/aws-sdk/v3/bedrock.js +11 -9
  21. package/lib/instrumentation/bunyan.js +1 -5
  22. package/lib/instrumentation/core/child_process.js +4 -4
  23. package/lib/instrumentation/core/fs.js +2 -2
  24. package/lib/instrumentation/core/http2.js +266 -0
  25. package/lib/instrumentation/core/timers.js +4 -4
  26. package/lib/instrumentation/fastify.js +1 -1
  27. package/lib/instrumentation/grpc-js/grpc.js +7 -7
  28. package/lib/instrumentation/koa/route-instrumentation.js +16 -18
  29. package/lib/instrumentation/langchain/runnable.js +2 -2
  30. package/lib/instrumentation/langchain/vectorstore.js +3 -2
  31. package/lib/instrumentation/when/index.js +5 -5
  32. package/lib/instrumentation/winston.js +1 -1
  33. package/lib/instrumentation-tracker.js +2 -2
  34. package/lib/instrumentations.js +0 -1
  35. package/lib/llm-events/aws-bedrock/bedrock-response.js +9 -0
  36. package/lib/llm-events/aws-bedrock/chat-completion-message.js +32 -4
  37. package/lib/llm-events/aws-bedrock/chat-completion-summary.js +30 -1
  38. package/lib/llm-events/aws-bedrock/embedding.js +37 -4
  39. package/lib/llm-events/aws-bedrock/stream-handler.js +22 -0
  40. package/lib/llm-events/aws-bedrock/utils.js +59 -1
  41. package/lib/llm-events/google-genai/chat-completion-message.js +33 -5
  42. package/lib/llm-events/google-genai/chat-completion-summary.js +33 -0
  43. package/lib/llm-events/google-genai/embedding.js +34 -4
  44. package/lib/llm-events/google-genai/utils.js +32 -0
  45. package/lib/llm-events/openai/chat-completion-message.js +33 -6
  46. package/lib/llm-events/openai/chat-completion-summary.js +36 -0
  47. package/lib/llm-events/openai/embedding.js +34 -4
  48. package/lib/llm-events/openai/utils.js +34 -0
  49. package/lib/llm-events/utils.js +110 -0
  50. package/lib/metrics/index.js +7 -7
  51. package/lib/metrics/normalizer/tx_segment.js +26 -28
  52. package/lib/metrics/normalizer.js +9 -7
  53. package/lib/metrics/recorders/distributed-trace.js +2 -2
  54. package/lib/otel/traces/rules.js +2 -2
  55. package/lib/serverless/aws-lambda.js +7 -7
  56. package/lib/shim/datastore-shim.js +8 -8
  57. package/lib/shim/message-shim/index.js +8 -8
  58. package/lib/shim/message-shim/subscribe-consume.js +12 -10
  59. package/lib/shim/promise-shim.js +3 -3
  60. package/lib/shim/shim.js +11 -9
  61. package/lib/shim/transaction-shim.js +7 -7
  62. package/lib/shim/webframework-shim/index.js +8 -9
  63. package/lib/shimmer.js +19 -26
  64. package/lib/stats/apdex.js +1 -1
  65. package/lib/subscriber-configs.js +1 -0
  66. package/lib/subscribers/dc-base.js +6 -4
  67. package/lib/subscribers/express/config.js +102 -0
  68. package/lib/subscribers/express/param.js +22 -0
  69. package/lib/subscribers/express/render.js +28 -0
  70. package/lib/subscribers/express/route.js +55 -0
  71. package/lib/subscribers/express/router-param.js +24 -0
  72. package/lib/subscribers/express/router-route.js +24 -0
  73. package/lib/subscribers/express/router-use.js +24 -0
  74. package/lib/subscribers/express/use.js +46 -0
  75. package/lib/subscribers/fastify/add-hook.js +5 -6
  76. package/lib/subscribers/fastify/decorate.js +6 -8
  77. package/lib/subscribers/fastify/index.js +3 -2
  78. package/lib/subscribers/ioredis/config.js +3 -3
  79. package/lib/subscribers/ioredis/index.js +24 -1
  80. package/lib/subscribers/middleware-wrapper.js +278 -0
  81. package/lib/subscribers/middleware.js +20 -0
  82. package/lib/subscribers/openai/base.js +5 -6
  83. package/lib/subscribers/openai/utils.js +5 -4
  84. package/lib/system-metrics-sampler.js +5 -5
  85. package/lib/transaction/index.js +7 -7
  86. package/lib/transaction/name-state.js +4 -4
  87. package/lib/transaction/trace/aggregator.js +1 -1
  88. package/lib/transaction/trace/index.js +3 -1
  89. package/lib/transaction/trace/segment.js +2 -2
  90. package/lib/uninstrumented.js +4 -4
  91. package/lib/util/hashes.js +4 -4
  92. package/lib/util/label-parser.js +7 -7
  93. package/lib/util/logger.js +3 -3
  94. package/lib/util/process-version.js +1 -1
  95. package/lib/utilization/docker-info.js +1 -1
  96. package/lib/utilization/index.js +2 -2
  97. package/newrelic.js +1 -1
  98. package/package.json +1 -1
  99. package/lib/instrumentation/express.js +0 -176
  100. package/lib/subscribers/fastify/common.js +0 -121
package/NEWS.md CHANGED
@@ -1,3 +1,50 @@
1
+ ### v13.6.1 (2025-10-28)
2
+
3
+ #### Bug fixes
4
+
5
+ * Updated middleware wrapper to not wrap handler if it is not a function ([#3469](https://github.com/newrelic/node-newrelic/pull/3469)) ([c702689](https://github.com/newrelic/node-newrelic/commit/c702689a6e73756f6b3ad39706a33874fbd6da73))
6
+
7
+ #### Documentation
8
+
9
+ * Updated compatibility report ([#3466](https://github.com/newrelic/node-newrelic/pull/3466)) ([5853657](https://github.com/newrelic/node-newrelic/commit/5853657a63dc75481fc6598c10afd208391f525b))
10
+
11
+ ### v13.6.0 (2025-10-27)
12
+
13
+ #### Features
14
+
15
+ * Added instrumentation for http2 client methods ([#3284](https://github.com/newrelic/node-newrelic/pull/3284)) ([bda7aea](https://github.com/newrelic/node-newrelic/commit/bda7aeaac16ce9f54bd28de72aa7465be96cd157))
16
+
17
+ #### Bug fixes
18
+
19
+ * Updated `ioredis` instrumentation to handle breakage of errors when using `.pipeline`. ([#3457](https://github.com/newrelic/node-newrelic/pull/3457)) ([49f4d93](https://github.com/newrelic/node-newrelic/commit/49f4d93a59045f35406dfdbd3248dca0652727d6))
20
+ * Updated `openai` `instrumentStream` function to handle empty chunk when `include_usage` is set ([#3427](https://github.com/newrelic/node-newrelic/pull/3427)) ([f804940](https://github.com/newrelic/node-newrelic/commit/f8049405003f0811450f75468e0bddfb1f05ec2b))
21
+
22
+ #### Code refactoring
23
+
24
+ * Update `express` instrumentation to subscribe to events emitted ([#3424](https://github.com/newrelic/node-newrelic/pull/3424)) ([bbf3d01](https://github.com/newrelic/node-newrelic/commit/bbf3d010bc402953e53cae5200af6bfb55a6446d))
25
+ * Updated instances in instrumentation of `Array.forEach` for a more performant for...of or for index loop ([#3463](https://github.com/newrelic/node-newrelic/pull/3463)) ([99484ce](https://github.com/newrelic/node-newrelic/commit/99484ce0e7a963fbbc3cbc22f4956ce19e5eecc2))
26
+ * Updated instances of `Array.forEach` for a more performant for...of or for index loop ([#3440](https://github.com/newrelic/node-newrelic/pull/3440)) ([48c37bf](https://github.com/newrelic/node-newrelic/commit/48c37bf7f85291553666d4512ca995b6a5b136a2))
27
+ * Updated token calculation for `aws-bedrock` LLM Events ([#3445](https://github.com/newrelic/node-newrelic/pull/3445)) ([9450181](https://github.com/newrelic/node-newrelic/commit/945018171da713487a0b5b674e68bdbb211e655e))
28
+ * Updated token calculation for `google-genai` LLM Events ([#3431](https://github.com/newrelic/node-newrelic/pull/3431)) ([41d32be](https://github.com/newrelic/node-newrelic/commit/41d32befe1d9c3201b62253a5de76c918d98a025))
29
+ * Updated token calculation for `openai` LLM Events ([#3430](https://github.com/newrelic/node-newrelic/pull/3430)) ([b8678cc](https://github.com/newrelic/node-newrelic/commit/b8678cc92bb986eae7efec4b516f66406307e841))
30
+
31
+ #### Documentation
32
+
33
+ * Updated compatibility report ([#3459](https://github.com/newrelic/node-newrelic/pull/3459)) ([f253b97](https://github.com/newrelic/node-newrelic/commit/f253b97c039caa9e9110055d93e0c32e2d6911a8))
34
+
35
+ #### Miscellaneous chores
36
+
37
+ * Update release workflows ([#3444](https://github.com/newrelic/node-newrelic/pull/3444)) ([d1ec158](https://github.com/newrelic/node-newrelic/commit/d1ec158f46d034160b665f8b0785c020ba39b820))
38
+
39
+ #### Tests
40
+
41
+ * Added a `randomString` helper to agent_helper and use it in ioredis to avoid flappy tests, also updated local instances of random strings in kafka, elasticsearch and opensearch tests ([#3462](https://github.com/newrelic/node-newrelic/pull/3462)) ([4deb6d8](https://github.com/newrelic/node-newrelic/commit/4deb6d80d9daa7fd9d4c077a5cc52f358ed44e61))
42
+ * Fixed conflict between ioredis and ioredis-esm by running `flushdb` instead of `flushall` to avoid index getting removed mid test ([#3464](https://github.com/newrelic/node-newrelic/pull/3464)) ([5e3f0a8](https://github.com/newrelic/node-newrelic/commit/5e3f0a81bfcf8bc8cf04559f29d3a76c1262bcc7))
43
+ * Fixed express async error test to purposely misspell a method to emit a crash ([#3435](https://github.com/newrelic/node-newrelic/pull/3435)) ([ff9f064](https://github.com/newrelic/node-newrelic/commit/ff9f0646c4fc23e367c1e190eb8091423c690103))
44
+ * Moved aws-sdk-v3 common.js requirement of semver ([#3461](https://github.com/newrelic/node-newrelic/pull/3461)) ([6a380ef](https://github.com/newrelic/node-newrelic/commit/6a380ef580268be131417587a2dda5adf3545e68))
45
+ * Pinned Next.js tests to <16.0.0 ([#3446](https://github.com/newrelic/node-newrelic/pull/3446)) ([10787a1](https://github.com/newrelic/node-newrelic/commit/10787a1f4e325b7321173ee5b2fab0809af5e8d1))
46
+ * Updated minimum tested version of `@langchain/core` to 1.0.0 ([#3437](https://github.com/newrelic/node-newrelic/pull/3437)) ([b61f67a](https://github.com/newrelic/node-newrelic/commit/b61f67a4c6d59f0b2a49e0de93a6d38e56d214fd))
47
+
1
48
  ### v13.5.0 (2025-10-14)
2
49
 
3
50
  #### Code refactoring
@@ -7960,3 +8007,7 @@ Special thanks to Ryan Copley (@RyanCopley) for the contribution.
7960
8007
 
7961
8008
 
7962
8009
 
8010
+
8011
+
8012
+
8013
+
package/api.js CHANGED
@@ -1813,16 +1813,16 @@ API.prototype.setUserID = function setUserID(id) {
1813
1813
  */
1814
1814
  function _filterAttributes(attributes, name) {
1815
1815
  const filteredAttributes = Object.create(null)
1816
- Object.keys(attributes).forEach((attributeKey) => {
1816
+ for (const attributeKey of Object.keys(attributes)) {
1817
1817
  if (!isValidType(attributes[attributeKey])) {
1818
1818
  logger.info(
1819
1819
  `Omitting attribute ${attributeKey} from ${name} call, type must ` +
1820
1820
  'be boolean, number, or string'
1821
1821
  )
1822
- return
1822
+ continue
1823
1823
  }
1824
1824
  filteredAttributes[attributeKey] = attributes[attributeKey]
1825
- })
1825
+ }
1826
1826
  return filteredAttributes
1827
1827
  }
1828
1828
 
package/lib/agent.js CHANGED
@@ -444,7 +444,7 @@ Agent.prototype._scheduleHarvests = function _scheduleHarvests(shouldImmediately
444
444
 
445
445
  const agent = this
446
446
 
447
- // For data collection that streams immediately, dont delay capture/sending until
447
+ // For data collection that streams immediately, don't delay capture/sending until
448
448
  // the harvest of everything else has completed.
449
449
  agent.startStreaming()
450
450
 
@@ -564,7 +564,7 @@ Agent.prototype._resetCustomEvents = function resetCustomEvents() {
564
564
  * @fires Agent#harvestFinished
565
565
  */
566
566
  Agent.prototype.harvestSync = function harvestSync() {
567
- logger.trace('Peparing to harvest.')
567
+ logger.trace('Preparing to harvest.')
568
568
 
569
569
  if (!this.collector.isConnected()) {
570
570
  throw new Error('Sync harvest not connected/enabled!')
@@ -81,9 +81,9 @@ class LogAggregator extends EventAggregator {
81
81
  }
82
82
 
83
83
  addBatch(logs, priority) {
84
- logs.forEach((logLine) => {
84
+ for (const logLine of logs) {
85
85
  super.add(logLine, priority)
86
- })
86
+ }
87
87
  }
88
88
 
89
89
  reconfigure(config) {
@@ -63,15 +63,15 @@ const AGENT_RUN_BEHAVIOR = CollectorResponse.AGENT_RUN_BEHAVIOR
63
63
  function dumpErrors(errors, name) {
64
64
  let index = 1
65
65
 
66
- errors.forEach(function forEachError(error) {
66
+ for (const error of errors) {
67
67
  logger.trace(error, 'Error %s during %s:', index++, name)
68
68
 
69
69
  if (error.laterErrors) {
70
- error.laterErrors.forEach(function forEachLaterError(laterError) {
70
+ for (const laterError of error.laterErrors) {
71
71
  logger.trace(laterError, 'Error %s during %s:', index++, name)
72
- })
72
+ }
73
73
  }
74
- })
74
+ }
75
75
  }
76
76
 
77
77
  /**
@@ -421,9 +421,9 @@ CollectorAPI.prototype._onConnect = function _onConnect(callback, error, res) {
421
421
 
422
422
  // Log "Reporting to..." message from connect response.
423
423
  if (config.messages) {
424
- config.messages.forEach((element) => {
424
+ for (const element of config.messages) {
425
425
  logger.info(element.message)
426
- })
426
+ }
427
427
  }
428
428
 
429
429
  // Store request headers for future collector requests if they're present
@@ -260,7 +260,7 @@ RemoteMethod.prototype._safeRequest = function _safeRequest(options) {
260
260
  level = 'info'
261
261
  }
262
262
 
263
- // check if trace is enabled or audit log(aka info in this case) before attemping
263
+ // check if trace is enabled or audit log(aka info in this case) before attempting
264
264
  // to get the body length or parse the path with redacted key
265
265
  if (logger.traceEnabled() || level === 'info') {
266
266
  const logBody = Buffer.isBuffer(options.body) ? 'Buffer ' + options.body.length : options.body
@@ -70,12 +70,12 @@ function AttributeFilter(config) {
70
70
  this._rules.global = Object.create(null)
71
71
 
72
72
  // And all the destination rules.
73
- DESTINATION_DETAILS.forEach(function forEachDestination(dest) {
73
+ for (const dest of DESTINATION_DETAILS) {
74
74
  config.on(dest.name + '.attributes.enabled', updater)
75
75
  config.on(dest.name + '.attributes.include', updater)
76
76
  config.on(dest.name + '.attributes.exclude', updater)
77
77
  this._rules[dest.name] = Object.create(null)
78
- }, this)
78
+ }
79
79
 
80
80
  // Now pull in all the rules.
81
81
  this.update()
@@ -184,10 +184,10 @@ AttributeFilter.prototype.update = function update() {
184
184
  this._cachedCount = 0
185
185
 
186
186
  // And all the destination rules.
187
- DESTINATION_DETAILS.forEach(function forEachDestination(dest) {
187
+ for (const dest of DESTINATION_DETAILS) {
188
188
  const name = dest.name
189
189
  if (!this.config[name].attributes.enabled) {
190
- return
190
+ continue
191
191
  }
192
192
 
193
193
  this._enabledDestinations |= dest.id
@@ -196,7 +196,7 @@ AttributeFilter.prototype.update = function update() {
196
196
  )
197
197
  this._rules[name].exclude = _importRules(this.config[name].attributes.exclude)
198
198
  this._cache[name] = Object.create(null)
199
- }, this)
199
+ }
200
200
  }
201
201
 
202
202
  /**
@@ -291,13 +291,13 @@ function _importRules(rules) {
291
291
  }
292
292
  const exactRules = []
293
293
  const wildcardRules = []
294
- rules.forEach(function separateRules(rule) {
294
+ for (const rule of rules) {
295
295
  if (rule[rule.length - 1] === '*') {
296
296
  wildcardRules.push(rule)
297
297
  } else {
298
298
  exactRules.push(rule)
299
299
  }
300
- })
300
+ }
301
301
 
302
302
  if (exactRules.length) {
303
303
  out.exact = new RegExp('^' + _convertRulesToRegex(exactRules) + '$')
@@ -323,7 +323,7 @@ defaultConfig.definition = () => {
323
323
  */
324
324
  diagnostics: {
325
325
  formatter: boolean,
326
- deafult: false
326
+ default: false
327
327
  }
328
328
  },
329
329
  audit_log: {
@@ -1145,7 +1145,7 @@ defaultConfig.definition = () => {
1145
1145
  /**
1146
1146
  * Controls whether the agent will generate spans for in-process actions.
1147
1147
  * When disabled, this will only create spans for entry and exit spans.
1148
- * entry spans - initial actions for web servers and messsage queue consumption.
1148
+ * entry spans - initial actions for web servers and message queue consumption.
1149
1149
  * exit spans - all outgoing calls to external services(external and database calls)
1150
1150
  */
1151
1151
  in_process_spans: {
@@ -1399,7 +1399,7 @@ defaultConfig.definition = () => {
1399
1399
  /**
1400
1400
  * Obfuscates URL parameters
1401
1401
  * for outgoing and incoming requests
1402
- * for distrubuted tracing attributes - both transaction and span attributes
1402
+ * for distributed tracing attributes - both transaction and span attributes
1403
1403
  * for transaction trace transaction details
1404
1404
  */
1405
1405
  url_obfuscation: {
@@ -1429,7 +1429,7 @@ defaultConfig.definition = () => {
1429
1429
 
1430
1430
  /**
1431
1431
  * A string containing a replacement value for URL parameters
1432
- * can contain refferences to capture groups in the pattern
1432
+ * can contain references to capture groups in the pattern
1433
1433
  */
1434
1434
  replacement: {
1435
1435
  default: ''
@@ -1499,7 +1499,7 @@ defaultConfig.definition = () => {
1499
1499
  },
1500
1500
 
1501
1501
  /**
1502
- * Unique test identifier when runnning IAST with CI/CD
1502
+ * Unique test identifier when running IAST with CI/CD
1503
1503
  */
1504
1504
  iast_test_identifier: '',
1505
1505
 
package/lib/config/hsm.js CHANGED
@@ -71,7 +71,7 @@ const REDACT_BEFORE_SEND = new Set([
71
71
  'certificates' // should be public but in case user mistake and also these are huge
72
72
  ])
73
73
 
74
- // process.domain needs to be stripped befeore sending
74
+ // process.domain needs to be stripped before sending
75
75
  const REMOVE_BEFORE_SEND = new Set(['domain'])
76
76
 
77
77
  exports.HIGH_SECURITY_SETTINGS = HIGH_SECURITY_SETTINGS
@@ -277,9 +277,9 @@ Config.prototype.onConnect = function onConnect(json, recursion) {
277
277
  return
278
278
  }
279
279
 
280
- Object.keys(json).forEach(function updateProp(key) {
280
+ for (const key of Object.keys(json)) {
281
281
  this._fromServer(json, key)
282
- }, this)
282
+ }
283
283
 
284
284
  this._warnDeprecations()
285
285
 
@@ -652,11 +652,11 @@ Config.prototype._alwaysUpdateIfChanged = function _alwaysUpdateIfChanged(json,
652
652
  const value = json[key]
653
653
  if (value != null && this[key] !== value) {
654
654
  if (Array.isArray(value) && Array.isArray(this[key])) {
655
- value.forEach(function pushIfNew(element) {
655
+ for (const element of value) {
656
656
  if (this[key].indexOf(element) === -1) {
657
657
  this[key].push(element)
658
658
  }
659
- }, this)
659
+ }
660
660
  } else {
661
661
  this[key] = value
662
662
  }
@@ -703,7 +703,7 @@ function _validateThenUpdateStatusCodes(remote, local, remoteKey, localKey) {
703
703
  }
704
704
 
705
705
  let valid = true
706
- valueToTest.forEach(function validateArray(thingToTest) {
706
+ for (const thingToTest of valueToTest) {
707
707
  if (!(typeof thingToTest === 'string' || typeof thingToTest === 'number')) {
708
708
  logger.warn(
709
709
  'Saw SSC (ignore|expect)_status_code that is not a number or string,' +
@@ -712,7 +712,7 @@ function _validateThenUpdateStatusCodes(remote, local, remoteKey, localKey) {
712
712
  )
713
713
  valid = false
714
714
  }
715
- })
715
+ }
716
716
  if (!valid) {
717
717
  return
718
718
  }
@@ -747,7 +747,7 @@ function _validateThenUpdateErrorClasses(remote, local, remoteKey, localKey) {
747
747
  }
748
748
 
749
749
  let valid = true
750
- Object.keys(valueToTest).forEach(function validateArray(key) {
750
+ for (const key of Object.keys(valueToTest)) {
751
751
  const thingToTest = valueToTest[key]
752
752
  if (typeof thingToTest !== 'string') {
753
753
  logger.warn(
@@ -756,7 +756,7 @@ function _validateThenUpdateErrorClasses(remote, local, remoteKey, localKey) {
756
756
  )
757
757
  valid = false
758
758
  }
759
- })
759
+ }
760
760
  if (!valid) {
761
761
  return
762
762
  }
@@ -801,13 +801,13 @@ function _validateThenUpdateErrorMessages(remote, local, remoteKey, localKey) {
801
801
  }
802
802
 
803
803
  let valid = true
804
- Object.keys(valueToTest).forEach(function validateArray(key) {
804
+ for (const key of Object.keys(valueToTest)) {
805
805
  const arrayToTest = valueToTest[key]
806
806
  if (!Array.isArray(arrayToTest)) {
807
807
  logger.warn('Saw SSC message array that is not an array, will not merge: %s', arrayToTest)
808
808
  valid = false
809
809
  }
810
- })
810
+ }
811
811
  if (!valid) {
812
812
  return
813
813
  }
@@ -1058,15 +1058,15 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
1058
1058
  internal = this
1059
1059
  }
1060
1060
 
1061
- Object.keys(external).forEach(function overwrite(key) {
1061
+ for (const key of Object.keys(external)) {
1062
1062
  // if it's not in the defaults, it doesn't exist
1063
1063
  if (!arbitrary && !(key in internal)) {
1064
- return
1064
+ continue
1065
1065
  }
1066
1066
 
1067
1067
  if (key === 'ssl' && !isTruthular(external.ssl)) {
1068
1068
  logger.warn(SSL_WARNING)
1069
- return
1069
+ continue
1070
1070
  }
1071
1071
 
1072
1072
  let node = null
@@ -1074,7 +1074,7 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
1074
1074
  node = external[key]
1075
1075
  } catch {
1076
1076
  logger.warn('Error thrown on access of user config for key: %s', key)
1077
- return
1077
+ continue
1078
1078
  }
1079
1079
 
1080
1080
  if (typeof node === 'object' && !Array.isArray(node) && !(node instanceof RegExp)) {
@@ -1084,7 +1084,7 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
1084
1084
  } else {
1085
1085
  internal[key] = node
1086
1086
  }
1087
- }, this)
1087
+ }
1088
1088
  }
1089
1089
 
1090
1090
  /**
@@ -1117,12 +1117,12 @@ Config.prototype._fromSpecial = function _fromSpecial() {
1117
1117
  Config.prototype._featureFlagsFromEnv = function _featureFlagsFromEnv() {
1118
1118
  const flags = Object.keys(featureFlag.prerelease).concat(featureFlag.released)
1119
1119
  const config = this
1120
- flags.forEach(function checkFlag(flag) {
1120
+ for (const flag of flags) {
1121
1121
  const envVal = process.env['NEW_RELIC_FEATURE_FLAG_' + flag.toUpperCase()]
1122
1122
  if (envVal) {
1123
1123
  config.feature_flag[flag] = isTruthular(envVal)
1124
1124
  }
1125
- })
1125
+ }
1126
1126
  }
1127
1127
 
1128
1128
  /**
@@ -1341,7 +1341,7 @@ Config.prototype._serverlessDT = function _serverlessDT() {
1341
1341
  */
1342
1342
  Config.prototype._preventServerlessDT = function _preventServerlessDT() {
1343
1343
  // Don't allow DT config settings to be set if serverless_mode is disabled
1344
- SERVERLESS_DT_KEYS.forEach((key) => {
1344
+ for (const key of SERVERLESS_DT_KEYS) {
1345
1345
  if (this[key]) {
1346
1346
  logger.warn(
1347
1347
  key +
@@ -1350,7 +1350,7 @@ Config.prototype._preventServerlessDT = function _preventServerlessDT() {
1350
1350
  )
1351
1351
  this[key] = null
1352
1352
  }
1353
- })
1353
+ }
1354
1354
  }
1355
1355
 
1356
1356
  /**
@@ -1502,7 +1502,9 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
1502
1502
  this.attributes.exclude.push('request.parameters.*')
1503
1503
 
1504
1504
  function checkNode(base, target, settings) {
1505
- Object.keys(settings).forEach(checkKey.bind(null, base, target, settings))
1505
+ for (const key of Object.keys(settings)) {
1506
+ checkKey(base, target, settings, key)
1507
+ }
1506
1508
  }
1507
1509
 
1508
1510
  function checkKey(base, target, settings, key) {
@@ -1531,7 +1533,7 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
1531
1533
  * @param {Array} keys keys from a LASP policy
1532
1534
  * @returns {CollectorResponse} creates CollectorResponse with either preserve or shutdown
1533
1535
  */
1534
- function _laspReponse(keys) {
1536
+ function _laspResponse(keys) {
1535
1537
  if (keys.length) {
1536
1538
  logger.error('The agent received one or more unexpected security policies and will shut down.')
1537
1539
  return CollectorResponse.fatal(null)
@@ -1617,18 +1619,18 @@ Config.prototype.applyLasp = function applyLasp(agent, policies) {
1617
1619
  const keys = Object.keys(policies)
1618
1620
 
1619
1621
  if (!this.security_policies_token) {
1620
- return _laspReponse(keys)
1622
+ return _laspResponse(keys)
1621
1623
  }
1622
1624
 
1623
1625
  const { finalPolicies, missingRequired } = this._buildLaspPolicy(agent, policies)
1624
1626
 
1625
1627
  const missingLASP = []
1626
- Object.keys(LASP_MAP).forEach(function checkPolicy(name) {
1628
+ for (const name of Object.keys(LASP_MAP)) {
1627
1629
  if (!policies[name]) {
1628
1630
  // agent is expecting a policy that was not sent from server -- fail
1629
1631
  missingLASP.push(name)
1630
1632
  }
1631
- })
1633
+ }
1632
1634
 
1633
1635
  let fatalMessage = null
1634
1636
  if (missingLASP.length) {
@@ -1655,14 +1657,14 @@ Config.prototype.applyLasp = function applyLasp(agent, policies) {
1655
1657
  }
1656
1658
 
1657
1659
  Config.prototype.validateFlags = function validateFlags() {
1658
- Object.keys(this.feature_flag).forEach(function forEachFlag(key) {
1660
+ for (const key of Object.keys(this.feature_flag)) {
1659
1661
  if (featureFlag.released.indexOf(key) > -1) {
1660
1662
  logger.warn('Feature flag %s has been released', key)
1661
1663
  }
1662
1664
  if (featureFlag.unreleased.indexOf(key) > -1) {
1663
1665
  logger.warn('Feature flag %s has been deprecated', key)
1664
1666
  }
1665
- })
1667
+ }
1666
1668
  }
1667
1669
 
1668
1670
  function redactValue(value) {
@@ -32,28 +32,28 @@ class MergeServerConfig {
32
32
  }
33
33
 
34
34
  updateArray(value, local, localKey) {
35
- value.forEach((element) => {
35
+ for (const element of value) {
36
36
  if (local[localKey].indexOf(element) === -1) {
37
37
  local[localKey].push(element)
38
38
  }
39
- })
39
+ }
40
40
  }
41
41
 
42
42
  updateObject(value, local, localKey) {
43
43
  // go through each key of the object and update it
44
- Object.keys(value).forEach((element) => {
44
+ for (const element of Object.keys(value)) {
45
45
  if (Array.isArray(local[localKey][element]) && Array.isArray(value[element])) {
46
46
  // if both key-values are arrays, push the remote value onto the local array
47
- value[element].forEach((elementValue) => {
47
+ for (const elementValue of value[element]) {
48
48
  if (local[localKey][element].indexOf(elementValue) === -1) {
49
49
  local[localKey][element].push(elementValue)
50
50
  }
51
- })
51
+ }
52
52
  } else {
53
53
  // otherwise, replace the local value with the server value
54
54
  local[localKey][element] = value[element]
55
55
  }
56
- })
56
+ }
57
57
  }
58
58
  }
59
59
 
@@ -32,6 +32,10 @@ module.exports = {
32
32
  type: InstrumentationDescriptor.TYPE_TRANSACTION,
33
33
  file: 'http.js'
34
34
  },
35
+ http2: {
36
+ type: InstrumentationDescriptor.TYPE_TRANSACTION,
37
+ file: 'http2.js'
38
+ },
35
39
  inspector: {
36
40
  type: InstrumentationDescriptor.TYPE_GENERIC,
37
41
  file: 'inspector.js'
@@ -72,18 +72,19 @@ function parsePath(pathString, method) {
72
72
  operation = 'index.create'
73
73
  return { collection, operation }
74
74
  }
75
- path.forEach((segment, idx) => {
75
+ for (let idx = 0; idx < path.length; idx++) {
76
+ const segment = path[idx]
76
77
  const prev = idx - 1
77
- let opname
78
78
  if (segment === '_search') {
79
79
  collection = path?.[prev] || defaultCollection
80
80
  operation = 'search'
81
81
  } else if (segment[0] === '_') {
82
- opname = segment.substring(1)
82
+ const opname = segment.substring(1)
83
83
  collection = path?.[prev] || defaultCollection
84
84
  operation = `${opname}.${suffix}`
85
85
  }
86
- })
86
+ }
87
+
87
88
  if (!operation && !collection) {
88
89
  // likely creating an index--no underscore segments
89
90
  collection = path?.[1] || defaultCollection
@@ -40,7 +40,7 @@ module.exports = function parseSql(sql) {
40
40
  try {
41
41
  logger.trace('parseSQL got an a non-string sql that looks like: %s', stringify(sql))
42
42
  } catch (err) {
43
- logger.debug(err, 'Unabler to stringify SQL')
43
+ logger.debug(err, 'Unable to stringify SQL')
44
44
  }
45
45
  }
46
46
  return {
@@ -240,7 +240,7 @@ function getGlobalPackages() {
240
240
  */
241
241
  function flattenVersions(packages) {
242
242
  const info = Object.create(null)
243
- packages.forEach((pair) => {
243
+ for (const pair of packages) {
244
244
  const p = pair[0]
245
245
  const v = pair[1]
246
246
 
@@ -251,7 +251,7 @@ function flattenVersions(packages) {
251
251
  } else {
252
252
  info[p] = [v]
253
253
  }
254
- })
254
+ }
255
255
 
256
256
  return Object.keys(info)
257
257
  .map((key) => [key, info[key].join(', ')])
@@ -277,7 +277,7 @@ function flattenVersions(packages) {
277
277
  function remapConfigSettings() {
278
278
  if (process.config && process.config.variables) {
279
279
  const variables = process.config.variables
280
- Object.keys(variables).forEach((key) => {
280
+ for (const key of Object.keys(variables)) {
281
281
  if (remapping[key]) {
282
282
  let value = variables[key]
283
283
 
@@ -290,7 +290,7 @@ function remapConfigSettings() {
290
290
 
291
291
  addSetting(remapping[key], value)
292
292
  }
293
- })
293
+ }
294
294
 
295
295
  addMissingProcessVars()
296
296
  }
@@ -334,10 +334,10 @@ async function getOtherPackages() {
334
334
  2
335
335
  )
336
336
 
337
- otherPackages.forEach((pkg) => {
337
+ for (const pkg of otherPackages) {
338
338
  other.packages.push.apply(other.packages, pkg.packages)
339
339
  other.dependencies.push.apply(other.dependencies, pkg.dependencies)
340
- })
340
+ }
341
341
 
342
342
  _log('Done getting other packages')
343
343
  return other
@@ -442,21 +442,21 @@ function refreshSyncOnly() {
442
442
  settings = Object.create(null)
443
443
  // add persisted settings
444
444
  if (framework.length) {
445
- framework.forEach(function addFrameworks(fw) {
445
+ for (const fw of framework) {
446
446
  addSetting('Framework', fw)
447
- })
447
+ }
448
448
  }
449
449
 
450
450
  if (dispatcher.length) {
451
- dispatcher.forEach(function addDispatchers(d) {
451
+ for (const d of dispatcher) {
452
452
  addSetting('Dispatcher', d)
453
- })
453
+ }
454
454
  }
455
455
 
456
456
  if (dispatcherVersion.length) {
457
- dispatcher.forEach(function addDispatchers(d) {
457
+ for (const d of dispatcher) {
458
458
  addSetting(DISPATCHER_VERSION, d)
459
- })
459
+ }
460
460
  }
461
461
 
462
462
  gatherEnv()
@@ -498,11 +498,11 @@ async function getJSON() {
498
498
  }
499
499
 
500
500
  const items = []
501
- Object.keys(settings).forEach(function settingKeysForEach(key) {
502
- settings[key].forEach(function settingsValuesForEach(setting) {
501
+ for (const [key, value] of Object.entries(settings)) {
502
+ for (const setting of value) {
503
503
  items.push([key, setting])
504
- })
505
- })
504
+ }
505
+ }
506
506
  _log('JSON got')
507
507
  return items
508
508
  }
@@ -58,7 +58,7 @@ class Exception {
58
58
  * because everything's an object in JS. I'm not entirely sure why we do this, but
59
59
  * weird enough to make note of
60
60
  *
61
- * @param {Transaction} transaction The agent transaction, coming from the instrumentatation
61
+ * @param {Transaction} transaction The agent transaction, coming from the instrumentation
62
62
  * @param {Exception} exception An custom Exception object with the error and other information
63
63
  * @param {object} config The configuration to use when creating the object
64
64
  * @returns {Array} an Array of Error information, [0] -> placeholder,