newrelic 13.19.2 → 13.20.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 (46) hide show
  1. package/NEWS.md +41 -0
  2. package/THIRD_PARTY_NOTICES.md +11 -11
  3. package/lib/collector/remote-method.js +3 -1
  4. package/lib/config/index.js +20 -0
  5. package/lib/context-manager/async-local-context-manager.js +1 -1
  6. package/lib/instrumentation/core/domain.js +2 -13
  7. package/lib/instrumentation/core/globals.js +0 -1
  8. package/lib/instrumentations.js +0 -3
  9. package/lib/llm-events/ai-agent.js +28 -0
  10. package/lib/llm-events/google-genai/chat-completion-message.js +6 -3
  11. package/lib/message-broker-description.js +29 -12
  12. package/lib/metrics/names.js +14 -8
  13. package/lib/subscriber-configs.js +4 -0
  14. package/lib/subscribers/amqplib/consume.js +1 -1
  15. package/lib/subscribers/aws-sdk/config.js +41 -3
  16. package/lib/subscribers/aws-sdk/core-send.js +16 -0
  17. package/lib/subscribers/aws-sdk/middleware/sqs/index.js +10 -13
  18. package/lib/subscribers/azure-functions/azure-handler-base.js +138 -0
  19. package/lib/subscribers/azure-functions/background-handler.js +29 -0
  20. package/lib/subscribers/azure-functions/config.js +44 -0
  21. package/lib/subscribers/azure-functions/http-handler.js +58 -0
  22. package/lib/subscribers/azure-functions/index.js +74 -0
  23. package/lib/subscribers/azure-functions/logger.js +72 -0
  24. package/lib/subscribers/connect/config.js +42 -0
  25. package/lib/subscribers/connect/use.js +31 -0
  26. package/lib/subscribers/google-adk/agent-run-async.js +119 -0
  27. package/lib/subscribers/google-adk/config.js +59 -0
  28. package/lib/subscribers/google-adk/tool-run-async.js +87 -0
  29. package/lib/subscribers/kafkajs/client-constructor.js +349 -0
  30. package/lib/subscribers/kafkajs/config.js +25 -0
  31. package/lib/subscribers/kafkajs/utils/record-data-metrics.js +48 -0
  32. package/lib/subscribers/kafkajs/utils/record-linking-metrics.js +30 -0
  33. package/lib/{instrumentation/kafkajs → subscribers/kafkajs/utils}/record-method-metric.js +3 -2
  34. package/lib/subscribers/langgraph/graph-stream.js +2 -1
  35. package/lib/subscribers/message-consumer-tools.js +161 -0
  36. package/lib/subscribers/message-consumer.js +43 -61
  37. package/lib/subscribers/undici/index.js +5 -7
  38. package/lib/transaction/tracer/index.js +26 -2
  39. package/package.json +2 -2
  40. package/lib/instrumentation/@azure/functions.js +0 -323
  41. package/lib/instrumentation/connect.js +0 -83
  42. package/lib/instrumentation/kafkajs/consumer.js +0 -145
  43. package/lib/instrumentation/kafkajs/index.js +0 -34
  44. package/lib/instrumentation/kafkajs/producer.js +0 -83
  45. package/lib/instrumentation/kafkajs/record-linking-metrics.js +0 -17
  46. package/lib/instrumentation/kafkajs.js +0 -7
