newrelic 13.3.3 → 13.5.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.
Files changed (169) hide show
  1. package/NEWS.md +54 -0
  2. package/THIRD_PARTY_NOTICES.md +11 -11
  3. package/api.js +1 -1
  4. package/esm-loader.mjs +2 -2
  5. package/lib/agent.js +2 -2
  6. package/lib/aggregators/event-aggregator.js +0 -2
  7. package/lib/attributes.js +6 -6
  8. package/lib/collector/api.js +1 -1
  9. package/lib/collector/facts.js +1 -1
  10. package/lib/collector/http-agents.js +2 -2
  11. package/lib/collector/parse-response.js +9 -12
  12. package/lib/collector/remote-method.js +4 -5
  13. package/lib/collector/serverless.js +1 -1
  14. package/lib/config/build-instrumentation-config.js +13 -3
  15. package/lib/config/default.js +21 -10
  16. package/lib/config/formatters.js +5 -6
  17. package/lib/config/index.js +37 -24
  18. package/lib/harvester.js +1 -1
  19. package/lib/header-processing.js +3 -3
  20. package/lib/health-reporter.js +2 -2
  21. package/lib/instrumentation/@node-redis/client.js +1 -1
  22. package/lib/instrumentation/@prisma/client.js +1 -1
  23. package/lib/instrumentation/aws-sdk/util.js +3 -3
  24. package/lib/instrumentation/aws-sdk/v2/instrumentation-helper.js +2 -2
  25. package/lib/instrumentation/aws-sdk/v3/bedrock.js +5 -5
  26. package/lib/instrumentation/aws-sdk/v3/common.js +14 -14
  27. package/lib/instrumentation/aws-sdk/v3/dynamodb.js +13 -13
  28. package/lib/instrumentation/aws-sdk/v3/lambda.js +3 -3
  29. package/lib/instrumentation/aws-sdk/v3/sns.js +12 -12
  30. package/lib/instrumentation/aws-sdk/v3/sqs.js +9 -9
  31. package/lib/instrumentation/core/http-outbound.js +1 -2
  32. package/lib/instrumentation/fastify/spec-builders.js +9 -29
  33. package/lib/instrumentation/fastify.js +23 -94
  34. package/lib/instrumentation/kafkajs/consumer.js +1 -1
  35. package/lib/instrumentation/koa/instrumentation.js +1 -1
  36. package/lib/instrumentation/langchain/runnable.js +1 -1
  37. package/lib/instrumentation/memcached.js +4 -4
  38. package/lib/instrumentation/mongodb.js +2 -2
  39. package/lib/instrumentation/nextjs/next-server.js +1 -3
  40. package/lib/instrumentation/nextjs/utils.js +2 -2
  41. package/lib/instrumentation/restify.js +2 -2
  42. package/lib/instrumentation/when/contextualizer.js +1 -1
  43. package/lib/instrumentation-descriptor.js +2 -11
  44. package/lib/instrumentations.js +1 -20
  45. package/lib/llm-events/aws-bedrock/bedrock-response.js +6 -6
  46. package/lib/llm-events/aws-bedrock/chat-completion-summary.js +2 -1
  47. package/lib/llm-events/aws-bedrock/converse-stream-handler.js +1 -1
  48. package/lib/llm-events/aws-bedrock/stream-handler.js +4 -4
  49. package/lib/metrics/index.js +2 -2
  50. package/lib/metrics/normalizer/rule.js +1 -1
  51. package/lib/metrics/normalizer.js +4 -5
  52. package/lib/metrics/recorders/database-operation.js +2 -3
  53. package/lib/metrics/recorders/message-transaction.js +3 -3
  54. package/lib/metrics/recorders/middleware.js +1 -2
  55. package/lib/otel/context-manager.js +4 -4
  56. package/lib/otel/trace-propagator.js +1 -1
  57. package/lib/otel/traces/segments/database.js +1 -1
  58. package/lib/otel/traces/utils.js +9 -9
  59. package/lib/prioritized-attributes.js +2 -2
  60. package/lib/{adaptive-sampler.js → samplers/adaptive-sampler.js} +8 -0
  61. package/lib/serverless/aws-lambda.js +4 -4
  62. package/lib/shim/datastore-shim.js +2 -2
  63. package/lib/shim/message-shim/consume.js +4 -4
  64. package/lib/shim/message-shim/subscribe-consume.js +1 -2
  65. package/lib/shim/promise-shim.js +1 -4
  66. package/lib/shim/shim.js +14 -29
  67. package/lib/shim/specs/class.js +3 -3
  68. package/lib/shim/specs/middleware-mounter.js +2 -2
  69. package/lib/shim/specs/middleware.js +3 -3
  70. package/lib/shim/specs/query.js +1 -1
  71. package/lib/shim/specs/recorder.js +1 -1
  72. package/lib/shim/specs/wrap.js +2 -2
  73. package/lib/shim/transaction-shim.js +0 -1
  74. package/lib/shim/webframework-shim/common.js +2 -4
  75. package/lib/shim/webframework-shim/index.js +10 -1
  76. package/lib/shim/webframework-shim/middleware.js +17 -21
  77. package/lib/shimmer.js +56 -103
  78. package/lib/spans/span-context.js +1 -1
  79. package/lib/spans/span-event-aggregator.js +2 -2
  80. package/lib/spans/span-event.js +6 -5
  81. package/lib/spans/streaming-span-attributes.js +1 -1
  82. package/lib/spans/streaming-span-event-aggregator.js +5 -3
  83. package/lib/spans/streaming-span-event.js +1 -1
  84. package/lib/stats/index.js +1 -1
  85. package/lib/subscriber-configs.js +6 -1
  86. package/lib/subscribers/amqplib/accept-message.js +14 -0
  87. package/lib/subscribers/amqplib/callback-model.js +39 -0
  88. package/lib/subscribers/amqplib/channel-model.js +39 -0
  89. package/lib/subscribers/amqplib/config.js +697 -0
  90. package/lib/subscribers/amqplib/connect.js +74 -0
  91. package/lib/subscribers/amqplib/consume.js +54 -0
  92. package/lib/subscribers/amqplib/get-cb.js +16 -0
  93. package/lib/subscribers/amqplib/get.js +50 -0
  94. package/lib/subscribers/amqplib/purge-queue-cb.js +16 -0
  95. package/lib/subscribers/amqplib/purge-queue.js +37 -0
  96. package/lib/subscribers/amqplib/send-message.js +44 -0
  97. package/lib/subscribers/amqplib/send-or-enqueue.js +18 -0
  98. package/lib/subscribers/amqplib/utils.js +53 -0
  99. package/lib/subscribers/application-logs.js +1 -1
  100. package/lib/subscribers/base.js +113 -29
  101. package/lib/subscribers/cassandra-driver/client-batch.js +49 -0
  102. package/lib/subscribers/cassandra-driver/client-connect.js +35 -0
  103. package/lib/subscribers/cassandra-driver/client-each-row.js +36 -0
  104. package/lib/subscribers/cassandra-driver/client-execute.js +36 -0
  105. package/lib/subscribers/cassandra-driver/client-shutdown.js +32 -0
  106. package/lib/subscribers/cassandra-driver/config.js +145 -0
  107. package/lib/subscribers/cassandra-driver/legacy-client-batch.js +22 -0
  108. package/lib/subscribers/cassandra-driver/legacy-client-connect.js +22 -0
  109. package/lib/subscribers/cassandra-driver/legacy-client-each-row.js +22 -0
  110. package/lib/subscribers/cassandra-driver/legacy-client-execute.js +21 -0
  111. package/lib/subscribers/cassandra-driver/legacy-client-shutdown.js +32 -0
  112. package/lib/subscribers/create-config.js +4 -6
  113. package/lib/subscribers/db-operation.js +12 -0
  114. package/lib/subscribers/db-query.js +5 -1
  115. package/lib/subscribers/dc-base.js +89 -0
  116. package/lib/subscribers/fastify/add-hook.js +46 -0
  117. package/lib/subscribers/fastify/common.js +121 -0
  118. package/lib/subscribers/fastify/config.js +39 -0
  119. package/lib/subscribers/fastify/decorate.js +35 -0
  120. package/lib/subscribers/fastify/index.js +31 -0
  121. package/lib/subscribers/mcp-sdk/client-request.js +1 -1
  122. package/lib/subscribers/mcp-sdk/config.js +2 -0
  123. package/lib/subscribers/message-consumer.js +146 -0
  124. package/lib/subscribers/message-producer.js +60 -0
  125. package/lib/subscribers/meta-subscriber.js +69 -0
  126. package/lib/subscribers/openai/base.js +27 -1
  127. package/lib/subscribers/openai/chat.js +0 -27
  128. package/lib/subscribers/openai/config.js +3 -3
  129. package/lib/subscribers/openai/utils.js +10 -11
  130. package/lib/subscribers/pg/config.js +91 -0
  131. package/lib/subscribers/pg/connect.js +28 -0
  132. package/lib/subscribers/pg/native-connect.js +25 -0
  133. package/lib/subscribers/pg/native-query.js +22 -0
  134. package/lib/subscribers/pg/query.js +66 -0
  135. package/lib/subscribers/pino/index.js +2 -2
  136. package/lib/subscribers/propagation.js +23 -0
  137. package/lib/subscribers/undici/config.js +11 -0
  138. package/lib/subscribers/undici/index.js +195 -0
  139. package/lib/synthetics.js +4 -4
  140. package/lib/timer.js +1 -1
  141. package/lib/tracking-packages.js +25 -0
  142. package/lib/transaction/dt-payload.js +1 -1
  143. package/lib/transaction/handle.js +8 -9
  144. package/lib/transaction/index.js +25 -21
  145. package/lib/transaction/name-state.js +11 -11
  146. package/lib/transaction/trace/segment.js +3 -4
  147. package/lib/transaction/tracer/index.js +1 -1
  148. package/lib/util/attribute-types.js +1 -1
  149. package/lib/util/byte-limit.js +1 -1
  150. package/lib/util/cat.js +13 -13
  151. package/lib/util/flatten.js +2 -3
  152. package/lib/util/is-absolute-path.js +1 -1
  153. package/lib/util/is-string.js +15 -0
  154. package/lib/util/llm-utils.js +3 -3
  155. package/lib/util/logger.js +8 -8
  156. package/lib/util/stream-sink.js +1 -1
  157. package/lib/utilization/docker-info.js +4 -3
  158. package/lib/utilization/ecs-info.js +1 -1
  159. package/lib/w3c/traceparent.js +3 -3
  160. package/lib/w3c/tracestate.js +1 -1
  161. package/package.json +2 -2
  162. package/lib/instrumentation/amqplib/amqplib.js +0 -122
  163. package/lib/instrumentation/amqplib/channel-model.js +0 -124
  164. package/lib/instrumentation/amqplib/channel.js +0 -72
  165. package/lib/instrumentation/amqplib/nr-hooks.js +0 -21
  166. package/lib/instrumentation/amqplib/utils.js +0 -143
  167. package/lib/instrumentation/cassandra-driver.js +0 -131
  168. package/lib/instrumentation/pg.js +0 -137
  169. package/lib/instrumentation/undici.js +0 -229
