newrelic 13.1.0 → 13.2.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 (58) hide show
  1. package/NEWS.md +46 -0
  2. package/README.md +2 -4
  3. package/THIRD_PARTY_NOTICES.md +3 -3
  4. package/esm-loader.mjs +9 -1
  5. package/index.js +2 -2
  6. package/lib/agent.js +1 -2
  7. package/lib/config/build-instrumentation-config.js +3 -0
  8. package/lib/config/default.js +1397 -1395
  9. package/lib/config/index.js +15 -19
  10. package/lib/context-manager/context.js +13 -4
  11. package/lib/harvester.js +11 -13
  12. package/lib/instrumentation/@google/genai.js +8 -3
  13. package/lib/instrumentation/@hapi/hapi.js +4 -6
  14. package/lib/instrumentation/@nestjs/core.js +12 -14
  15. package/lib/instrumentation/aws-sdk/v3/bedrock.js +2 -2
  16. package/lib/instrumentation/kafkajs/producer.js +13 -19
  17. package/lib/instrumentation/openai.js +2 -2
  18. package/lib/instrumentation/undici.js +48 -40
  19. package/lib/instrumentations.js +14 -5
  20. package/lib/llm-events/aws-bedrock/utils.js +1 -1
  21. package/lib/metrics/names.js +8 -0
  22. package/lib/metrics/normalizer.js +1 -3
  23. package/lib/otel/context.js +18 -14
  24. package/lib/otel/metrics/bootstrap-metrics.js +1 -1
  25. package/lib/patch-module.js +70 -0
  26. package/lib/serverless/aws-lambda.js +1 -3
  27. package/lib/shim/webframework-shim/middleware-mounter.js +1 -3
  28. package/lib/shimmer.js +56 -8
  29. package/lib/subscriber-configs.js +17 -0
  30. package/lib/subscribers/application-logs.js +55 -0
  31. package/lib/subscribers/base.js +177 -0
  32. package/lib/subscribers/create-config.js +27 -0
  33. package/lib/subscribers/db-operation.js +21 -0
  34. package/lib/subscribers/db-query.js +54 -0
  35. package/lib/subscribers/db.js +57 -0
  36. package/lib/subscribers/elasticsearch/config.js +49 -0
  37. package/lib/subscribers/elasticsearch/elasticsearch.js +42 -0
  38. package/lib/subscribers/elasticsearch/opensearch.js +15 -0
  39. package/lib/subscribers/elasticsearch/transport.js +14 -0
  40. package/lib/subscribers/ioredis/config.js +37 -0
  41. package/lib/subscribers/ioredis/index.js +48 -0
  42. package/lib/subscribers/mcp-sdk/client-prompt.js +23 -0
  43. package/lib/subscribers/mcp-sdk/client-resource.js +24 -0
  44. package/lib/subscribers/mcp-sdk/client-tool.js +23 -0
  45. package/lib/subscribers/mcp-sdk/client.js +29 -0
  46. package/lib/subscribers/mcp-sdk/config.js +104 -0
  47. package/lib/subscribers/pino/config.js +20 -0
  48. package/lib/subscribers/pino/index.js +102 -0
  49. package/lib/transaction/trace/aggregator.js +7 -9
  50. package/lib/util/camel-case.js +1 -3
  51. package/lib/util/get-package-version.js +34 -0
  52. package/lib/w3c/tracestate.js +3 -3
  53. package/package.json +7 -5
  54. package/lib/instrumentation/@elastic/elasticsearch.js +0 -62
  55. package/lib/instrumentation/@opensearch-project/opensearch.js +0 -66
  56. package/lib/instrumentation/ioredis.js +0 -50
  57. package/lib/instrumentation/pino/nr-hooks.js +0 -19
  58. package/lib/instrumentation/pino/pino.js +0 -168
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const DbQuerySubscriber = require('../db-query')
8
+ const stringify = require('json-stringify-safe')
9
+ const { queryParser } = require('../../db/query-parsers/elasticsearch')
10
+
11
+ class ElasticSearchSubscriber extends DbQuerySubscriber {
12
+ constructor({ agent, logger, packageName = '@elastic/elasticsearch', channelName = 'nr_request', system = 'ElasticSearch' } = {}) {
13
+ super({ agent, logger, packageName, channelName, system })
14
+ this.events = ['asyncEnd']
15
+ this.opaque = true
16
+ }
17
+
18
+ handler(data, ctx) {
19
+ const { self, arguments: args } = data
20
+ this.queryString = stringify(args?.[0])
21
+ this.setParameters(self)
22
+ return super.handler(data, ctx)
23
+ }
24
+
25
+ setParameters(self) {
26
+ this.parameters = {}
27
+ this.parameters.product = this.system
28
+ const connectionPool = self?.connectionPool?.connections?.[0]
29
+ if (connectionPool) {
30
+ const host = connectionPool?.url?.host?.split(':')
31
+ const port = connectionPool?.url?.port || host?.[1]
32
+ this.parameters.host = host?.[0]
33
+ this.parameters.port_path_or_id = port
34
+ }
35
+ }
36
+
37
+ parseQuery(queryString) {
38
+ return queryParser(queryString)
39
+ }
40
+ }
41
+
42
+ module.exports = ElasticSearchSubscriber
@@ -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
+ const ElasticSearchSubscriber = require('./elasticsearch.js')
9
+ class OpenSearchSubscriber extends ElasticSearchSubscriber {
10
+ constructor({ agent, logger }) {
11
+ super({ agent, logger, packageName: '@opensearch-project/opensearch', channelName: 'nr_request', system: 'OpenSearch' })
12
+ }
13
+ }
14
+
15
+ module.exports = OpenSearchSubscriber
@@ -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 ElasticSearchSubscriber = require('./elasticsearch')
7
+
8
+ class ElasticSearchTransportSubscriber extends ElasticSearchSubscriber {
9
+ constructor({ agent, logger }) {
10
+ super({ agent, logger, packageName: '@elastic/transport' })
11
+ }
12
+ }
13
+
14
+ module.exports = ElasticSearchTransportSubscriber
@@ -0,0 +1,37 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ module.exports = {
7
+ ioredis: [{
8
+ path: './ioredis',
9
+ instrumentations: [
10
+ {
11
+ channelName: 'nr_sendCommand',
12
+ module: { name: 'ioredis', versionRange: '>=4', filePath: 'built/Redis.js' },
13
+ functionQuery: {
14
+ className: 'Redis',
15
+ methodName: 'sendCommand',
16
+ kind: 'Async'
17
+ }
18
+ },
19
+ {
20
+ channelName: 'nr_sendCommand',
21
+ module: { name: 'ioredis', versionRange: '>=4', filePath: 'built/redis.js' },
22
+ functionQuery: {
23
+ expressionName: 'sendCommand',
24
+ kind: 'Async'
25
+ }
26
+ },
27
+ {
28
+ channelName: 'nr_sendCommand',
29
+ module: { name: 'ioredis', versionRange: '>=4', filePath: 'built/redis/index.js' },
30
+ functionQuery: {
31
+ expressionName: 'sendCommand',
32
+ kind: 'Async'
33
+ }
34
+ }
35
+ ]
36
+ }]
37
+ }
@@ -0,0 +1,48 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const DbOperationSubscriber = require('../db-operation')
8
+ const stringify = require('json-stringify-safe')
9
+
10
+ class IoRedisSubscriber extends DbOperationSubscriber {
11
+ constructor({ agent, logger }) {
12
+ super({ agent, logger, packageName: 'ioredis', channelName: 'nr_sendCommand', system: 'Redis' })
13
+ this.events = ['asyncEnd']
14
+ }
15
+
16
+ handler(data, ctx) {
17
+ const { self, arguments: args } = data
18
+ const [command] = args
19
+ this.operation = command.name
20
+ this.setParameters(self, command)
21
+ return super.handler(data, ctx)
22
+ }
23
+
24
+ setParameters(self, command) {
25
+ this.parameters = {}
26
+ this.parameters.product = this.system
27
+ this.parameters.host = self?.connector?.options?.host
28
+ this.parameters.port_path_or_id = self?.connector?.options?.port
29
+ this.parameters.key = this.parseKey(command.args)
30
+ this.parameters.database_name = self?.condition?.select
31
+ }
32
+
33
+ parseKey(keys) {
34
+ let key
35
+ if (keys && typeof keys !== 'function') {
36
+ try {
37
+ key = stringify(keys[0])
38
+ } catch (err) {
39
+ this.logger.debug(err, 'Failed to stringify ioredis key')
40
+ key = '<unknown>'
41
+ }
42
+ }
43
+
44
+ return key
45
+ }
46
+ }
47
+
48
+ module.exports = IoRedisSubscriber
@@ -0,0 +1,23 @@
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 McpClientSubscriber = require('./client')
9
+ const { MCP } = require('../../metrics/names')
10
+
11
+ class McpClientPromptSubscriber extends McpClientSubscriber {
12
+ constructor({ agent, logger }) {
13
+ super({ agent, logger, channelName: 'nr_getPrompt' })
14
+ }
15
+
16
+ handler(data, ctx) {
17
+ const promptName = data?.arguments?.[0]?.name
18
+ this.segmentName = `${MCP.PROMPT}/getPrompt/${promptName}`
19
+ return super.handler(ctx)
20
+ }
21
+ }
22
+
23
+ module.exports = McpClientPromptSubscriber
@@ -0,0 +1,24 @@
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 McpClientSubscriber = require('./client')
9
+ const { MCP } = require('../../metrics/names')
10
+
11
+ class McpClientResourceSubscriber extends McpClientSubscriber {
12
+ constructor({ agent, logger }) {
13
+ super({ agent, logger, channelName: 'nr_readResource' })
14
+ }
15
+
16
+ handler(data, ctx) {
17
+ const uri = data?.arguments?.[0]?.uri
18
+ const scheme = typeof uri === 'string' ? uri.split('://')[0] : undefined
19
+ this.segmentName = `${MCP.RESOURCE}/readResource/${scheme}`
20
+ return super.handler(ctx)
21
+ }
22
+ }
23
+
24
+ module.exports = McpClientResourceSubscriber
@@ -0,0 +1,23 @@
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 McpClientSubscriber = require('./client')
9
+ const { MCP } = require('../../metrics/names')
10
+
11
+ class McpClientToolSubscriber extends McpClientSubscriber {
12
+ constructor({ agent, logger }) {
13
+ super({ agent, logger, channelName: 'nr_callTool' })
14
+ }
15
+
16
+ handler(data, ctx) {
17
+ const toolName = data?.arguments?.[0]?.name
18
+ this.segmentName = `${MCP.TOOL}/callTool/${toolName}`
19
+ return super.handler(ctx)
20
+ }
21
+ }
22
+
23
+ module.exports = McpClientToolSubscriber
@@ -0,0 +1,29 @@
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
+ class McpClientSubscriber extends Subscriber {
11
+ constructor({ agent, logger, channelName }) {
12
+ super({ agent, logger, packageName: '@modelcontextprotocol/sdk', channelName })
13
+ this.events = ['asyncEnd']
14
+ this.segmentName = 'Unknown'
15
+ }
16
+
17
+ get enabled() {
18
+ return super.enabled && this.config.ai_monitoring.enabled === true
19
+ }
20
+
21
+ handler(ctx) {
22
+ return this.createSegment({
23
+ name: this.segmentName,
24
+ ctx
25
+ })
26
+ }
27
+ }
28
+
29
+ module.exports = McpClientSubscriber
@@ -0,0 +1,104 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const mcpClientToolConfig = {
7
+ path: './mcp-sdk/client-tool',
8
+ instrumentations: [
9
+ {
10
+ channelName: 'nr_callTool',
11
+ module: {
12
+ name: '@modelcontextprotocol/sdk',
13
+ versionRange: '>=1.13.0',
14
+ filePath: 'dist/cjs/client/index.js'
15
+ },
16
+ functionQuery: {
17
+ className: 'Client',
18
+ methodName: 'callTool', // must be methodName, not functionName
19
+ kind: 'Async'
20
+ }
21
+ },
22
+ {
23
+ channelName: 'nr_callTool',
24
+ module: {
25
+ name: '@modelcontextprotocol/sdk',
26
+ versionRange: '>=1.13.0',
27
+ filePath: 'dist/esm/client/index.js'
28
+ },
29
+ functionQuery: {
30
+ className: 'Client',
31
+ methodName: 'callTool',
32
+ kind: 'Async'
33
+ }
34
+ },
35
+ ]
36
+ }
37
+
38
+ const mcpClientResourceConfig = {
39
+ path: './mcp-sdk/client-resource',
40
+ instrumentations: [
41
+ {
42
+ channelName: 'nr_readResource',
43
+ module: {
44
+ name: '@modelcontextprotocol/sdk',
45
+ versionRange: '>=1.13.0',
46
+ filePath: 'dist/cjs/client/index.js'
47
+ },
48
+ functionQuery: {
49
+ className: 'Client',
50
+ methodName: 'readResource',
51
+ kind: 'Async'
52
+ }
53
+ },
54
+ {
55
+ channelName: 'nr_readResource',
56
+ module: {
57
+ name: '@modelcontextprotocol/sdk',
58
+ versionRange: '>=1.13.0',
59
+ filePath: 'dist/esm/client/index.js'
60
+ },
61
+ functionQuery: {
62
+ className: 'Client',
63
+ methodName: 'readResource',
64
+ kind: 'Async'
65
+ }
66
+ },
67
+ ]
68
+ }
69
+
70
+ const mcpClientPromptConfig = {
71
+ path: './mcp-sdk/client-prompt',
72
+ instrumentations: [
73
+ {
74
+ channelName: 'nr_getPrompt',
75
+ module: {
76
+ name: '@modelcontextprotocol/sdk',
77
+ versionRange: '>=1.13.0',
78
+ filePath: 'dist/cjs/client/index.js'
79
+ },
80
+ functionQuery: {
81
+ className: 'Client',
82
+ methodName: 'getPrompt',
83
+ kind: 'Async'
84
+ }
85
+ },
86
+ {
87
+ channelName: 'nr_getPrompt',
88
+ module: {
89
+ name: '@modelcontextprotocol/sdk',
90
+ versionRange: '>=1.13.0',
91
+ filePath: 'dist/esm/client/index.js'
92
+ },
93
+ functionQuery: {
94
+ className: 'Client',
95
+ methodName: 'getPrompt',
96
+ kind: 'Async'
97
+ }
98
+ },
99
+ ]
100
+ }
101
+
102
+ module.exports = {
103
+ '@modelcontextprotocol/sdk': [mcpClientToolConfig, mcpClientResourceConfig, mcpClientPromptConfig],
104
+ }
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ module.exports = {
7
+ pino: [{
8
+ path: './pino',
9
+ instrumentations: [
10
+ {
11
+ channelName: 'nr_asJson',
12
+ module: { name: 'pino', versionRange: '>=8.0.0', filePath: 'lib/tools.js' },
13
+ functionQuery: {
14
+ functionName: 'asJson',
15
+ kind: 'Sync'
16
+ }
17
+ }
18
+ ]
19
+ }]
20
+ }
@@ -0,0 +1,102 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const ApplicationLogsSubscriber = require('../application-logs')
8
+ const { truncate } = require('../../util/application-logging')
9
+
10
+ class PinoSubscriber extends ApplicationLogsSubscriber {
11
+ constructor({ agent, logger }) {
12
+ super({ agent, logger, packageName: 'pino', channelName: 'nr_asJson' })
13
+ this.events = ['end']
14
+ }
15
+
16
+ handler(data, ctx) {
17
+ this.createModuleUsageMetric('pino')
18
+ const { self, arguments: args } = data
19
+ const level = self?.levels?.labels?.[args[2]]
20
+ this.incrementLinesMetric(level)
21
+ const useMergeObj = this.decorateLogLine(data)
22
+ ctx.extras = { useMergeObj }
23
+ return ctx
24
+ }
25
+
26
+ decorateLogLine(data) {
27
+ // Pino log methods accept a singular object (a merging object) that can
28
+ // have a `msg` property for the log message. In such cases, we need to
29
+ // update that log property instead of the second parameter.
30
+ const useMergeObj = data.arguments[1] === undefined && Object.hasOwn(data.arguments[0], 'msg')
31
+ const meta = super.decorateLogLine()
32
+ if (meta) {
33
+ if (useMergeObj === true) {
34
+ data.arguments[0].msg += this.agent.getNRLinkingMetadata()
35
+ } else {
36
+ data.arguments[1] += this.agent.getNRLinkingMetadata()
37
+ }
38
+ }
39
+ return useMergeObj
40
+ }
41
+
42
+ end(data) {
43
+ this.forwardLogLine(data)
44
+ }
45
+
46
+ /**
47
+ * reformats error and assigns NR context data
48
+ * to log line
49
+ *
50
+ * @param {object} data event passed to the end handler
51
+ * @param {object} ctx agent context object
52
+ * @returns {function} wrapped log formatter function
53
+ */
54
+ reformatLogLine(data, ctx) {
55
+ const subscriber = this
56
+ const { self, result: logLine, arguments: args } = data
57
+ const msg = ctx?.extras?.useMergeObj === true ? args[0].msg : args[1]
58
+ const level = self?.levels?.labels?.[args[2]]
59
+ const metadata = this.agent.getLinkingMetadata(true)
60
+
61
+ const agentMeta = Object.assign({}, { timestamp: Date.now() }, metadata)
62
+ // eslint-disable-next-line eqeqeq
63
+ if (msg != undefined) {
64
+ // The spec lists `message` as "MUST" under the required column, but then
65
+ // details that it "MUST be omitted" if the value is "empty". Additionally,
66
+ // if someone has logged only a merging object, and that object contains a
67
+ // message key, we do not want to overwrite their value. See issue 2595.
68
+ agentMeta.message = msg
69
+ }
70
+
71
+ /**
72
+ * A function that gets executed in `_toPayloadSync` of log aggregator.
73
+ * This will parse the serialized log line and then add the relevant NR
74
+ * context metadata and rename the time/msg keys to timestamp/message
75
+ * @returns {object} formatted log line
76
+ */
77
+ return function formatLogLine() {
78
+ let formattedLog
79
+ try {
80
+ formattedLog = JSON.parse(logLine)
81
+ } catch (err) {
82
+ subscriber.logger.error('Failed to parse log line as json: %s', err.message)
83
+ return
84
+ }
85
+
86
+ if (formattedLog.err) {
87
+ formattedLog['error.message'] = truncate(formattedLog.err.message)
88
+ formattedLog['error.stack'] = truncate(formattedLog.err.stack)
89
+ formattedLog['error.class'] = formattedLog.err.type
90
+ delete formattedLog.err
91
+ }
92
+
93
+ Object.assign(formattedLog, agentMeta)
94
+ formattedLog.level = level
95
+ delete formattedLog.time
96
+ delete formattedLog.msg
97
+ return formattedLog
98
+ }
99
+ }
100
+ }
101
+
102
+ module.exports = PinoSubscriber
@@ -190,16 +190,14 @@ class TransactionTraceAggregator extends TraceAggregator {
190
190
  return callback(null, traces)
191
191
  }
