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
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const DbQuerySubscriber = require('../db-query')
9
+
10
+ /**
11
+ * Subscribes to the `execute` event in `cassandra-driver`
12
+ * and extracts relevant information from the query.
13
+ */
14
+ class CassandraEachRowSubscriber extends DbQuerySubscriber {
15
+ constructor({ agent, logger, channelName = 'nr_eachRow' }) {
16
+ super({ agent, logger, channelName, packageName: 'cassandra-driver', system: 'Cassandra' })
17
+ this.events = ['asyncEnd']
18
+ }
19
+
20
+ handler(data, ctx) {
21
+ const { self, arguments: args } = data
22
+ this.queryString = args?.[0]
23
+ this.setParameters(self)
24
+ return super.handler(data, ctx)
25
+ }
26
+
27
+ setParameters(self) {
28
+ this.parameters = {}
29
+ this.parameters.product = this.system
30
+ this.parameters.database_name = self?.keyspace
31
+ this.parameters.host = self?.controlConnection?.connection?.address
32
+ this.parameters.port_path_or_id = self?.controlConnection?.connection?.port
33
+ }
34
+ }
35
+
36
+ module.exports = CassandraEachRowSubscriber
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const DbQuerySubscriber = require('../db-query')
9
+
10
+ /**
11
+ * Subscribes to the `execute` event in `cassandra-driver`
12
+ * and extracts relevant information from the query.
13
+ */
14
+ class CassandraExecuteSubscriber extends DbQuerySubscriber {
15
+ constructor({ agent, logger, channelName = 'nr_execute' }) {
16
+ super({ agent, logger, channelName, packageName: 'cassandra-driver', system: 'Cassandra' })
17
+ this.events = ['asyncEnd']
18
+ }
19
+
20
+ handler(data, ctx) {
21
+ const { self, arguments: args } = data
22
+ this.queryString = args?.[0]
23
+ this.setParameters(self)
24
+ return super.handler(data, ctx)
25
+ }
26
+
27
+ setParameters(self) {
28
+ this.parameters = {}
29
+ this.parameters.product = this.system
30
+ this.parameters.database_name = self?.keyspace
31
+ this.parameters.host = self?.controlConnection?.connection?.address
32
+ this.parameters.port_path_or_id = self?.controlConnection?.connection?.port
33
+ }
34
+ }
35
+
36
+ module.exports = CassandraExecuteSubscriber
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const DbOperationSubscriber = require('../db-operation')
9
+
10
+ /**
11
+ * Subscribes to the `shutdown` event in `cassandra-driver`.
12
+ */
13
+ class CassandraShutdownSubscriber extends DbOperationSubscriber {
14
+ constructor({ agent, logger, channelName = 'nr_shutdown' }) {
15
+ super({ agent, logger, channelName, packageName: 'cassandra-driver', system: 'Cassandra' })
16
+ this.events = ['asyncStart', 'asyncEnd']
17
+ this.operation = 'shutdown'
18
+ }
19
+
20
+ handler(data, ctx) {
21
+ const { self } = data
22
+ this.setParameters(self)
23
+ return super.handler(data, ctx)
24
+ }
25
+
26
+ setParameters() {
27
+ this.parameters = {}
28
+ this.parameters.product = this.system
29
+ }
30
+ }
31
+
32
+ module.exports = CassandraShutdownSubscriber
@@ -0,0 +1,145 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ // there are diff subscribers for handling callback based code. In 4.4.0+ you can specify callbacks but they're all wrapped around promises so you don't have to wrap the callback in that case
7
+ const legacyBatchConfig = {
8
+ path: './cassandra-driver/legacy-client-batch.js',
9
+ instrumentations: [
10
+ {
11
+ channelName: 'nr_legacyBatch',
12
+ module: { name: 'cassandra-driver', versionRange: '>=3.4.0 <4.4.0', filePath: 'lib/client.js' },
13
+ functionQuery: {
14
+ expressionName: 'batch',
15
+ kind: 'Async'
16
+ }
17
+ },
18
+ ]
19
+ }
20
+
21
+ const legacyConnectConfig = {
22
+ path: './cassandra-driver/legacy-client-connect.js',
23
+ instrumentations: [
24
+ {
25
+ channelName: 'nr_legacyConnect',
26
+ module: { name: 'cassandra-driver', versionRange: '>=3.4.0 <4.4.0', filePath: 'lib/client.js' },
27
+ functionQuery: {
28
+ expressionName: 'connect',
29
+ kind: 'Async'
30
+ }
31
+ },
32
+ ]
33
+ }
34
+
35
+ const legacyExecuteConfig = {
36
+ path: './cassandra-driver/legacy-client-execute.js',
37
+ instrumentations: [
38
+ {
39
+ channelName: 'nr_legacyExecute',
40
+ module: { name: 'cassandra-driver', versionRange: '>=3.4.0 <4.4.0', filePath: 'lib/client.js' },
41
+ functionQuery: {
42
+ expressionName: 'execute',
43
+ kind: 'Async'
44
+ }
45
+ }
46
+ ]
47
+ }
48
+
49
+ const legacyEachRowConfig = {
50
+ path: './cassandra-driver/legacy-client-each-row.js',
51
+ instrumentations: [
52
+ {
53
+ channelName: 'nr_legacyEachRow',
54
+ module: { name: 'cassandra-driver', versionRange: '>=3.4.0 <4.4.0', filePath: 'lib/client.js' },
55
+ functionQuery: {
56
+ expressionName: 'eachRow',
57
+ kind: 'Async'
58
+ }
59
+ },
60
+ ]
61
+ }
62
+
63
+ const legacyShutdownConfig = {
64
+ path: './cassandra-driver/legacy-client-shutdown.js',
65
+ instrumentations: [
66
+ {
67
+ channelName: 'nr_legacyShutdown',
68
+ module: { name: 'cassandra-driver', versionRange: '>=3.4.0 <4.4.0', filePath: 'lib/client.js' },
69
+ functionQuery: {
70
+ expressionName: 'shutdown',
71
+ kind: 'Async'
72
+ }
73
+ },
74
+ ]
75
+ }
76
+
77
+ const batchConfig = {
78
+ path: './cassandra-driver/client-batch.js',
79
+ instrumentations: [
80
+ {
81
+ channelName: 'nr_batch',
82
+ module: { name: 'cassandra-driver', versionRange: '>=4.4.0', filePath: 'lib/client.js' },
83
+ functionQuery: {
84
+ expressionName: '_batch',
85
+ kind: 'Async'
86
+ }
87
+ },
88
+ ]
89
+ }
90
+
91
+ const connectConfig = {
92
+ path: './cassandra-driver/client-connect.js',
93
+ instrumentations: [
94
+ {
95
+ channelName: 'nr_connect',
96
+ module: { name: 'cassandra-driver', versionRange: '>=4.4.0', filePath: 'lib/client.js' },
97
+ functionQuery: {
98
+ expressionName: 'connect',
99
+ kind: 'Async'
100
+ }
101
+ },
102
+ ]
103
+ }
104
+
105
+ const executeConfig = {
106
+ path: './cassandra-driver/client-execute.js',
107
+ instrumentations: [
108
+ {
109
+ channelName: 'nr_execute',
110
+ module: { name: 'cassandra-driver', versionRange: '>=4.4.0', filePath: 'lib/client.js' },
111
+ functionQuery: {
112
+ expressionName: '_execute',
113
+ kind: 'Async'
114
+ }
115
+ }
116
+ ]
117
+ }
118
+
119
+ const shutdownConfig = {
120
+ path: './cassandra-driver/client-shutdown.js',
121
+ instrumentations: [
122
+ {
123
+ channelName: 'nr_shutdown',
124
+ module: { name: 'cassandra-driver', versionRange: '>=4.4.0', filePath: 'lib/client.js' },
125
+ functionQuery: {
126
+ expressionName: 'shutdown',
127
+ kind: 'Async'
128
+ }
129
+ },
130
+ ]
131
+ }
132
+
133
+ module.exports = {
134
+ 'cassandra-driver': [
135
+ batchConfig,
136
+ connectConfig,
137
+ executeConfig,
138
+ shutdownConfig,
139
+ legacyBatchConfig,
140
+ legacyEachRowConfig,
141
+ legacyConnectConfig,
142
+ legacyExecuteConfig,
143
+ legacyShutdownConfig
144
+ ]
145
+ }
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const CassandraBatchSubscriber = require('./client-batch')
9
+
10
+ /**
11
+ * Subscribes to the `batch` event in `cassandra-driver`
12
+ * and extracts relevant information from the queries.
13
+ */
14
+ class LegacyCassandraBatchSubscriber extends CassandraBatchSubscriber {
15
+ constructor({ agent, logger }) {
16
+ super({ agent, logger, channelName: 'nr_legacyBatch' })
17
+ this.events = ['asyncStart', 'asyncEnd']
18
+ this.callback = -1
19
+ }
20
+ }
21
+
22
+ module.exports = LegacyCassandraBatchSubscriber
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const CassandraConnectSubscriber = require('./client-connect')
9
+
10
+ /**
11
+ * Subscribes to the `connect` event in `cassandra-driver`'s `Client`.
12
+ */
13
+ class LegacyCassandraConnectSubscriber extends CassandraConnectSubscriber {
14
+ constructor({ agent, logger }) {
15
+ super({ agent, logger, channelName: 'nr_legacyConnect' })
16
+ this.events = ['asyncStart', 'asyncEnd']
17
+ this.internal = true
18
+ this.callback = -1
19
+ }
20
+ }
21
+
22
+ module.exports = LegacyCassandraConnectSubscriber
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const CassandraEachRowSubscriber = require('./client-each-row')
9
+
10
+ /**
11
+ * Subscribes to the `execute` event in `cassandra-driver`
12
+ * and extracts relevant information from the query.
13
+ */
14
+ class LegacyCassandraEachRowSubscriber extends CassandraEachRowSubscriber {
15
+ constructor({ agent, logger }) {
16
+ super({ agent, logger, channelName: 'nr_legacyEachRow' })
17
+ this.events = ['asyncStart', 'asyncEnd']
18
+ this.callback = -1
19
+ }
20
+ }
21
+
22
+ module.exports = LegacyCassandraEachRowSubscriber
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const CassandraExecuteSubscriber = require('./client-execute')
9
+ /**
10
+ * Subscribes to the `execute` event in `cassandra-driver`
11
+ * and extracts relevant information from the query.
12
+ */
13
+ class LegacyCassandraExecuteSubscriber extends CassandraExecuteSubscriber {
14
+ constructor({ agent, logger }) {
15
+ super({ agent, logger, channelName: 'nr_legacyExecute' })
16
+ this.events = ['asyncStart', 'asyncEnd']
17
+ this.callback = -1
18
+ }
19
+ }
20
+
21
+ module.exports = LegacyCassandraExecuteSubscriber
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const CassandraShutdownSubscriber = require('./client-shutdown')
9
+
10
+ /**
11
+ * Subscribes to the `shutdown` event in `cassandra-driver`.
12
+ */
13
+ class LegacyCassandraShutdownSubscriber extends CassandraShutdownSubscriber {
14
+ constructor({ agent, logger }) {
15
+ super({ agent, logger, channelName: 'nr_legacyShutdown' })
16
+ this.events = ['asyncStart', 'asyncEnd']
17
+ this.callback = -1
18
+ }
19
+
20
+ handler(data, ctx) {
21
+ const { self } = data
22
+ this.setParameters(self)
23
+ return super.handler(data, ctx)
24
+ }
25
+
26
+ setParameters() {
27
+ this.parameters = {}
28
+ this.parameters.product = this.system
29
+ }
30
+ }
31
+
32
+ module.exports = LegacyCassandraShutdownSubscriber
@@ -6,22 +6,20 @@
6
6
  'use strict'
