newrelic 13.3.2 → 13.4.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 (111) hide show
  1. package/NEWS.md +43 -0
  2. package/THIRD_PARTY_NOTICES.md +11 -11
  3. package/esm-loader.mjs +2 -2
  4. package/lib/attributes.js +4 -4
  5. package/lib/collector/facts.js +1 -1
  6. package/lib/collector/http-agents.js +2 -2
  7. package/lib/collector/parse-response.js +9 -12
  8. package/lib/collector/remote-method.js +4 -5
  9. package/lib/config/formatters.js +2 -3
  10. package/lib/config/index.js +6 -6
  11. package/lib/harvester.js +1 -1
  12. package/lib/header-processing.js +3 -3
  13. package/lib/instrumentation/@node-redis/client.js +1 -1
  14. package/lib/instrumentation/aws-sdk/v2/instrumentation-helper.js +2 -2
  15. package/lib/instrumentation/aws-sdk/v3/common.js +5 -5
  16. package/lib/instrumentation/aws-sdk/v3/dynamodb.js +4 -4
  17. package/lib/instrumentation/aws-sdk/v3/sns.js +9 -9
  18. package/lib/instrumentation/aws-sdk/v3/sqs.js +6 -6
  19. package/lib/instrumentation/core/http-outbound.js +1 -2
  20. package/lib/instrumentation/fastify/spec-builders.js +11 -11
  21. package/lib/instrumentation/fastify.js +4 -4
  22. package/lib/instrumentation/memcached.js +4 -4
  23. package/lib/instrumentation/mongodb.js +2 -2
  24. package/lib/instrumentation/undici.js +3 -3
  25. package/lib/instrumentations.js +0 -2
  26. package/lib/llm-events/aws-bedrock/bedrock-response.js +6 -6
  27. package/lib/llm-events/aws-bedrock/converse-stream-handler.js +1 -1
  28. package/lib/llm-events/aws-bedrock/stream-handler.js +4 -4
  29. package/lib/metrics/index.js +2 -2
  30. package/lib/metrics/normalizer/rule.js +1 -1
  31. package/lib/metrics/normalizer.js +4 -5
  32. package/lib/metrics/recorders/message-transaction.js +3 -3
  33. package/lib/otel/context-manager.js +4 -4
  34. package/lib/otel/metrics/index.js +3 -3
  35. package/lib/otel/setup.js +6 -0
  36. package/lib/otel/trace-propagator.js +1 -1
  37. package/lib/otel/traces/index.js +1 -1
  38. package/lib/prioritized-attributes.js +2 -2
  39. package/lib/serverless/aws-lambda.js +4 -4
  40. package/lib/shim/datastore-shim.js +1 -1
  41. package/lib/shim/message-shim/consume.js +1 -1
  42. package/lib/shim/message-shim/subscribe-consume.js +1 -2
  43. package/lib/shim/promise-shim.js +1 -3
  44. package/lib/shim/shim.js +3 -4
  45. package/lib/shim/transaction-shim.js +0 -1
  46. package/lib/shim/webframework-shim/common.js +2 -4
  47. package/lib/shim/webframework-shim/middleware.js +8 -8
  48. package/lib/spans/span-context.js +1 -1
  49. package/lib/spans/span-event-aggregator.js +2 -2
  50. package/lib/spans/span-event.js +6 -5
  51. package/lib/spans/streaming-span-attributes.js +1 -1
  52. package/lib/spans/streaming-span-event-aggregator.js +1 -2
  53. package/lib/stats/index.js +1 -1
  54. package/lib/subscriber-configs.js +2 -0
  55. package/lib/subscribers/amqplib/accept-message.js +14 -0
  56. package/lib/subscribers/amqplib/callback-model.js +39 -0
  57. package/lib/subscribers/amqplib/channel-model.js +39 -0
  58. package/lib/subscribers/amqplib/config.js +695 -0
  59. package/lib/subscribers/amqplib/connect.js +74 -0
  60. package/lib/subscribers/amqplib/consume.js +54 -0
  61. package/lib/subscribers/amqplib/get-cb.js +16 -0
  62. package/lib/subscribers/amqplib/get.js +50 -0
  63. package/lib/subscribers/amqplib/purge-queue-cb.js +16 -0
  64. package/lib/subscribers/amqplib/purge-queue.js +37 -0
  65. package/lib/subscribers/amqplib/send-message.js +44 -0
  66. package/lib/subscribers/amqplib/send-or-enqueue.js +20 -0
  67. package/lib/subscribers/amqplib/utils.js +53 -0
  68. package/lib/subscribers/application-logs.js +1 -1
  69. package/lib/subscribers/base.js +167 -9
  70. package/lib/subscribers/cassandra-driver/client-batch.js +49 -0
  71. package/lib/subscribers/cassandra-driver/client-connect.js +35 -0
  72. package/lib/subscribers/cassandra-driver/client-each-row.js +36 -0
  73. package/lib/subscribers/cassandra-driver/client-execute.js +36 -0
  74. package/lib/subscribers/cassandra-driver/client-shutdown.js +32 -0
  75. package/lib/subscribers/cassandra-driver/config.js +145 -0
  76. package/lib/subscribers/cassandra-driver/legacy-client-batch.js +22 -0
  77. package/lib/subscribers/cassandra-driver/legacy-client-connect.js +22 -0
  78. package/lib/subscribers/cassandra-driver/legacy-client-each-row.js +22 -0
  79. package/lib/subscribers/cassandra-driver/legacy-client-execute.js +21 -0
  80. package/lib/subscribers/cassandra-driver/legacy-client-shutdown.js +32 -0
  81. package/lib/subscribers/create-config.js +2 -4
  82. package/lib/subscribers/db-query.js +5 -1
  83. package/lib/subscribers/message-consumer.js +146 -0
  84. package/lib/subscribers/message-producer.js +60 -0
  85. package/lib/subscribers/meta-subscriber.js +69 -0
  86. package/lib/subscribers/openai/base.js +27 -1
  87. package/lib/subscribers/openai/config.js +6 -6
  88. package/lib/subscribers/openai/utils.js +9 -11
  89. package/lib/subscribers/propagation.js +43 -0
  90. package/lib/timer.js +1 -1
  91. package/lib/transaction/dt-payload.js +1 -1
  92. package/lib/transaction/handle.js +8 -9
  93. package/lib/transaction/name-state.js +11 -11
  94. package/lib/transaction/trace/segment.js +2 -3
  95. package/lib/util/attribute-types.js +1 -1
  96. package/lib/util/byte-limit.js +1 -1
  97. package/lib/util/cat.js +13 -13
  98. package/lib/util/flatten.js +2 -3
  99. package/lib/util/is-absolute-path.js +1 -1
  100. package/lib/util/is-string.js +15 -0
  101. package/lib/util/logger.js +6 -6
  102. package/lib/util/stream-sink.js +1 -1
  103. package/lib/utilization/docker-info.js +4 -3
  104. package/lib/w3c/traceparent.js +1 -1
  105. package/package.json +2 -2
  106. package/lib/instrumentation/amqplib/amqplib.js +0 -122
  107. package/lib/instrumentation/amqplib/channel-model.js +0 -124
  108. package/lib/instrumentation/amqplib/channel.js +0 -72
  109. package/lib/instrumentation/amqplib/nr-hooks.js +0 -21
  110. package/lib/instrumentation/amqplib/utils.js +0 -143
  111. package/lib/instrumentation/cassandra-driver.js +0 -131