192
192
 
193
- const tracePromises = traces.map((trace) => {
194
- return new Promise((resolve, reject) => {
195
- trace.generateJSON((err, data) => {
196
- if (err) {
197
- reject(err)
198
- }
199
- resolve(data)
200
- })
193
+ const tracePromises = traces.map((trace) => new Promise((resolve, reject) => {
194
+ trace.generateJSON((err, data) => {
195
+ if (err) {
196
+ reject(err)
197
+ }
198
+ resolve(data)
201
199
  })
202
- })
200
+ }))
203
201
 
204
202
  try {
205
203
  const encodedTraces = await Promise.all(tracePromises)
@@ -19,8 +19,6 @@ const words = (string) => string.match(wordPattern) || []
19
19
  */
20
20
  module.exports = function toCamelCase(string) {
21
21
  return words(string)
22
- .map((word, index) =>
23
- index === 0 ? word.toLowerCase() : word.slice(0, 1).toUpperCase() + word.slice(1)
24
- )
22
+ .map((word, index) => (index === 0 ? word.toLowerCase() : word.slice(0, 1).toUpperCase() + word.slice(1)))
25
23
  .join('')
26
24
  }
@@ -0,0 +1,34 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const { readFileSync } = require('node:fs')
8
+ const { join } = require('node:path')
9
+
10
+ const packageVersions = new Map()
11
+
12
+ /**
13
+ * Retrieves the version of a package from its package.json file.
14
+ * If the package.json file cannot be read, it defaults to the Node.js version.
15
+ * @param {string} baseDir - The base directory where the package.json file is located.
16
+ * @returns {string} The version of the package or the Node.js version if the package.json cannot be read.
17
+ */
18
+ function getPackageVersion(baseDir) {
19
+ if (packageVersions.has(baseDir)) {
20
+ return packageVersions.get(baseDir)
21
+ }
22
+
23
+ try {
24
+ const packageJsonPath = join(baseDir, 'package.json')
25
+ const jsonFile = readFileSync(packageJsonPath)
26
+ const { version } = JSON.parse(jsonFile)
27
+ packageVersions.set(baseDir, version)
28
+ return version
29
+ } catch {
30
+ return process.version.slice(1)
31
+ }
32
+ }
33
+
34
+ module.exports = getPackageVersion
@@ -69,7 +69,7 @@ class Tracestate {
69
69
  const vendors = new Set()
70
70
  const listMembers = new Map()
71
71
  for (const listMember of kvPairs) {
72
- const parts = listMember.split('=', 2).filter(v => Boolean(v))
72
+ const parts = listMember.split('=', 2).filter((v) => Boolean(v))
73
73
  if (parts.length !== 2) {
74
74
  this.#logger.debug('Unable to parse tracestate list members.')
75
75
  this.#agent.recordSupportability('TraceContext/TraceState/Parse/Exception/ListMember')
@@ -94,7 +94,7 @@ class Tracestate {
94
94
  let intrinsics
95
95
  if (nrTraceStateValue) {
96
96
  intrinsics = new TracestateIntrinsics()
97
- const values = nrTraceStateValue.split('-').map(v => v === '' ? null : v)
97
+ const values = nrTraceStateValue.split('-').map((v) => (v === '' ? null : v))
98
98
  intrinsics.version = values[0]
99
99
  intrinsics.parentType = values[1]
100
100
  intrinsics.accountId = values[2]
@@ -150,7 +150,7 @@ class Tracestate {
150
150
  if (typeof header !== 'string') {
151
151
  throw Error('header value must be a string')
152
152
  }
153
- const kvPairs = header.split(',').map(item => item.trim()).filter(Boolean)
153
+ const kvPairs = header.split(',').map((item) => item.trim()).filter(Boolean)
154
154
  return new Tracestate({ agent, logger, kvPairs })
155
155
  }
156
156
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "13.1.0",
3
+ "version": "13.2.0",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [
@@ -172,11 +172,11 @@
172
172
  "services": "DOCKER_PLATFORM=linux/$(uname -m) docker compose up -d --wait",
173
173
  "services:start": "npm run services",
174
174
  "services:stop": "docker compose down",
175
- "smoke": "time borp --timeout 180000 --reporter ./test/lib/test-reporter.mjs 'test/smoke/**/*.{test,tap}.js'",
175
+ "smoke": "time borp --timeout 180000 --reporter ./test/lib/test-reporter.mjs 'test/smoke/**/*.test.js'",
176
176
  "sub-install": "node test/bin/install_sub_deps",
177
177
  "test": "npm run integration && npm run unit",
178
178
  "third-party-updates": "oss third-party manifest --includeOptDeps && oss third-party notices --includeOptDeps && git add THIRD_PARTY_NOTICES.md third_party_manifest.json",
179
- "unit": "rm -f newrelic_agent.log && time c8 -o ./coverage/unit borp --timeout 180000 --reporter ./test/lib/test-reporter.mjs 'test/unit/**/*.test.js'",
179
+ "unit": "rm -f newrelic_agent.log && time c8 -o ./coverage/unit borp --timeout 180000 --reporter ./test/lib/test-reporter.mjs 'test/unit/**/*.test.{js,mjs}'",
180
180
  "unit:scripts": "time c8 -o ./coverage/scripts-unit borp --reporter ./test/lib/test-reporter.mjs 'bin/test/*.test.js'",
181
181
  "update-cross-agent-tests": "./bin/update-cats.sh",
182
182
  "versioned-tests": "./bin/run-versioned-tests.sh",
@@ -201,6 +201,7 @@
201
201
  "#test/assert": "./test/lib/custom-assertions/index.js"
202
202
  },
203
203
  "dependencies": {
204
+ "@apm-js-collab/code-transformer": "^0.6.0",
204
205
  "@grpc/grpc-js": "^1.13.2",
205
206
  "@grpc/proto-loader": "^0.7.5",
206
207
  "@newrelic/security-agent": "^2.4.2",
@@ -234,7 +235,7 @@
234
235
  "@aws-sdk/s3-request-presigner": "^3.556.0",
235
236
  "@koa/router": "^12.0.1",
236
237
  "@matteo.collina/tspl": "^0.1.1",
237
- "@newrelic/eslint-config": "^0.5.0",
238
+ "@newrelic/eslint-config": "^0.6.0",
238
239
  "@newrelic/newrelic-oss-cli": "^0.1.2",
239
240
  "@newrelic/test-utilities": "^10.0.0",
240
241
  "@octokit/rest": "^18.0.15",
@@ -271,7 +272,8 @@
271
272
  "self-cert": "^2.0.0",
272
273
  "should": "*",
273
274
  "sinon": "^5.1.1",
274
- "superagent": "^9.0.1"
275
+ "superagent": "^9.0.1",
276
+ "testdouble": "^3.20.2"
275
277
  },
276
278
  "repository": {
277
279
  "type": "git",