7
7
 
8
8
  /**
9
- * Builds a set of packages and instrumentaions from a list of subscriber configurations.
9
+ * Builds a set of packages and instrumentations from a list of subscriber configurations.
10
10
  *
11
11
  * @param {Array} subscribers - An array of subscriber objects, each containing a package name and an array of instrumentations.
12
- * @returns {Object} An object containing a Set of unique package names and an array of instrumentations.
12
+ * @returns {object} An object containing a Set of unique package names and an array of instrumentations.
13
13
  */
14
14
  function createSubscribersConfig (subscribers = []) {
15
- const packages = new Set()
16
15
  const instrumentations = []
17
- for (const [packageName, subscriberList] of Object.entries(subscribers)) {
18
- packages.add(packageName)
16
+ for (const subscriberList of Object.values(subscribers)) {
19
17
  for (const subscriber of subscriberList) {
20
18
  instrumentations.push(...subscriber.instrumentations)
21
19
  }
22
20
  }
23
21
 
24
- return { packages, instrumentations }
22
+ return { instrumentations }
25
23
  }
26
24
 
27
25
  module.exports = createSubscribersConfig
@@ -7,7 +7,19 @@ const DbSubscriber = require('./db')
7
7
  const recordOperationMetrics = require('../metrics/recorders/database-operation')
8
8
  const { DB } = require('../metrics/names')
9
9
 
10
+ /**
11
+ * Subscriber for database operation events e.g. `connect`.
12
+ */
10
13
  class DbOperationSubscriber extends DbSubscriber {
14
+ /**
15
+ * On a tracing channel event specified by `this.events`,
16
+ * this handler will create a new segment with the name
17
+ * `${DB.OPERATION}/${this.system}/${this.operation}`.
18
+ *
19
+ * @param {*} data event data
20
+ * @param {Context} ctx our context
21
+ * @returns {Context} updated context with the new segment
22
+ */
11
23
  handler(data, ctx) {
12
24
  const name = `${DB.OPERATION}/${this.system}/${this.operation}`
13
25
  return this.createSegment({
@@ -13,7 +13,11 @@ class DbQuerySubscriber extends DbSubscriber {
13
13
  handler(data, ctx) {
14
14
  const queryString = this.queryString
15
15
  const parsed = this.parseQueryString(queryString)
16
- const name = `${DB.STATEMENT}/${this.system}/${parsed.collection}/${parsed.operation}`
16
+ let name = `${DB.STATEMENT}/${this.system}/${parsed.collection}/${parsed.operation}`
17
+ if (this.isBatch) {
18
+ name += '/batch'
19
+ }
20
+
17
21
  return this.createSegment({
18
22
  name,
19
23
  ctx,
@@ -0,0 +1,89 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
8
+ const dc = require('node:diagnostics_channel')
9
+
10
+ /**
11
+ * The baseline parameters available to all subscribers.
12
+ *
13
+ * @typedef {object} SubscriberParams
14
+ * @property {object} agent A New Relic Node.js agent instance.
15
+ * @property {object} logger An agent logger instance.
16
+ * @property {string} packageName The package name being instrumented.
17
+ * This is what a developer would provide to the `require` function.
18
+ */
19
+
20
+ /**
21
+ * @typedef {object} ChannelDescriptor
22
+ * @property {string} channel The fully qualified name of a diagnostic channel,
23
+ * e.g. `undici:request:create`.
24
+ * @property {Function} hook The function to execute when the channel is fired.
25
+ * This function will be bound to the `Subscriber` instance.
26
+ */
27
+
28
+ /**
29
+ * @property {object} agent A New Relic Node.js agent instance.
30
+ * @property {ChannelDescriptor[]} channels The channels to subscribe to.
31
+ * @property {object} logger An agent logger instance.
32
+ * @property {object} config The agent configuration object.
33
+ * @property {string} id The name of the module being instrumented.
34
+ * This is the same string one would pass to the `require` function.
35
+ */
36
+ class Subscriber {
37
+ /**
38
+ * @param {SubscriberParams} params to function
39
+ */
40
+ constructor({ agent, logger, packageName }) {
41
+ this.agent = agent
42
+ this.logger = logger.child({ component: `${packageName}-subscriber` })
43
+ this.config = agent.config
44
+ this.id = packageName
45
+ }
46
+
47
+ set channels(channels) {
48
+ if (!Array.isArray(channels)) {
49
+ throw new Error('channels must be a collection of with propertiesof channel and hook')
50
+ }
51
+ this._channels = channels
52
+ }
53
+
54
+ get channels() {
55
+ return this._channels
56
+ }
57
+
58
+ /**
59
+ * Checks if the subscriber is enabled based on the agent's configuration.
60
+ * @returns {boolean} if subscriber is enabled
61
+ */
62
+ get enabled() {
63
+ return this.config.instrumentation[this.id].enabled === true
64
+ }
65
+
66
+ enable() {
67
+ return true
68
+ }
69
+
70
+ disable() {
71
+ return true
72
+ }
73
+
74
+ subscribe() {
75
+ this.channels.forEach(({ channel, hook }, index) => {
76
+ const boundHook = hook.bind(this)
77
+ dc.subscribe(channel, boundHook)
78
+ this.channels[index].boundHook = boundHook
79
+ })
80
+ }
81
+
82
+ unsubscribe() {
83
+ this.channels.forEach(({ channel, boundHook }) => {
84
+ dc.unsubscribe(channel, boundHook)
85
+ })
86
+ }
87
+ }
88
+
89
+ module.exports = Subscriber
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const Subscriber = require('../base')
9
+ /**
10
+ * These are the events that occur during a fastify
11
+ * request
12
+ * see: https://www.fastify.io/docs/latest/Lifecycle/
13
+ *
14
+ * Note: preSerialization and onSend happen after the route handler
15
+ * executes. `onResponse` does not execute until after the client
16
+ * sends the response so it'll never be in scope of the transaction
17
+ */
18
+ const REQUEST_HOOKS = [
19
+ 'onRequest',
20
+ 'preParsing',
21
+ 'preValidation',
22
+ 'preHandler',
23
+ 'preSerialization',
24
+ 'onSend',
25
+ 'onResponse',
26
+ 'onError'
27
+ ]
28
+ const { handlerWrapper } = require('./common')
29
+
30
+ class FastifyAddHookSubscriber extends Subscriber {
31
+ constructor({ agent, logger }) {
32
+ super({ agent, logger, packageName: 'fastify', channelName: 'nr_addHook' })
33
+ this.requireActiveTx = false
34
+ }
35
+
36
+ handler(data) {
37
+ const { arguments: args } = data
38
+ const [hookName, fn] = args
39
+ if (REQUEST_HOOKS.includes(hookName)) {
40
+ const wrappedFn = handlerWrapper({ handler: fn, hookName, self: this })
41
+ data.arguments[1] = wrappedFn
42
+ }
43
+ }
44
+ }
45
+
46
+ module.exports = FastifyAddHookSubscriber