@@ -0,0 +1,138 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const Transaction = require('#agentlib/transaction/index.js')
9
+ const { DESTINATIONS: DESTS } = Transaction
10
+
11
+ module.exports = class AzureHandler {
12
+ constructor(subscriber) {
13
+ this.subscriber = subscriber
14
+ this.agent = subscriber.agent
15
+ }
16
+
17
+ handleColdStart(transaction) {
18
+ if (this.subscriber.coldStart === true) {
19
+ transaction.trace.attributes.addAttribute(DESTS.TRANS_COMMON, 'faas.coldStart', true)
20
+ this.subscriber.coldStart = false
21
+ }
22
+ }
23
+
24
+ createTransaction({ handlerArgs, ctx }) {
25
+ const [, context] = handlerArgs
26
+ const transaction = new Transaction(this.agent)
27
+ transaction.type = this.type
28
+ transaction.setPartialName(`AzureFunction/${context.functionName}`)
29
+ ctx = ctx.enterTransaction(transaction)
30
+ const newCtx = this.createSegment({ handlerArgs, ctx })
31
+ transaction.baseSegment = newCtx.segment
32
+ return newCtx
33
+ }
34
+
35
+ async handle({ thisArg, originalHandler, handlerArgs }) {
36
+ const ctx = this.agent.tracer.getContext()
37
+ if (ctx.transaction != null) {
38
+ return originalHandler.apply(thisArg, handlerArgs)
39
+ }
40
+
41
+ const [, context] = handlerArgs
42
+ const newCtx = this.createTransaction({ handlerArgs, ctx })
43
+ const transaction = newCtx?.transaction
44
+ this.addFaasAttributes(transaction, context)
45
+ const result = await this.runHandlerInContext({ originalHandler, ctx: newCtx, thisArg, handlerArgs })
46
+ this.handleColdStart(transaction)
47
+ return this.finalizeTransaction({ result, transaction })
48
+ }
49
+
50
+ runHandlerInContext({ originalHandler, ctx, thisArg, handlerArgs }) {
51
+ return this.agent.tracer.bindFunction(originalHandler, ctx).apply(thisArg, handlerArgs)
52
+ }
53
+
54
+ finalizeTransaction({ result, transaction }) {
55
+ transaction.end()
56
+ return result
57
+ }
58
+
59
+ addFaasAttributes(transaction, functionContext) {
60
+ transaction.trace.attributes.addAttribute(
61
+ DESTS.TRANS_COMMON,
62
+ 'faas.invocation_id',
63
+ functionContext.invocationId ?? 'unknown'
64
+ )
65
+ transaction.trace.attributes.addAttribute(
66
+ DESTS.TRANS_COMMON,
67
+ 'faas.name',
68
+ functionContext.functionName ?? 'unknown'
69
+ )
70
+ transaction.trace.attributes.addAttribute(
71
+ DESTS.TRANS_COMMON,
72
+ 'faas.trigger',
73
+ this.mapTriggerType(functionContext)
74
+ )
75
+ transaction.trace.attributes.addAttribute(
76
+ DESTS.TRANS_COMMON,
77
+ 'cloud.resource_id',
78
+ this.buildCloudResourceId(functionContext)
79
+ )
80
+ }
81
+
82
+ mapTriggerType(functionContext) {
83
+ const input = functionContext.options?.trigger?.type
84
+
85
+ // Input types are found at:
86
+ // https://github.com/Azure/azure-functions-nodejs-library/blob/138c021/src/trigger.ts
87
+ // https://learn.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings?tabs=isolated-process%2Cnode-v4%2Cpython-v2&pivots=programming-language-javascript#supported-bindings
88
+ switch (input) {
89
+ case 'httpTrigger': {
90
+ return 'http'
91
+ }
92
+
93
+ case 'timerTrigger': {
94
+ return 'timer'
95
+ }
96
+
97
+ case 'blobTrigger':
98
+ case 'cosmosDBTrigger':
99
+ case 'daprBindingTrigger':
100
+ case 'mysqlTrigger':
101
+ case 'queueTrigger':
102
+ case 'sqlTrigger': {
103
+ return 'datasource'
104
+ }
105
+
106
+ case 'daprTopicTrigger':
107
+ case 'eventGridTrigger':
108
+ case 'eventHubTrigger':
109
+ case 'kafkaTrigger':
110
+ case 'rabbitMQTrigger':
111
+ case 'redisListTrigger':
112
+ case 'redisPubSubTrigger':
113
+ case 'redisStreamTrigger':
114
+ case 'serviceBusTrigger':
115
+ case 'signalRTrigger':
116
+ case 'webPubSubTrigger': {
117
+ return 'pubsub'
118
+ }
119
+
120
+ default: {
121
+ return 'other'
122
+ }
123
+ }
124
+ }
125
+
126
+ buildCloudResourceId(functionContext) {
127
+ return [
128
+ '/subscriptions/',
129
+ this.subscriber.subscriptionId,
130
+ '/resourceGroups/',
131
+ this.subscriber.resourceGroup,
132
+ '/providers/Microsoft.Web/sites/',
133
+ this.subscriber.azureFunctionAppName,
134
+ '/functions/',
135
+ functionContext.functionName
136
+ ].join('')
137
+ }
138
+ }
@@ -0,0 +1,29 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const AzureHandler = require('#agentlib/subscribers/azure-functions/azure-handler-base.js')
9
+ const Transaction = require('#agentlib/transaction/index.js')
10
+ const backgroundRecorder = require('#agentlib/metrics/recorders/other.js')
11
+ const { TYPES } = Transaction
12
+
13
+ module.exports = class BackgroundHandler extends AzureHandler {
14
+ constructor({ subscriber }) {
15
+ super(subscriber)
16
+ this.type = TYPES.BG
17
+ }
18
+
19
+ createSegment({ handlerArgs, ctx }) {
20
+ const [, context] = handlerArgs
21
+ const triggerType = context.options?.trigger?.type ?? 'unknown'
22
+ const methodName = triggerType.replace(/Trigger$/, '')
23
+ return this.subscriber.createSegment({
24
+ name: `${methodName}-trigger`,
25
+ recorder: backgroundRecorder,
26
+ ctx
27
+ })
28
+ }
29
+ }
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ 'use strict'
6
+
7
+ const modName = '@azure/functions'
8
+ const filePath = 'dist/azure-functions.js'
9
+ const versionRange = '>=4.7.0'
10
+
11
+ const generic = {
12
+ path: './azure-functions/index.js',
13
+ instrumentations: [
14
+ {
15
+ channelName: 'nr_generic',
16
+ module: { name: modName, versionRange, filePath },
17
+ functionQuery: {
18
+ functionName: 'generic',
19
+ kind: 'Sync'
20
+ }
21
+ }
22
+ ]
23
+ }
24
+
25
+ const logger = {
26
+ path: './azure-functions/logger.js',
27
+ instrumentations: [
28
+ {
29
+ channelName: 'nr_logger',
30
+ module: { name: modName, versionRange, filePath },
31
+ functionQuery: {
32
+ functionName: 'tryGetCoreApiLazy',
33
+ kind: 'Sync'
34
+ }
35
+ }
36
+ ]
37
+ }
38
+
39
+ module.exports = {
40
+ [modName]: [
41
+ generic,
42
+ logger
43
+ ]
44
+ }
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const AzureHandler = require('#agentlib/subscribers/azure-functions/azure-handler-base.js')
9
+ const Transaction = require('#agentlib/transaction/index.js')
10
+ const { TYPES } = Transaction
11
+ const { Transform } = require('node:stream')
12
+ const recordWeb = require('#agentlib/metrics/recorders/http.js')
13
+
14
+ module.exports = class HttpHandler extends AzureHandler {
15
+ constructor({ subscriber }) {
16
+ super(subscriber)
17
+ this.type = TYPES.WEB
18
+ }
19
+
20
+ #initializeWeb(transaction, request) {
21
+ const absoluteUrl = request.url
22
+ const url = new URL(absoluteUrl)
23
+ const transport = url.protocol === 'https:' ? 'HTTPS' : 'HTTP'
24
+ const port = url.port || (transport === 'HTTPS' ? 443 : 80)
25
+ transaction.initializeWeb({ absoluteUrl, method: request.method, port, headers: request.headers, transport })
26
+ }
27
+
28
+ runHandlerInContext({ originalHandler, ctx, thisArg, handlerArgs }) {
29
+ const { transaction } = ctx
30
+ const [request] = handlerArgs
31
+ const self = this
32
+ function inContext() {
33
+ self.#initializeWeb(transaction, request)
34
+ return originalHandler.apply(this, arguments)
35
+ }
36
+
37
+ return this.agent.tracer.bindFunction(inContext, ctx).apply(thisArg, handlerArgs)
38
+ }
39
+
40
+ finalizeTransaction({ result, transaction }) {
41
+ transaction.finalizeWeb({ statusCode: result?.status, headers: result?.headers, end: false })
42
+ if (result?.body instanceof Transform) {
43
+ result.body.on('close', () => transaction.end())
44
+ } else {
45
+ transaction.end()
46
+ }
47
+ return result
48
+ }
49
+
50
+ createSegment({ handlerArgs, ctx }) {
51
+ const [request] = handlerArgs
52
+ return this.subscriber.createSegment({
53
+ name: request.url,
54
+ recorder: recordWeb,
55
+ ctx
56
+ })
57
+ }
58
+ }
@@ -0,0 +1,74 @@
1
+ /*
2
+ * Copyright 2026 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
+ const HttpHandler = require('#agentlib/subscribers/azure-functions/http-handler.js')
10
+ const BackgroundHandler = require('#agentlib/subscribers/azure-functions/background-handler.js')
11
+
12
+ module.exports = class AzureFunctionsSubscriber extends Subscriber {
13
+ constructor({ agent, logger }) {
14
+ super({ agent, logger, channelName: 'nr_generic', packageName: '@azure/functions' })
15
+ this.requireActiveTx = false
16
+ this.coldStart = true
17
+ }
18
+
19
+ handler(data, ctx) {
20
+ if (this.missingEnvVars) {
21
+ this.logger.warn(
22
+ {
23
+ data: {
24
+ expectedVars: ['WEBSITE_OWNER_NAME', 'WEBSITE_RESOURCE_GROUP', 'WEBSITE_SITE_NAME'],
25
+ found: { WEBSITE_OWNER_NAME: this.subscriptionId, WEBSITE_RESOURCE_GROUP: this.resourceGroup, WEBSITE_SITE_NAME: this.azureFunctionAppName }
26
+ }
27
+ },
28
+ 'could not initialize azure functions instrumentation due to missing environment variables'
29
+ )
30
+ return ctx
31
+ }
32
+
33
+ const { arguments: args } = data
34
+ const [, options] = args
35
+ const self = this
36
+ const originalHandler = options.handler
37
+
38
+ args[1].handler = async function wrappedHandler(...handlerArgs) {
39
+ let handler
40
+ if (options?.return?.type === 'http') {
41
+ handler = new HttpHandler({ subscriber: self })
42
+ } else {
43
+ handler = new BackgroundHandler({ subscriber: self })
44
+ }
45
+ return handler.handle({ thisArg: this, originalHandler, handlerArgs })
46
+ }
47
+ }
48
+
49
+ get missingEnvVars() {
50
+ return !this.subscriptionId || !this.resourceGroup || !this.azureFunctionAppName
51
+ }
52
+
53
+ get subscriptionId() {
54
+ if (!process.env.WEBSITE_OWNER_NAME) {
55
+ return null
56
+ }
57
+
58
+ return process.env.WEBSITE_OWNER_NAME?.split('+').shift()
59
+ }
60
+
61
+ get resourceGroup() {
62
+ const { WEBSITE_RESOURCE_GROUP, WEBSITE_OWNER_NAME } = process.env
63
+ if (!WEBSITE_RESOURCE_GROUP && WEBSITE_OWNER_NAME) {
64
+ return WEBSITE_OWNER_NAME.split('+').pop().split('-Linux').shift()
65
+ }
66
+
67
+ return WEBSITE_RESOURCE_GROUP
68
+ }
69
+
70
+ get azureFunctionAppName() {
71
+ const { WEBSITE_SITE_NAME } = process.env
72
+ return WEBSITE_SITE_NAME
73
+ }
74
+ }
@@ -0,0 +1,72 @@
1
+ /*
2
+ * Copyright 2026 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
+ const {
10
+ isApplicationLoggingEnabled,
11
+ isLogForwardingEnabled,
12
+ isMetricsEnabled,
13
+ incrementLoggingLinesMetrics
14
+ } = require('#agentlib/util/application-logging.js')
15
+
16
+ // Azure Functions uses 'information' as the context level for context.log and
17
+ // context.info and uses 'warning' as the context level for context.warn.
18
+ // These map to the NR standard names that LOGGING.LEVELS recognizes ('info', 'warn').
19
+ const AZURE_TO_NR_LEVEL = {
20
+ information: 'info',
21
+ warning: 'warn'
22
+ }
23
+
24
+ module.exports = class AzureFunctionsSubscriber extends Subscriber {
25
+ constructor({ agent, logger }) {
26
+ super({ agent, logger, channelName: 'nr_logger', packageName: '@azure/functions' })
27
+ this.logHookRegistered = false
28
+ this.events = ['end']
29
+ }
30
+
31
+ end(data) {
32
+ const coreApi = data.result
33
+ this.registerLogHook(coreApi)
34
+ }
35
+
36
+ registerLogHook(coreApi) {
37
+ if (this.logHookRegistered) {
38
+ return
39
+ }
40
+
41
+ this.logHookRegistered = true
42
+
43
+ if (!isApplicationLoggingEnabled(this.agent.config)) {
44
+ this.logger.debug('Application logging not enabled. Not auto capturing logs from Azure Functions.')
45
+ return
46
+ }
47
+
48
+ const agent = this.agent
49
+
50
+ coreApi.registerHook('log', (context) => {
51
+ const logLevel = AZURE_TO_NR_LEVEL[context.level] ?? context.level ?? 'info'
52
+
53
+ if (isLogForwardingEnabled(agent.config, agent)) {
54
+ const meta = agent.getLinkingMetadata(true)
55
+
56
+ const logData = {
57
+ message: context.message ?? 'unknown',
58
+ level: logLevel,
59
+ timestamp: Date.now(),
60
+ category: context.category ?? 'user',
61
+ ...meta
62
+ }
63
+
64
+ agent.logs.add(logData)
65
+ }
66
+
67
+ if (isMetricsEnabled(agent.config)) {
68
+ incrementLoggingLinesMetrics(logLevel, agent.metrics)
69
+ }
70
+ })
71
+ }
72
+ }
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const modName = 'connect'
9
+
10
+ module.exports = {
11
+ [modName]: [
12
+ {
13
+ path: './connect/use.js',
14
+ instrumentations: [
15
+ {
16
+ channelName: 'nr_use',
17
+ module: {
18
+ name: modName,
19
+ filePath: 'index.js',
20
+ versionRange: '>=3.4.0'
21
+ },
22
+ functionQuery: {
23
+ expressionName: 'use',
24
+ kind: 'Sync'
25
+ }
26
+ },
27
+ {
28
+ channelName: 'nr_use',
29
+ module: {
30
+ name: modName,
31
+ filePath: 'lib/proto.js',
32
+ versionRange: '>=3.0.0 <3.4.0'
33
+ },
34
+ functionQuery: {
35
+ expressionName: 'use',
36
+ kind: 'Sync'
37
+ }
38
+ },
39
+ ]
40
+ }
41
+ ]
42
+ }
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const MiddlewareSubscriber = require('../middleware.js')
9
+
10
+ module.exports = class CreateServerSubscriber extends MiddlewareSubscriber {
11
+ constructor({ agent, logger }) {
12
+ super({
13
+ agent,
14
+ logger,
15
+ channelName: 'nr_use',
16
+ packageName: 'connect',
17
+ system: 'Connect'
18
+ })
19
+ }
20
+
21
+ handler(data, ctx) {
22
+ const { arguments: args } = data
23
+ const [route, mw] = args
24
+ if (typeof route === 'string') {
25
+ data.arguments[1] = this.wrapper.wrap({ handler: mw, route })
26
+ } else {
27
+ data.arguments[0] = this.wrapper.wrap({ handler: route, route: '/' })
28
+ }
29
+ return ctx
30
+ }
31
+ }
@@ -0,0 +1,119 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const AiMonitoringSubscriber = require('../ai-monitoring/base')
7
+ const LlmAgent = require('#agentlib/llm-events/ai-agent.js')
8
+ const LlmErrorMessage = require('#agentlib/llm-events/error-message.js')
9
+ const { AI: { GOOGLE_ADK } } = require('#agentlib/metrics/names.js')
10
+
11
+ module.exports = class GoogleAdkAgentRunSubscriber extends AiMonitoringSubscriber {
12
+ constructor({ agent, logger }) {
13
+ super({
14
+ agent,
15
+ logger,
16
+ packageName: '@google/adk',
17
+ channelName: 'nr_agentRunAsync',
18
+ name: `${GOOGLE_ADK.AGENT}/runAsync/agent`,
19
+ trackingPrefix: GOOGLE_ADK.TRACKING_PREFIX
20
+ })
21
+ this.events = ['end']
22
+ }
23
+
24
+ handler(data, ctx) {
25
+ this.aiAgentName = data?.self?.name ?? 'agent'
26
+ this.name = `${GOOGLE_ADK.AGENT}/runAsync/${this.aiAgentName}`
27
+ return super.handler(data, ctx)
28
+ }
29
+
30
+ // BaseAgent.runAsync is an async generator. The tracePromise wrapper returns
31
+ // the generator object synchronously (it has no .then), so `asyncEnd` is
32
+ // never published. We use `end` instead, which fires right after the
33
+ // generator is created but before it is consumed by the caller.
34
+ end(data) {
35
+ const { agent, logger } = this
36
+ if (!this.enabled) {
37
+ logger.debug('Google ADK instrumentation is disabled, not instrumenting runAsync.')
38
+ return
39
+ }
40
+
41
+ const ctx = agent.tracer.getContext()
42
+ const { segment, transaction } = ctx
43
+ if (!(segment || transaction) || (transaction?.isActive() !== true)) {
44
+ return
45
+ }
46
+ segment.addSpanAttribute('subcomponent', `{"type": "APM-AI_AGENT", "name": "${this.aiAgentName}"}`)
47
+
48
+ const { result: generator } = data
49
+ if (generator && typeof generator[Symbol.asyncIterator] === 'function') {
50
+ this.#instrumentGenerator({ generator, ctx })
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Wraps the async generator returned by BaseAgent.runAsync() so that
56
+ * child instrumentation (e.g. Gemini, FunctionTool) runs within the
57
+ * agent segment context. Records the LlmAgent event when the generator
58
+ * completes or throws.
59
+ *
60
+ * @param {object} params function parameters
61
+ * @param {object} params.ctx The NR async context to bind generator calls to
62
+ * @param {AsyncGenerator} params.generator The async generator from runAsync
63
+ */
64
+ #instrumentGenerator({ ctx, generator }) {
65
+ const self = this
66
+ const origNext = generator.next
67
+
68
+ generator.next = async function wrappedNext(...args) {
69
+ try {
70
+ // Bind to the segment context so that child instrumentation
71
+ // (e.g. Gemini) creates spans as children of this agent span.
72
+ const boundNext = self.agent.tracer.bindFunction(origNext, ctx)
73
+ const result = await boundNext.apply(this, args)
74
+ if (result?.done) {
75
+ self.#recordAgentEvent({ ctx, error: false })
76
+ }
77
+ return result
78
+ } catch (err) {
79
+ self.#recordAgentEvent({ ctx, error: true })
80
+ throw err
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Records a Google ADK LlmAgent event.
87
+ *
88
+ * @param {object} params function parameters
89
+ * @param {object} params.ctx The active tracer context containing the segment and transaction
90
+ * @param {boolean} params.error Whether an error occurred
91
+ */
92
+ #recordAgentEvent({ ctx, error }) {
93
+ const { agent, aiAgentName } = this
94
+ const { segment, transaction } = ctx
95
+ segment.end()
96
+ const agentEvent = new LlmAgent({
97
+ agent,
98
+ segment,
99
+ transaction,
100
+ aiAgentName,
101
+ vendor: 'google_adk',
102
+ error: error || undefined
103
+ })
104
+
105
+ this.recordEvent({ type: 'LlmAgent', msg: agentEvent })
106
+
107
+ if (error) {
108
+ agent.errors.add(
109
+ transaction,
110
+ error,
111
+ new LlmErrorMessage({
112
+ response: {},
113
+ cause: error,
114
+ aiAgent: agentEvent
115
+ })
116
+ )
117
+ }
118
+ }
119
+ }
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Copyright 2026 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const agentRunAsync = {
7
+ path: './google-adk/agent-run-async.js',
8
+ instrumentations: [
9
+ {
10
+ channelName: 'nr_agentRunAsync',
11
+ module: { name: '@google/adk', versionRange: '>=1.1.0', filePath: 'dist/cjs/agents/base_agent.js' },
12
+ functionQuery: {
13
+ className: 'BaseAgent',
14
+ methodName: 'runAsync',
15
+ kind: 'Async'
16
+ }
17
+ },
18
+ {
19
+ channelName: 'nr_agentRunAsync',
20
+ module: { name: '@google/adk', versionRange: '>=1.1.0', filePath: 'dist/esm/agents/base_agent.js' },
21
+ functionQuery: {
22
+ className: 'BaseAgent',
23
+ methodName: 'runAsync',
24
+ kind: 'Async'
25
+ }
26
+ }
27
+ ]
28
+ }
29
+
30
+ const toolRunAsync = {
31
+ path: './google-adk/tool-run-async.js',
32
+ instrumentations: [
33
+ {
34
+ channelName: 'nr_toolRunAsync',
35
+ module: { name: '@google/adk', versionRange: '>=1.1.0', filePath: 'dist/cjs/tools/function_tool.js' },
36
+ functionQuery: {
37
+ className: 'FunctionTool',
38
+ methodName: 'runAsync',
39
+ kind: 'Async'
40
+ }
41
+ },
42
+ {
43
+ channelName: 'nr_toolRunAsync',
44
+ module: { name: '@google/adk', versionRange: '>=1.1.0', filePath: 'dist/esm/tools/function_tool.js' },
45
+ functionQuery: {
46
+ className: 'FunctionTool',
47
+ methodName: 'runAsync',
48
+ kind: 'Async'
49
+ }
50
+ }
51
+ ]
52
+ }
53
+
54
+ module.exports = {
55
+ '@google/adk': [
56
+ agentRunAsync,
57
+ toolRunAsync
58
+ ]
59
+ }