package/lib/shimmer.js CHANGED
@@ -18,14 +18,15 @@ const { nrEsmProxy } = require('./symbols')
18
18
  const isAbsolutePath = require('./util/is-absolute-path')
19
19
  const InstrumentationDescriptor = require('./instrumentation-descriptor')
20
20
  const InstrumentationTracker = require('./instrumentation-tracker')
21
- let pkgsToHook = []
22
-
23
21
  const NAMES = require('./metrics/names')
22
+ const INSTRUMENTATION_TRACKING_PREFIX = NAMES.FEATURES.INSTRUMENTATION.ON_REQUIRE
24
23
  const symbols = require('./symbols')
25
- const { unsubscribe } = require('./instrumentation/undici')
26
24
  const subscriptions = require('./subscriber-configs')
27
25
  const createSubscriberConfigs = require('./subscribers/create-config')
28
26
  const ModulePatch = require('@apm-js-collab/tracing-hooks')
27
+ const getPackageVersion = require('./util/get-package-version')
28
+ const trackingPkgs = require('./tracking-packages')
29
+ let pkgsToHook = []
29
30
 
30
31
  /**
31
32
  * Unwrapping is only likely to be used by test code, and is a fairly drastic
@@ -280,7 +281,6 @@ const shimmer = (module.exports = {
280
281
  */