@@ -0,0 +1,69 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const Subscriber = require('./base')
8
+
9
+ /**
10
+ * Used to subscribe to many different events that have the same behavior around
11
+ * segment creation.
12
+ *
13
+ * @typedef {object} MetaSubscriberParams
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
+ * @property {string} channelName A unique name for the diagnostics channel
19
+ * that will be created and monitored.
20
+ * @property {Array} channels list of channels to construct new subscribers
21
+ * @property {Array} events list of events to subscribe to new subscribers
22
+ * @property {number} callback if consumer is callback based, indicates index of callback
23
+ */
24
+ class MetaSubscriber {
25
+ constructor({ agent, logger, packageName, channelName, channels, events, callback }) {
26
+ this.config = agent.config
27
+ this.packageName = packageName
28
+ this.id = `orchestrion:${packageName}:${channelName}`
29
+ this.subscribers = channels.map((name) => {
30
+ const subscriber = new Subscriber({ agent, logger, packageName, channelName: name })
31
+ subscriber.events = events
32
+ subscriber.handler = this.handler.bind(subscriber)
33
+ if (callback !== null) {
34
+ subscriber.callback = callback
35
+ }
36
+ return subscriber
37
+ })
38
+ }
39
+
40
+ get enabled() {
41
+ return this.config.instrumentation[this.packageName].enabled === true
42
+ }
43
+
44
+ enable() {
45
+ for (const subscriber of this.subscribers) {
46
+ subscriber.enable()
47
+ }
48
+ }
49
+
50
+ disable() {
51
+ for (const subscriber of this.subscribers) {
52
+ subscriber.disable()
53
+ }
54
+ }
55
+
56
+ subscribe() {
57
+ for (const subscriber of this.subscribers) {
58
+ subscriber.subscribe()
59
+ }
60
+ }
61
+
62
+ unsubscribe() {
63
+ for (const subscriber of this.subscribers) {
64
+ subscriber.unsubscribe()
65
+ }
66
+ }
67
+ }
68
+
69
+ module.exports = MetaSubscriber
@@ -10,12 +10,38 @@ const Subscriber = require('../base')
10
10
  class OpenAISubscriber extends Subscriber {
11
11
  constructor({ agent, logger, channelName }) {
12
12
  super({ agent, logger, packageName: 'openai', channelName })
13
- this.events = ['asyncEnd']
13
+ this.events = ['asyncEnd', 'end']
14
14
  }
15
15
 
16
16
  get enabled() {
17
17
  return super.enabled && this.config.ai_monitoring?.enabled
18
18
  }
19
+
20
+ /**
21
+ * Temporary fix as `tracePromise` wraps the promise in a native one.
22
+ * We are now wrapping all openai functions in a `traceSync` call.
23
+ * Then we wrap the promise here so it returns the custom promise.
24
+ * OpenAI has a [custom promise](https://github.com/openai/openai-node/blob/master/src/core/api-promise.ts).
25
+ * see: https://github.com/newrelic/node-newrelic/issues/3379
26
+ * see: https://github.com/nodejs/node/issues/59936
27
+ * @param {object} data the data associated with the `end` event
28
+ */
29
+ end(data) {
30
+ const promise = data?.result
31
+ if (!promise.then) {
32
+ return promise
33
+ }
34
+
35
+ return promise.then((result) => {
36
+ data.result = result
37
+ this.channel.asyncEnd.publish(data)
38
+ return result
39
+ }).catch((err) => {
40
+ data.error = err
41
+ this.channel.asyncEnd.publish(data)
42
+ return err
43
+ })
44
+ }
19
45
  }