281
282
  registerCoreInstrumentation(agent) {
282
283
  instrumentProcessMethods(agent)
283
- instrumentUndiciFetch(agent)
284
284
 
285
285
  // Instrument each of the core modules.
286
286
  for (const [mojule, core] of Object.entries(CORE_INSTRUMENTATION)) {
@@ -311,6 +311,9 @@ const shimmer = (module.exports = {
311
311
  },
312
312
 
313
313
  registerHooks(agent) {
314
+ // add the packages from the subscriber based instrumentation
315
+ // this is only added to add tracking metrics
316
+ pkgsToHook.push(...Object.keys(subscriptions), ...trackingPkgs)
314
317
  this._ritm = new Hook(pkgsToHook, function onHook(exports, name, basedir) {
315
318
  return _postLoad(agent, exports, name, basedir)
316
319
  })
@@ -336,7 +339,6 @@ const shimmer = (module.exports = {
336
339
  // `@opentelemetry` packages for slim builds.
337
340
  require('./otel/setup').teardownOtel(agent)
338
341
  }
339
- unsubscribe()
340
342
  if (this._subscribers) {
341
343
  shimmer.teardownSubscribers()
342
344
  }
@@ -492,30 +494,6 @@ const shimmer = (module.exports = {
492
494
  // previously it would just call instrumentation
493
495
  // and not check the result
494
496
  return returnModule ? result : shimmer.isInstrumented(moduleName, resolvedName)
495
- },
496
-
497
- /**
498
- * Gets the version of a given package by parsing it from package.json
499
- *
500
- * @param {string} moduleName name of module
501
- * @returns {string} version, defaults to Node.js version when it cannot parse
502
- */
503
- getPackageVersion(moduleName) {
504
- try {
505
- const trackedItems = shimmer.registeredInstrumentations.getAllByName(moduleName)
506
- if (trackedItems === undefined) {
507
- throw Error(`no tracked items for module '${moduleName}'`)
508
- }
509
- const item = trackedItems.find((item) => item.instrumentation.resolvedName !== undefined)
510
- if (item === undefined) {
511
- return process.version
512
- }
513
- const pkg = require(path.resolve(item.instrumentation.resolvedName, 'package.json'))
514
- return pkg.version
515
- } catch (err) {
516
- logger.debug('Failed to get version for `%s`, reason: %s', moduleName, err.message)
517
- return process.version
518
- }
519
497
  }
520
498
  })
521
499
 
@@ -539,16 +517,16 @@ function applyDebugState(shim, nodule, inEsm) {
539
517
  * initialization function that takes the agent and the module to be
540
518
  * instrumented.
541
519
  *
542
- * @param {object} agent NR agent
543
- * @param {object} nodule Class or module containing the function to wrap.
544
- * @param {string} moduleName name of module
545
- * @param {string} resolvedName fully qualified path to module
546
- * @param {boolean} esmResolver indicates if it came from esm loader
520
+ * @param {object} params to function
521
+ * @param {object} params.agent NR agent
522
+ * @param {object} params.nodule Class or module containing the function to wrap.
523
+ * @param {string} params.moduleName name of module
524
+ * @param {string} params.resolvedName fully qualified path to module
525
+ * @param {boolean} params.esmResolver indicates if it came from esm loader
526
+ * @param {string} params.pkgVersion version of package loading instrumentation
547
527
  * @returns {object|undefined} returns exported module unless already instrumented
548
528
  */
549
- function instrumentPostLoad(agent, nodule, moduleName, resolvedName, esmResolver) {
550
- // default to Node.js version, this occurs for core libraries
551
- const pkgVersion = shimmer.getPackageVersion(moduleName)
529
+ function instrumentPostLoad({ agent, nodule, moduleName, resolvedName, pkgVersion, esmResolver }) {
552
530
  const trackedInstrumentations = shimmer.registeredInstrumentations.getAllByName(moduleName)
553
531
  trackedInstrumentations.forEach((trackedInstrumentation) => {
554
532
  const isInstrumented = trackedInstrumentation.meta.instrumented === true
@@ -571,16 +549,6 @@ function instrumentPostLoad(agent, nodule, moduleName, resolvedName, esmResolver
571
549
  })
572
550
 
573
551
  applyDebugState(shim, resolvedNodule, esmResolver)
574
- trackInstrumentationUsage(agent, shim, moduleName, NAMES.FEATURES.INSTRUMENTATION.ON_REQUIRE)
575
-
576
- // Tracking instrumentation is only used to add the supportability metrics
577
- // that occur directly above this. No reason to attempt to load instrumentation
578
- // as it does not exist.
579
- if (instrumentation.type === InstrumentationDescriptor.TYPE_TRACKING) {
580
- shimmer.registeredInstrumentations.setHookSuccess(trackedInstrumentation)
581
- return
582
- }
583
-
584
552
  nodule = loadInstrumentation({
585
553
  shim,
586
554
  resolvedNodule,
@@ -722,7 +690,7 @@ function _firstPartyInstrumentation(agent, fileName, shim, nodule, moduleName) {
722
690
  * @param {string} name The simple name used to load the module.
723
691
  * @param {string} resolvedName The full file system path to the module.
724
692
  * @param {object} [esmResolver] If the module was loaded via ESM
725
- * @returns {*|Object|undefined} The instrumented module, or the original
693
+ * @returns {* | object | undefined} The instrumented module, or the original
726
694
  * @private
727
695
  */
728
696
  function _postLoad(agent, nodule, name, resolvedName, esmResolver) {
@@ -733,21 +701,36 @@ function _postLoad(agent, nodule, name, resolvedName, esmResolver) {
733
701
  registeredInstrumentations.length &&
734
702
  registeredInstrumentations.filter((ri) => ri.instrumentation.onRequire).length
735
703
 
704
+ if (resolvedName === undefined && isAbsolutePath(name) === true) {
705
+ // `resolvedName` comes from the `basedir` returned by the `Hook`
706
+ // function from import-in-the-middle or require-in-the-middle. At least
707
+ // with IITM, if the path string does not include a `node_modules` then
708
+ // `basedir` will be `undefined`. But we need it for our instrumentation
709
+ // to work. We'll only reach this situation if the module being
710
+ // instrumented has an `absolutePath` defined. So we detect that and
711
+ // assign appropriately.
712
+ resolvedName = name
713
+ }
714
+
715
+ let pkgVersion = null
716
+ // check for resolvedName
717
+ // core node libs lack this so we do not need to obtain package version
718
+ if (resolvedName) {
719
+ pkgVersion = getPackageVersion(resolvedName)
720
+ }
721
+ // this currently works because we add subscriber based instrumentation
722
+ // and packages we want to track that are not instrumented to the `pkgsToHook`
723
+ // array that get passed to require-in-the-middle and import-in-the-middle
724
+ // if/once we removed reliance on those packages, we will have to subscribe to the
725
+ // https://nodejs.org/api/diagnostics_channel.html#modules channels to see when
726
+ // a module is required/imported and increment the metrics there
727
+ trackInstrumentationUsage(agent, name, pkgVersion)
728
+
736
729
  // Check if this is a known instrumentation and then run it.
737
730
  if (hasPostLoadInstrumentation) {
738
- if (resolvedName === undefined && isAbsolutePath(name) === true) {
739
- // `resolvedName` comes from the `basedir` returned by the `Hook`
740
- // function from import-in-the-middle or require-in-the-middle. At least
741
- // with IITM, if the path string does not include a `node_modules` then
742
- // `basedir` will be `undefined`. But we need it for our instrumentation
743
- // to work. We'll only reach this situation if the module being
744
- // instrumented has an `absolutePath` defined. So we detect that and
745
- // assign appropriately.
746
- resolvedName = name
747
- }
748
731
  shimmer.registeredInstrumentations.setResolvedName(simpleName, resolvedName)
749
732
  logger.trace('Instrumenting %s with onRequire (module loaded) hook.', name)
750
- return instrumentPostLoad(agent, nodule, simpleName, resolvedName, esmResolver)
733
+ return instrumentPostLoad({ agent, nodule, moduleName: simpleName, resolvedName, pkgVersion, esmResolver })
751
734
  }
752
735
 
753
736
  return nodule
@@ -779,18 +762,23 @@ function hasValidRegisterOptions(opts) {
779
762
  /**
780
763
  * Adds metrics to indicate instrumentation was used for a particular module and
781
764
  * what major version the module was at, if possible.
782
- *
783
- * @param {*} agent The agent instance.
784
- * @param {*} shim The instance of the shim used to instrument the module.
765
+ * Creates the `Supportability/Features/Instrumentation/OnRequire/<packageName>`
766
+ * and `Supportability/Features/Instrumentation/OnRequire/<packageName>/Version/<majorVersion>`
767
+ * metrics to track the usage of an instrumented package.
768
+ * @param {Agent} agent The agent instance.
785
769
  * @param {string} moduleName The name of the required module.
786
- * @param {string} metricPrefix Support metric prefix to prepend to the metrics. Will indicate onRequire
787
- *
788
- * from NAMES.FEATURES.INSTRUMENTATION.
770
+ * @param {string} version version of package
789
771
  */
790
- function trackInstrumentationUsage(agent, shim, moduleName, metricPrefix) {
772
+ function trackInstrumentationUsage(agent, moduleName, version) {
791
773
  try {
792
- const version = tryGetVersion(shim)
793
- const instrumentationMetricName = `${metricPrefix}/${moduleName}`
774
+ // only save the package name not a file within package
775
+ if (moduleName.startsWith('@')) {
776
+ const split = moduleName.split('/')
777
+ moduleName = `${split[0]}/${split[1]}`
778
+ } else {
779
+ moduleName = moduleName.split('/')[0]
780
+ }
781
+ const instrumentationMetricName = `${INSTRUMENTATION_TRACKING_PREFIX}/${moduleName}`
794
782
 
795
783
  agent.metrics.getOrCreateMetric(instrumentationMetricName).incrementCallCount()
796
784
 
@@ -805,16 +793,6 @@ function trackInstrumentationUsage(agent, shim, moduleName, metricPrefix) {
805
793
  }
806
794
  }
807
795
 
808
- function tryGetVersion(shim) {
809
- // Indicates it is a built-in where the version is not useful as
810
- // it is `process.version`
811
- if (shim._moduleRoot === '.') {
812
- return
813
- }
814
-
815
- return shim.pkgVersion
816
- }
817
-
818
796
  /**
819
797
  * Loads the instrumentation with `./lib/instrumentation/core/globals.js`
820
798
  * This instrumentation cannot be disabled by config at the moment as it just
@@ -829,31 +807,6 @@ function instrumentProcessMethods(agent) {
829
807
  _firstPartyInstrumentation(agent, globalsFilepath, globalShim, global, 'globals')
830
808
  }
831
809
 
832
- /**
833
- * Checks if undici/fetch instrumentation is enabled.
834
- * If so, it loads the diagnostics_channel hooks to instrument outbound
835
- * undici/fetch calls.
836
- * Since this just registers subscriptions to diagnostics_channel events from undici,
837
- * we register this as core and it'll work for both fetch and undici
838
- *
839
- * @param {Agent} agent the agent instance
840
- */
841
- function instrumentUndiciFetch(agent) {
842
- if (agent.config.instrumentation?.undici.enabled === false) {
843
- logger.warn('Instrumentation for undici/fetch has been disabled via `config.instrumentation.undici.enabled`. Not instrumenting package')
844
- return
845
- }
846
-
847
- const undiciPath = path.join(__dirname, 'instrumentation', 'undici.js')
848
- const undiciShim = shims.createShimFromType({
849
- type: InstrumentationDescriptor.TYPE_TRANSACTION,
850
- agent,
851
- moduleName: 'undici',
852
- resolvedName: '.'
853
- })
854
- _firstPartyInstrumentation(agent, undiciPath, undiciShim)
855
- }
856
-
857
810
  function instrumentDomain(agent) {
858
811
  if (agent.config.instrumentation?.domain.enabled === false) {
859
812
  logger.warn('Instrumentation for domain has been disabled via `config.instrumentation.domain.enabled`. Not instrumenting package')
@@ -41,7 +41,7 @@ class SpanContext {
41
41
  *
42
42
  * Last error wins.
43
43
  *
44
- * @param details
44
+ * @param {object} details error details
45
45
  */
46
46
  setError(details) {
47
47
  this.hasError = true
@@ -87,7 +87,7 @@ class SpanEventAggregator extends EventAggregator {
87
87
  /**
88
88
  * Reconfigure the `SpanEventAggregator` based on values from server
89
89
  *
90
- * @param {Config} config
90
+ * @param {Config} config the config to reconfigure with
91
91
  */
92
92
  reconfigure(config) {
93
93
  super.reconfigure(config)
@@ -105,7 +105,7 @@ class SpanEventAggregator extends EventAggregator {
105
105
  * When no `span_event_harvest_config` has been received from the server, applies an
106
106
  * agent-defined fallback maximum to protect against collecting and sending too many spans.
107
107
  *
108
- * @param {Config} config
108
+ * @param {Config} config the config to check
109
109
  */
110
110
  _getValidSpanConfiguration(config) {
111
111
  const spanHarvestConfig = config.span_event_harvest_config
@@ -89,11 +89,12 @@ class SpanEvent {
89
89
  * The constructed span event will contain extra data depending on the
90
90
  * category of the segment.
91
91
  *
92
- * @param {TraceSegment} segment segment to turn into a span event.
93
- * @param {Transaction} transaction active transaction
94
- * @param {?string} [parentId] ID of the segment's parent.
95
- * @param {boolean} isRoot if segment is root segment
96
- * @param {boolean} inProcessSpans if the segment is in-process, create span
92
+ * @param {object} params params object
93
+ * @param {TraceSegment} params.segment segment to turn into a span event.
94
+ * @param {Transaction} params.transaction active transaction
95
+ * @param {?string} [params.parentId] ID of the segment's parent.
96
+ * @param {boolean} [params.isRoot] if segment is root segment; defaults to `false`
97
+ * @param {boolean} params.inProcessSpans if the segment is in-process, create span
97
98
  * @returns {SpanEvent} The constructed event.
98
99
  */
99
100
  static fromSegment({ segment, transaction, parentId = null, isRoot = false, inProcessSpans }) {
@@ -46,7 +46,7 @@ class StreamingSpanAttributes {
46
46
  *
47
47
  * Does not apply filtering/truncation.
48
48
  *
49
- * @param {object} [attributes]
49
+ * @param {object} [attributes] Attributes to add.
50
50
  * @param {string} [attributes.key] Name of the attribute to be stored.
51
51
  * @param {string|boolean|number} [attributes.value] Value of the attribute to be stored.
52
52
  */
@@ -101,23 +101,25 @@ class StreamingSpanEventAggregator extends Aggregator {
101
101
  *
102
102
  * @param {object} params to function
103
103
  * @param {TraceSegment} params.segment segment to add.
104
- * @param {string} [parms.parentId] GUID of the parent span.
105
104
  * @param {Transaction} params.transaction active transaction
105
+ * @param {string} [params.parentId] GUID of the parent span.
106
106
  * @param {boolean} params.isRoot is segment root segment
107
- * @param params.parentId
108
107
  * @returns {boolean} True if the segment was added, or false if it was discarded.
109
108
  */
110
109
  addSegment({ segment, transaction, parentId, isRoot }) {
111
110
  if (!this.started) {
112
111
  logger.trace('Aggregator has not yet started, dropping span (%s).', segment.name)
113
- return
112
+ return false
114
113
  }
115
114
 
116
115
  const span = StreamingSpanEvent.fromSegment({ segment, transaction, parentId, isRoot, inProcessSpans: this.inProcessSpans })
117
116
 
118
117
  if (span) {
119
118
  this.stream.write(span)
119
+ return true
120
120
  }
121
+
122
+ return false
121
123
  }
122
124
 
123
125
  reconfigure(config) {
@@ -224,7 +224,7 @@ class StreamingHttpSpanEvent extends StreamingSpanEvent {
224
224
  * Currently designed to be sent over grpc via the v1.proto definition.
225
225
  *
226
226
  * @private
227
- * @class.
227
+ * @class
228
228
  */
229
229
  class StreamingDatastoreSpanEvent extends StreamingSpanEvent {
230
230
  /**
@@ -84,7 +84,7 @@ Stats.prototype.incrementCallCount = function incrementCallCount(count) {
84
84
  /**
85
85
  * Fold another summary's statistics into this one.
86
86
  *
87
- * @param other
87
+ * @param {Stats} other other Stats instance
88
88
  */
89
89
  Stats.prototype.merge = function merge(other) {
90
90
  if (other.count && !other.callCount) {
@@ -8,11 +8,16 @@
8
8
  // The expected export of these files is:
9
9
  // 'package-name': [ { path: 'subscriberPath', instrumentations: [] }, ... ]
10
10
  const subscribers = {
11
+ ...require('./subscribers/amqplib/config'),
12
+ ...require('./subscribers/cassandra-driver/config'),
11
13
  ...require('./subscribers/elasticsearch/config'),
14
+ ...require('./subscribers/fastify/config'),
12
15
  ...require('./subscribers/ioredis/config'),
13
16
  ...require('./subscribers/mcp-sdk/config'),
14
17
  ...require('./subscribers/openai/config'),
15
- ...require('./subscribers/pino/config')
18
+ ...require('./subscribers/pino/config'),
19
+ ...require('./subscribers/pg/config'),
20
+ ...require('./subscribers/undici/config')
16
21
  }
17
22
 
18
23
  module.exports = subscribers
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const PropagationSubscriber = require('../propagation')
7
+
8
+ class AcceptMessageSubscriber extends PropagationSubscriber {
9
+ constructor({ agent, logger }) {
10
+ super({ agent, logger, packageName: 'amqplib', channelName: 'nr_acceptMessage', callback: 0 })
11
+ }
12
+ }
13
+
14
+ module.exports = AcceptMessageSubscriber
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MetaSubscriber = require('../meta-subscriber')
7
+ const CHANNEL_METHODS = [
8
+ 'cb_close',
9
+ 'cb_open',
10
+ 'cb_assertQueue',
11
+ 'cb_checkQueue',
12
+ 'cb_deleteQueue',
13
+ 'cb_bindQueue',
14
+ 'nr_unbindQueue',
15
+ 'cb_assertExchange',
16
+ 'cb_checkExchange',
17
+ 'cb_deleteExchange',
18
+ 'cb_bindExchange',
19
+ 'cb_unbindExchange',
20
+ 'cb_cancel',
21
+ 'cb_prefetch',
22
+ 'cb_recover'
23
+ ]
24
+
25
+ class ChannelModelSubscriber extends MetaSubscriber {
26
+ constructor({ agent, logger }) {
27
+ super({ agent, logger, packageName: 'amqplib', channelName: 'channelModel', channels: CHANNEL_METHODS, events: ['asyncEnd'], callback: -1 })
28
+ }
29
+
30
+ handler(_data, ctx) {
31
+ const [, name] = this.channelName.split('_')
32
+ return this.createSegment({
33
+ name: `Channel#${name}`,
34
+ ctx
35
+ })
36
+ }
37
+ }
38
+
39
+ module.exports = ChannelModelSubscriber
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MetaSubscriber = require('../meta-subscriber')
7
+ const CHANNEL_METHODS = [
8
+ 'nr_close',
9
+ 'nr_open',
10
+ 'nr_assertQueue',
11
+ 'nr_checkQueue',
12
+ 'nr_deleteQueue',
13
+ 'nr_bindQueue',
14
+ 'nr_unbindQueue',
15
+ 'nr_assertExchange',
16
+ 'nr_checkExchange',
17
+ 'nr_deleteExchange',
18
+ 'nr_bindExchange',
19
+ 'nr_unbindExchange',
20
+ 'nr_cancel',
21
+ 'nr_prefetch',
22
+ 'nr_recover'
23
+ ]
24
+
25
+ class ChannelModelSubscriber extends MetaSubscriber {
26
+ constructor({ agent, logger }) {
27
+ super({ agent, logger, packageName: 'amqplib', channelName: 'channelModel', channels: CHANNEL_METHODS, events: ['asyncEnd'] })
28
+ }
29
+
30
+ handler(data, ctx) {
31
+ const [, name] = this.channelName.split('_')
32
+ return this.createSegment({
33
+ name: `Channel#${name}`,
34
+ ctx
35
+ })
36
+ }
37
+ }
38
+
39
+ module.exports = ChannelModelSubscriber