20
46
 
21
47
  module.exports = OpenAISubscriber
@@ -16,7 +16,7 @@ module.exports = {
16
16
  functionQuery: {
17
17
  className: 'Completions',
18
18
  methodName: 'create',
19
- kind: 'Async'
19
+ kind: 'Sync'
20
20
  }
21
21
  },
22
22
  {
@@ -25,7 +25,7 @@ module.exports = {
25
25
  functionQuery: {
26
26
  className: 'Completions',
27
27
  methodName: 'create',
28
- kind: 'Async'
28
+ kind: 'Sync'
29
29
  }
30
30
  }
31
31
  ]
@@ -39,7 +39,7 @@ module.exports = {
39
39
  functionQuery: {
40
40
  className: 'Responses',
41
41
  methodName: 'create',
42
- kind: 'Async'
42
+ kind: 'Sync'
43
43
  }
44
44
  }
45
45
  ]
@@ -53,7 +53,7 @@ module.exports = {
53
53
  functionQuery: {
54
54
  className: 'APIClient',
55
55
  methodName: 'makeRequest',
56
- kind: 'Async'
56
+ kind: 'Sync'
57
57
  }
58
58
  },
59
59
  {
@@ -62,7 +62,7 @@ module.exports = {
62
62
  functionQuery: {
63
63
  className: 'OpenAI',
64
64
  methodName: 'makeRequest',
65
- kind: 'Async'
65
+ kind: 'Sync'
66
66
  }
67
67
  }
68
68
  ]
@@ -76,7 +76,7 @@ module.exports = {
76
76
  functionQuery: {
77
77
  className: 'Embeddings',
78
78
  methodName: 'create',
79
- kind: 'Async'
79
+ kind: 'Sync'
80
80
  }
81
81
  }
82
82
  ]
@@ -41,7 +41,7 @@ function getMessageFromResponse(response) {
41
41
  * Parses all messages from the OpenAI request object.
42
42
  *
43
43
  * @param {object} request The OpenAI SDK request object
44
- * @param logger
44
+ * @param {Logger} logger instance
45
45
  * @returns {Array<object>} an array of message objects with fields `content` and `role`
46
46
  */
47
47
  function getMessagesFromRequest(request, logger) {
@@ -95,7 +95,7 @@ function recordEvent({ agent, type, msg }) {
95
95
  * @param {object} params input params
96
96
  * @param {Agent} params.agent NR agent instance
97
97
  * @param {Transaction} params.transaction active transaction
98
- * @param params.version
98
+ * @param {string} params.version package version
99
99
  */
100
100
  function addLlmMeta({ agent, transaction, version }) {
101
101
  TRACKING_METRIC = `${TRACKING_METRIC}/${version}`
@@ -112,13 +112,13 @@ function addLlmMeta({ agent, transaction, version }) {
112
112
  *
113
113
  * @param {object} params input params
114
114
  * @param {Agent} params.agent NR agent instance
115
+ * @param {object} params.headers request headers
116
+ * @param {Logger} params.logger logger instance
115
117
  * @param {TraceSegment} params.segment active segment from chat completion
116
118
  * @param {object} params.request chat completion params
117
119
  * @param {object} params.response chat completion response
118
120
  * @param {boolean} [params.err] err if it exists
119
121
  * @param {Transaction} params.transaction active transaction
120
- * @param params.headers
121
- * @param params.logger
122
122
  */
123
123
  function recordChatCompletionMessages({
124
124
  agent,
@@ -189,11 +189,10 @@ function recordChatCompletionMessages({
189
189
 
190
190
  /**
191
191
  * Checks if we should skip instrumentation.
192
- * Currently, it checks if `ai_monitoring.enabled` is true
193
- * and the package version >= 4.0.0
192
+ * Currently, just checks if `ai_monitoring.enabled` is true.
194
193
  *
195
194
  * @param {object} config agent config
196
- * @param logger
195
+ * @param {Logger} logger instance
197
196
  * @returns {boolean} flag if instrumentation should be skipped
198
197
  */
199
198
  function shouldSkipInstrumentation(config, logger) {
@@ -212,14 +211,13 @@ function shouldSkipInstrumentation(config, logger) {
212
211
  * messages.
213
212
  * @param {object} params input params
214
213
  * @param {Agent} params.agent NR agent instance
215
- * @param {Shim} params.shim the current shim instance
214
+ * @param {object} params.headers request headers
215
+ * @param {object} params.logger logger instance
216
216
  * @param {object} params.request chat completion params
217
217
  * @param {object} params.response chat completion response
218
218
  * @param {TraceSegment} params.segment active segment from chat completion
219
219
  * @param {Transaction} params.transaction active transaction
220
- * @param {Error} params.err error if it exists
221
- * @param params.headers
222
- * @param params.logger
220
+ * @param {Error} [params.err] error if it exists
223
221
  */
224
222
  function instrumentStream({ agent, headers, logger, request, response, segment, transaction, err = null }) {
225
223
  if (!agent.config.ai_monitoring.streaming.enabled) {
@@ -0,0 +1,43 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const Subscriber = require('./base')
8
+
9
+ /**
10
+ * This subscriber is purely for propagation of async context within the `asyncStart` event.
11
+ * This will be typically used in a callback based scenario where there is async code getting scheduled
12
+ * but not bound to the context.
13
+ */
14
+ class PropagationSubscriber extends Subscriber {
15
+ constructor({ agent, logger, packageName, channelName, callback }) {
16
+ super({ agent, logger, packageName, channelName })
17
+ this.callback = callback
18
+ this.propagateTx = true
19
+ this.events = ['asyncStart', 'asyncEnd']
20
+ }
21
+
22
+ enable() {
23
+ super.enable()
24
+ this.channel.asyncStart.bindStore(this.store, (data) => {
25
+ const { transaction, segment } = data
26
+ const ctx = this.agent.tracer.getContext()
27
+
28
+ if (!(transaction && segment)) {
29
+ this.logger.trace('No active transaction/segment, returning existing context')
30
+ return ctx
31
+ }
32
+ const newCtx = ctx.enterSegment({ transaction, segment })
33
+ return newCtx
34
+ })
35
+ }
36
+
37
+ disable() {
38
+ super.disable()
39
+ this.channel.asyncStart.unbindStore(this.store)
40
+ }
41
+ }
42
+
43
+ module.exports = PropagationSubscriber
package/lib/timer.js CHANGED
@@ -220,7 +220,7 @@ Timer.prototype.startedRelativeTo = function startedRelativeTo(other) {
220
220
  /**
221
221
  * Returns true if this timer ends after the other.
222
222
  *
223
- * @param other
223
+ * @param {Timer} other other timer
224
224
  */
225
225
  Timer.prototype.endsAfter = function compare(other) {
226
226
  return this.getDurationInMillis() + this.start > other.getDurationInMillis() + other.start
@@ -15,7 +15,7 @@ module.exports = class DistributedTracePayload {
15
15
  * The class responsible for producing distributed trace payloads.
16
16
  * Created by calling {@link TransactionHandle#_createDistributedTracePayload}.
17
17
  *
18
- * @param payload
18
+ * @param {Object} payload DT payload
19
19
  * @class
20
20
  */
21
21
  constructor(payload) {
@@ -14,8 +14,8 @@ class TransactionHandle {
14
14
  * A light representation of a transaction instance, returned by calling
15
15
  * {@link API#getTransaction}.
16
16
  *
17
- * @param transaction
18
- * @param metrics
17
+ * @param {Transaction} transaction the associated transaction
18
+ * @param {Metrics} metrics class instance
19
19
  * @class
20
20
  */
21
21
  constructor(transaction, metrics) {
@@ -26,7 +26,7 @@ class TransactionHandle {
26
26
  /**
27
27
  * End the transaction.
28
28
  *
29
- * @param {Function} callback
29
+ * @param {Function} callback The function to call after ending the transaction.
30
30
  */
31
31
  end(callback) {
32
32
  const tx = this._transaction.end()
@@ -57,11 +57,10 @@ class TransactionHandle {
57
57
  * W3C TraceContext format is preferred over the NewRelic DT format.
58
58
  * NewRelic DT format will be used if no `traceparent` header is found.
59
59
  *
60
- * @param @param {string} [transportType='Unknown'] - The transport type that delivered the trace.
61
- * @param transportType
60
+ * @param {string} [transportType] - The transport type that delivered the trace; defaults to 'Unknown'.
62
61
  * @param {object} headers - Headers to search for supported formats. Keys must be lowercase.
63
62
  */
64
- acceptDistributedTraceHeaders(transportType, headers) {
63
+ acceptDistributedTraceHeaders(transportType = 'Unknown', headers) {
65
64
  incrementApiSupportMetric(this._metrics, 'acceptDistributedTraceHeaders')
66
65
  return this._transaction.acceptDistributedTraceHeaders(transportType, headers)
67
66
  }
@@ -69,7 +68,7 @@ class TransactionHandle {
69
68
  /**
70
69
  * Inserts distributed trace headers into the provided headers map.
71
70
  *
72
- * @param {object} headers
71
+ * @param {object} headers DT headers
73
72
  */
74
73
  insertDistributedTraceHeaders(headers) {
75
74
  incrementApiSupportMetric(this._metrics, 'insertDistributedTraceHeaders')
@@ -82,8 +81,8 @@ module.exports = TransactionHandle
82
81
  /**
83
82
  *
84
83
  * @private
85
- * @param metrics
86
- * @param functionName
84
+ * @param {Metrics} metrics class instance
85
+ * @param {string} functionName name of function to increment the metric of
87
86
  */
88
87
  function incrementApiSupportMetric(metrics, functionName) {
89
88
  if (!metrics) {
@@ -29,10 +29,10 @@ const STATUS_CODE_NAMES = {
29
29
  /**
30
30
  * Manages transaction names using a stack of paths.
31
31
  *
32
- * @param prefix
33
- * @param verb
34
- * @param delimiter
35
- * @param path
32
+ * @param {string} prefix metric prefix
33
+ * @param {string} verb HTTP verb
34
+ * @param {string} delimiter delimiter character
35
+ * @param {string} path path element
36
36
  * @class
37
37
  */
38
38
  function NameState(prefix, verb, delimiter, path) {
@@ -72,7 +72,7 @@ NameState.prototype.markPath = function markPath() {
72
72
  /**
73
73
  * Sets the metric prefix (i.e. Expressjs).
74
74
  *
75
- * @param prefix
75
+ * @param {string} prefix metric prefix
76
76
  */
77
77
  NameState.prototype.setPrefix = function setPrefix(prefix) {
78
78
  if (this._frozen) {
@@ -89,7 +89,7 @@ NameState.prototype.setPrefix = function setPrefix(prefix) {
89
89
  /**
90
90
  * Sets the HTTP verb (i.e. GET/POST/PUT)
91
91
  *
92
- * @param verb
92
+ * @param {string} verb HTTP verb
93
93
  */
94
94
  NameState.prototype.setVerb = function setVerb(verb) {
95
95
  if (!this._frozen) {
@@ -100,7 +100,7 @@ NameState.prototype.setVerb = function setVerb(verb) {
100
100
  /**
101
101
  * Sets the delimiter character used to separate the http verb from the path.
102
102
  *
103
- * @param delimiter
103
+ * @param {string} delimiter delimiter character
104
104
  */
105
105
  NameState.prototype.setDelimiter = function setDelimiter(delimiter) {
106
106
  if (!this._frozen) {
@@ -115,8 +115,8 @@ NameState.prototype.isEmpty = function isEmpty() {
115
115
  /**
116
116
  * Pushes a new path element onto the naming stack.
117
117
  *
118
- * @param path
119
- * @param params
118
+ * @param {string} path path element
119
+ * @param {Object} params to add to pathStack
120
120
  */
121
121
  NameState.prototype.appendPath = function appendPath(path, params) {
122
122
  if (!this._frozen && path != null) {
@@ -134,8 +134,8 @@ NameState.prototype.appendPath = function appendPath(path, params) {
134
134
  * Pushes a new path element onto the naming stack if the stack is
135
135
  * empty.
136
136
  *
137
- * @param path
138
- * @param params
137
+ * @param {string} path path element
138
+ * @param {Object} params to add with appendPath
139
139
  */
140
140
  NameState.prototype.appendPathIfEmpty = function appendPathIfEmpty(path, params) {
141
141
  if (!this._frozen && this.isEmpty()) {
@@ -138,7 +138,7 @@ TraceSegment.prototype.setNameFromTransaction = function setNameFromTransaction(
138
138
  * finally, marking the trace segment as being a web segment copies the
139
139
  * segment's parameters onto the transaction.
140
140
  * @param {Transaction} transaction The transaction to which this segment will be bound.
141
- * @param obfuscatedUrl
141
+ * @param {object} obfuscatedUrl The obfuscated URL for the request.
142
142
  */
143
143
  TraceSegment.prototype.markAsWeb = function markAsWeb(transaction, obfuscatedUrl) {
144
144
  this.setNameFromTransaction(transaction)
@@ -270,11 +270,10 @@ function getExclusiveDurationInMillis(trace) {
270
270
  * @param {string} params.protocol protocol of request(i.e. `http:`, `grpc:`)
271
271
  * @param {string} params.hostname hostname of request(no port)
272
272
  * @param {string} params.host host of request(hostname + port)
273
- * @param [string] params.port port of request if applicable
273
+ * @param {string} params.port port of request if applicable
274
274
  * @param {string} params.path uri of request
275
275
  * @param {string} [params.method] method of request
276
276
  * @param {object} [params.queryParams] query parameters of request
277
- * @param params.port
278
277
  */
279
278
  TraceSegment.prototype.captureExternalAttributes = function captureExternalAttributes({
280
279
  protocol,
@@ -11,7 +11,7 @@ const VALID_ATTR_TYPES = new Set(['string', 'number', 'boolean'])
11
11
  * Checks incoming attribute value against valid types:
12
12
  * string, number, & boolean.
13
13
  *
14
- * @param {*} val
14
+ * @param {*} val value to check type of
15
15
  * @returns {boolean}
16
16
  */
17
17
  function isValidType(val) {
@@ -21,7 +21,7 @@ function isValidLength(str, limit) {
21
21
  * 0 if the string is at the limit
22
22
  * <1 if the string is shorter than the limit
23
23
  *
24
- * @param {string} str
24
+ * @param {string} str - Object key name or value
25
25
  * @param {number} limit - String byte limit
26
26
  */
27
27
  function compareLength(str, limit) {
package/lib/util/cat.js CHANGED
@@ -32,11 +32,11 @@ const MATCH_CAT_APP_DATA_HEADER = new RegExp(
32
32
  /**
33
33
  * Decodes the CAT id and transaction headers from incoming request
34
34
  *
35
- * @param {object} headers incoming headers
36
- * @param id
37
- * @param transactionId
35
+ * @param {object} id CAT id
36
+ * @param {object} transactionId transaction header id
38
37
  * @param {string} encKey config.encoding_key used to decode CAT headers
39
- * @param {object} { externalId, externalTransaction }
38
+ *
39
+ * @returns {object} { externalId, externalTransaction }
40
40
  */
41
41
  cat.parseCatData = function parseCatData(id, transactionId, encKey) {
42
42
  if (!encKey) {
@@ -109,10 +109,10 @@ cat.assignCatToTransaction = function assignCatToTransaction(
109
109
  * for incoming requests
110
110
  *
111
111
  * @param {object} config agent config
112
- * @param {Transaction} transaction
113
- * @param {string} contentLength
112
+ * @param {Transaction} transaction current transaction
113
+ * @param {string} contentLength length of content
114
114
  * @param {boolean} useMqHeaders flag to return proper headers for MQ compliance
115
- * @returns {object} { key, data} to add as header
115
+ * @returns {object} { key, data } to add as header
116
116
  */
117
117
  cat.encodeAppData = function encodeAppData(config, transaction, contentLength, useMqHeaders) {
118
118
  let appData = null
@@ -147,7 +147,7 @@ cat.encodeAppData = function encodeAppData(config, transaction, contentLength, u
147
147
  * Adds CAT headers to outbound request.
148
148
  *
149
149
  * @param {object} config agent config
150
- * @param {Transaction} transaction
150
+ * @param {Transaction} transaction current transaction
151
151
  * @param {object} headers object that contains headers the agent is adding to client request
152
152
  * @param {boolean} useMqHeaders flag to return proper headers for MQ compliance
153
153
  */
@@ -189,9 +189,9 @@ cat.addCatHeaders = function addCatHeaders(config, transaction, headers, useMqHe
189
189
 
190
190
  /**
191
191
  * Find the CAT id, transaction, app data headers
192
- * from the headers of either HTTP or MQ request
192
+ * from the headers of either HTTP or MQ request.
193
193
  *
194
- * @param {object} headers
194
+ * @param {object} headers HTTP/MQ headers
195
195
  * @returns {object} { id, transactionId, appData }
196
196
  */
197
197
  cat.extractCatHeaders = function extractCatHeaders(headers) {
@@ -220,8 +220,7 @@ cat.extractCatHeaders = function extractCatHeaders(headers) {
220
220
  * Extracts the account Id from CAT data and verifies if it is
221
221
  * a trusted account id
222
222
  *
223
- * @param {object} CAT data
224
- * @param data
223
+ * @param {object} data CAT data
225
224
  * @param {Array} trustedAccounts from config
226
225
  * @returns {boolean}
227
226
  */
@@ -240,7 +239,8 @@ cat.isTrustedAccountId = function isTrustedAccountId(data, trustedAccounts) {
240
239
  *
241
240
  * @param {object} config agent config
242
241
  * @param {string} obfAppData encoded app data to parse and use
243
- * @param {Array} decoded app data header
242
+ *
243
+ * @returns {Array} decoded app data header
244
244
  */
245
245
  cat.parseAppData = function parseAppData(config, obfAppData) {
246
246
  if (!config.encoding_key) {
@@ -16,8 +16,8 @@ exports.keys = flatKeys
16
16
  * @private
17
17
  * @param {object} result Object to place key-value pairs into, normally called with `{}`.
18
18
  * @param {string} prefix Prefix for keys, normally called with `''`.
19
- * @param seen
20
19
  * @param {object} obj Object to be flattened.
20
+ * @param {Array} seen Array of seen objects to prevent circular references.
21
21
  * @returns {object} Object with flattened key-value pairs
22
22
  */
23
23
  function flatten(result, prefix, obj, seen) {
@@ -45,8 +45,7 @@ function flatten(result, prefix, obj, seen) {
45
45
  * @private
46
46
  * @param {object} obj - The object to get the flat keys of.
47
47
  * @param {string} prefix - A prefix for the keys, usually `''`.
48
- * @param arrayIdxs
49
- * @param {boolean} arrayIdx - Flag indicating if array indexes should be iterated.
48
+ * @param {boolean} arrayIdxs - Flag indicating if array indexes should be iterated.
50
49
  * @returns {Array.<string>} An array of keys names.
51
50
  */
52
51
  function flatKeys(obj, prefix, arrayIdxs) {
@@ -19,7 +19,7 @@ module.exports = function isAbsolutePath(target) {
19
19
  }
20
20
 
21
21
  const suffix = target.slice(-4)
22
- /* eslint-disable-next-line */
22
+
23
23
  if (suffix.slice(-3) !== '.js' && suffix !== '.cjs' && suffix !== '.mjs') {
24
24
  return false
25
25
  }
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ /**
9
+ * Tests if argument passed in is a string or String object
10
+ * @param {*} data to check if it is a string
11
+ * @returns {boolean} if string or string object
12
+ */
13
+ module.exports = function isString(data) {
14
+ return typeof data === 'string' || data instanceof String
15
+ }
@@ -253,14 +253,14 @@ Logger.prototype._read = function _read() {
253
253
  }
254
254
 
255
255
  /**
256
- * For performance reasons we do not support %j because we will have
256
+ * For performance reasons, we do not support %j because we will have
257
257
  * already converted the objects to strings.
258
- * Returns a boolean representing the status of the write
259
- * (success/failure)
260
258
  *
261
- * @param level
262
- * @param args
263
- * @param extra
259
+ * @param {string} level log entry level
260
+ * @param {Array} args arguments to stringify
261
+ * @param {Object} extra data to log
262
+ *
263
+ * @returns {boolean} True if the log was written successfully, false otherwise.
264
264
  */
265
265
  Logger.prototype.write = function write(level, args, extra) {
266
266
  if (this._nestedLog) {
@@ -26,7 +26,7 @@ const util = require('util')
26
26
  * contract and the callback will be fired when the stream has been completely
27
27
  * read.
28
28
  *
29
- * @param callback
29
+ * @param {function} callback Function to call when stream has been read.
30
30
  */
31
31
  function StreamSink(callback) {
32
32
  EventEmitter.call(this)
@@ -58,9 +58,10 @@ function recordBootIdError(agent) {
58
58
  /**
59
59
  * Utility function to parse a Docker boot id from a cgroup proc file.
60
60
  *
61
- * @param {Buffer} data The information from the proc file.
62
- * @param {object} agent Newrelic agent instance.
63
- * @param {Function} callback Typical error first callback. Second parameter
61
+ * @param {Object} params params object
62
+ * @param {Buffer} params.data The information from the proc file.
63
+ * @param {Agent} params.agent Newrelic agent instance.
64
+ * @param {Function} params.callback Typical error first callback. Second parameter
64
65
  * is the boot id as a string.
65
66
  *
66
67
  * @returns {*}
@@ -90,7 +90,7 @@ class Traceparent {
90
90
  *
91
91
  * @link https://opentelemetry.io/docs/concepts/signals/traces/#span-context
92
92
  *
93
- * @param {object} spanContext
93
+ * @param {object} spanContext OTEL span context
94
94
  *
95
95
  * @returns {Traceparent}
96
96
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "13.3.2",
3
+ "version": "13.4.0",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [
@@ -201,7 +201,7 @@
201
201
  "#test/assert": "./test/lib/custom-assertions/index.js"
202
202
  },
203
203
  "dependencies": {
204
- "@apm-js-collab/tracing-hooks": "^0.1.0",
204
+ "@apm-js-collab/tracing-hooks": "^0.3.1",
205
205
  "@grpc/grpc-js": "^1.13.2",
206
206
  "@grpc/proto-loader": "^0.7.5",
207
207
  "@newrelic/security-agent": "^2.4.2",