newrelic 13.2.1 → 13.3.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.
- package/NEWS.md +44 -10
- package/api.js +1 -1
- package/lib/instrumentation/@azure/functions.js +8 -46
- package/lib/instrumentation/core/http-outbound.js +26 -10
- package/lib/instrumentation/core/http.js +20 -118
- package/lib/instrumentations.js +0 -14
- package/lib/otel/logs/index.js +80 -0
- package/lib/otel/metrics/index.js +119 -0
- package/lib/otel/setup-signal.js +37 -0
- package/lib/otel/setup.js +15 -25
- package/lib/otel/{attr-reconciler.js → traces/attr-reconciler.js} +2 -2
- package/lib/otel/{exception-mapping.js → traces/exception-mapping.js} +1 -1
- package/lib/otel/traces/index.js +40 -0
- package/lib/otel/{rules.js → traces/rules.js} +1 -1
- package/lib/otel/{segment-synthesis.js → traces/segment-synthesis.js} +5 -4
- package/lib/otel/{segments → traces/segments}/consumer.js +4 -4
- package/lib/otel/{segments → traces/segments}/database.js +6 -6
- package/lib/otel/{segments → traces/segments}/http-external.js +11 -8
- package/lib/otel/traces/segments/index.js +22 -0
- package/lib/otel/{segments → traces/segments}/internal.js +1 -1
- package/lib/otel/{segments → traces/segments}/producer.js +2 -2
- package/lib/otel/{segments → traces/segments}/server.js +4 -4
- package/lib/otel/{segments → traces/segments}/utils.js +1 -1
- package/lib/otel/{span-processor.js → traces/span-processor.js} +13 -19
- package/lib/otel/{transformation-rules.json → traces/transformation-rules.json} +3 -2
- package/lib/otel/{utils.js → traces/utils.js} +2 -1
- package/lib/serverless/aws-lambda.js +7 -68
- package/lib/shim/webframework-shim/middleware.js +1 -1
- package/lib/shimmer.js +1 -1
- package/lib/subscriber-configs.js +2 -1
- package/lib/subscribers/base.js +30 -0
- package/lib/subscribers/elasticsearch/config.js +1 -0
- package/lib/subscribers/mcp-sdk/client-request.js +66 -0
- package/lib/subscribers/mcp-sdk/config.js +13 -75
- package/lib/subscribers/openai/base.js +21 -0
- package/lib/subscribers/openai/chat-responses.js +15 -0
- package/lib/subscribers/openai/chat.js +85 -0
- package/lib/subscribers/openai/client.js +31 -0
- package/lib/subscribers/openai/config.js +85 -0
- package/lib/subscribers/openai/embeddings.js +54 -0
- package/lib/subscribers/openai/utils.js +349 -0
- package/lib/transaction/index.js +157 -56
- package/lib/transaction/trace/segment.js +5 -2
- package/lib/util/urltils.js +158 -192
- package/lib/utilization/common.js +0 -6
- package/package.json +1 -1
- package/lib/instrumentation/openai.js +0 -482
- package/lib/otel/logs/bootstrap-logs.js +0 -84
- package/lib/otel/metrics/bootstrap-metrics.js +0 -117
- package/lib/otel/segments/index.js +0 -22
- package/lib/subscribers/mcp-sdk/client-prompt.js +0 -23
- package/lib/subscribers/mcp-sdk/client-resource.js +0 -24
- package/lib/subscribers/mcp-sdk/client-tool.js +0 -23
- package/lib/subscribers/mcp-sdk/client.js +0 -29
- /package/lib/otel/{constants.js → traces/constants.js} +0 -0
- /package/lib/otel/{sampler.js → traces/sampler.js} +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
const { MCP } = require('../../metrics/names')
|
|
10
|
+
|
|
11
|
+
class McpClientRequestSubscriber extends Subscriber {
|
|
12
|
+
constructor({ agent, logger }) {
|
|
13
|
+
super({ agent, logger, packageName: '@modelcontextprotocol/sdk', channelName: 'nr_request' })
|
|
14
|
+
this.events = ['asyncEnd']
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get enabled() {
|
|
18
|
+
return super.enabled && this.config.ai_monitoring.enabled === true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Determine the MCP function to record based on the incoming request.
|
|
23
|
+
* @param {*} args0 - The arguments passed to the request.
|
|
24
|
+
* @returns {Object} - An object containing the MCP prefix, function name, and primitive name.
|
|
25
|
+
*/
|
|
26
|
+
determineFunction(args0) {
|
|
27
|
+
const methodName = args0?.method
|
|
28
|
+
let mcpPrefix
|
|
29
|
+
let functionName
|
|
30
|
+
let primitiveName
|
|
31
|
+
|
|
32
|
+
if (methodName === 'tools/call') {
|
|
33
|
+
mcpPrefix = MCP.TOOL
|
|
34
|
+
functionName = 'callTool'
|
|
35
|
+
primitiveName = args0?.params?.name ?? 'tool'
|
|
36
|
+
} else if (methodName === 'prompts/get') {
|
|
37
|
+
mcpPrefix = MCP.PROMPT
|
|
38
|
+
functionName = 'getPrompt'
|
|
39
|
+
primitiveName = args0?.params?.name ?? 'prompt'
|
|
40
|
+
} else if (methodName === 'resources/read') {
|
|
41
|
+
mcpPrefix = MCP.RESOURCE
|
|
42
|
+
functionName = 'readResource'
|
|
43
|
+
const uri = args0?.params?.uri
|
|
44
|
+
primitiveName = typeof uri === 'string' ? uri.split('://')[0] : 'resource'
|
|
45
|
+
} else {
|
|
46
|
+
this.logger.debug(`@modelcontextprotocol/sdk: Will not create '${methodName}' segment.`)
|
|
47
|
+
}
|
|
48
|
+
return { mcpPrefix, functionName, primitiveName }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
handler(data, ctx) {
|
|
52
|
+
const { mcpPrefix, functionName, primitiveName } = this.determineFunction(data?.arguments?.[0])
|
|
53
|
+
if (!mcpPrefix || !functionName || !primitiveName) {
|
|
54
|
+
// If it is not a function we care about, don't instrument at all
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const segmentName = `${mcpPrefix}/${functionName}/${primitiveName}`
|
|
59
|
+
return this.createSegment({
|
|
60
|
+
name: segmentName,
|
|
61
|
+
ctx
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = McpClientRequestSubscriber
|
|
@@ -3,96 +3,32 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
path: './mcp-sdk/client-
|
|
6
|
+
const mcpClientRequestConfig = {
|
|
7
|
+
path: './mcp-sdk/client-request',
|
|
8
8
|
instrumentations: [
|
|
9
9
|
{
|
|
10
|
-
channelName: '
|
|
10
|
+
channelName: 'nr_request',
|
|
11
11
|
module: {
|
|
12
12
|
name: '@modelcontextprotocol/sdk',
|
|
13
13
|
versionRange: '>=1.13.0',
|
|
14
|
-
filePath: 'dist/cjs/
|
|
14
|
+
filePath: 'dist/cjs/shared/protocol.js'
|
|
15
15
|
},
|
|
16
16
|
functionQuery: {
|
|
17
|
-
className: '
|
|
18
|
-
methodName: '
|
|
17
|
+
className: 'Protocol',
|
|
18
|
+
methodName: 'request',
|
|
19
19
|
kind: 'Async'
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
|
-
channelName: '
|
|
23
|
+
channelName: 'nr_request',
|
|
24
24
|
module: {
|
|
25
25
|
name: '@modelcontextprotocol/sdk',
|
|
26
26
|
versionRange: '>=1.13.0',
|
|
27
|
-
filePath: 'dist/esm/
|
|
27
|
+
filePath: 'dist/esm/shared/protocol.js'
|
|
28
28
|
},
|
|
29
29
|
functionQuery: {
|
|
30
|
-
className: '
|
|
31
|
-
methodName: '
|
|
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',
|
|
30
|
+
className: 'Protocol',
|
|
31
|
+
methodName: 'request',
|
|
96
32
|
kind: 'Async'
|
|
97
33
|
}
|
|
98
34
|
},
|
|
@@ -100,5 +36,7 @@ const mcpClientPromptConfig = {
|
|
|
100
36
|
}
|
|
101
37
|
|
|
102
38
|
module.exports = {
|
|
103
|
-
'@modelcontextprotocol/sdk': [
|
|
39
|
+
'@modelcontextprotocol/sdk': [
|
|
40
|
+
mcpClientRequestConfig
|
|
41
|
+
]
|
|
104
42
|
}
|
|
@@ -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 Subscriber = require('../base')
|
|
9
|
+
|
|
10
|
+
class OpenAISubscriber extends Subscriber {
|
|
11
|
+
constructor({ agent, logger, channelName }) {
|
|
12
|
+
super({ agent, logger, packageName: 'openai', channelName })
|
|
13
|
+
this.events = ['asyncEnd']
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get enabled() {
|
|
17
|
+
return super.enabled && this.config.ai_monitoring?.enabled
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = OpenAISubscriber
|
|
@@ -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
|
+
const OpenAIChatCompletions = require('./chat')
|
|
8
|
+
|
|
9
|
+
class OpenAIResponses extends OpenAIChatCompletions {
|
|
10
|
+
constructor({ agent, logger }) {
|
|
11
|
+
super({ agent, logger, channelName: 'nr_responses' })
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = OpenAIResponses
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
/*
|
|
8
|
+
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
9
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const OpenAISubscriber = require('./base')
|
|
13
|
+
const { AI } = require('../../metrics/names')
|
|
14
|
+
const { OPENAI } = AI
|
|
15
|
+
const {
|
|
16
|
+
addLlmMeta,
|
|
17
|
+
recordChatCompletionMessages,
|
|
18
|
+
instrumentStream,
|
|
19
|
+
} = require('./utils')
|
|
20
|
+
const semver = require('semver')
|
|
21
|
+
const MIN_STREAM_VERSION = '4.12.2'
|
|
22
|
+
|
|
23
|
+
class OpenAIChatCompletions extends OpenAISubscriber {
|
|
24
|
+
constructor({ agent, logger, channelName = 'nr_completionsCreate' }) {
|
|
25
|
+
super({ agent, logger, channelName })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
handler(data, ctx) {
|
|
29
|
+
const { arguments: args, moduleVersion } = data
|
|
30
|
+
const [request] = args
|
|
31
|
+
if (request.stream && semver.lt(moduleVersion, MIN_STREAM_VERSION)) {
|
|
32
|
+
this.logger.warn(`Instrumenting chat completion streams is only supported with openai version ${MIN_STREAM_VERSION}+.`)
|
|
33
|
+
return ctx
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const segment = this.agent.tracer.createSegment({
|
|
37
|
+
name: OPENAI.COMPLETION,
|
|
38
|
+
parent: ctx.segment,
|
|
39
|
+
transaction: ctx.transaction
|
|
40
|
+
})
|
|
41
|
+
const newCtx = ctx.enterSegment({ segment })
|
|
42
|
+
return newCtx
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
asyncEnd(data) {
|
|
46
|
+
const ctx = this.agent.tracer.getContext()
|
|
47
|
+
if (!ctx?.segment || !ctx?.transaction) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
const { result: response, arguments: args, error: err } = data
|
|
51
|
+
const [request] = args
|
|
52
|
+
|
|
53
|
+
if (request.stream) {
|
|
54
|
+
instrumentStream({
|
|
55
|
+
agent: this.agent,
|
|
56
|
+
logger: this.logger,
|
|
57
|
+
request,
|
|
58
|
+
headers: ctx.extras?.headers,
|
|
59
|
+
response,
|
|
60
|
+
segment: ctx.segment,
|
|
61
|
+
transaction: ctx.transaction,
|
|
62
|
+
err
|
|
63
|
+
})
|
|
64
|
+
} else {
|
|
65
|
+
recordChatCompletionMessages({
|
|
66
|
+
agent: this.agent,
|
|
67
|
+
logger: this.logger,
|
|
68
|
+
segment: ctx.segment,
|
|
69
|
+
transaction: ctx.transaction,
|
|
70
|
+
request,
|
|
71
|
+
response,
|
|
72
|
+
headers: ctx.extras?.headers,
|
|
73
|
+
err
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
addLlmMeta({
|
|
78
|
+
agent: this.agent,
|
|
79
|
+
transaction: ctx.transaction,
|
|
80
|
+
version: data.moduleVersion,
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = OpenAIChatCompletions
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const OpenAISubscriber = require('./base')
|
|
8
|
+
class OpenAIClientSubscriber extends OpenAISubscriber {
|
|
9
|
+
constructor({ agent, logger }) {
|
|
10
|
+
super({ agent, logger, channelName: 'nr_makeRequest' })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
handler(data, ctx) {
|
|
14
|
+
const { self } = data
|
|
15
|
+
ctx.extras = { apiKey: self.apiKey }
|
|
16
|
+
return ctx
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
asyncEnd(data) {
|
|
20
|
+
const { result } = data
|
|
21
|
+
const ctx = this.agent.tracer.getContext()
|
|
22
|
+
if (ctx?.segment) {
|
|
23
|
+
const headers = result?.response?.headers
|
|
24
|
+
? Object.fromEntries(result.response.headers)
|
|
25
|
+
: { ...result?.headers }
|
|
26
|
+
ctx.extras = { headers }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = OpenAIClientSubscriber
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
openai: [
|
|
10
|
+
{
|
|
11
|
+
path: './openai/chat.js',
|
|
12
|
+
instrumentations: [
|
|
13
|
+
{
|
|
14
|
+
channelName: 'nr_completionsCreate',
|
|
15
|
+
module: { name: 'openai', versionRange: '>=4.0.0', filePath: 'resources/chat/completions.js' },
|
|
16
|
+
functionQuery: {
|
|
17
|
+
className: 'Completions',
|
|
18
|
+
methodName: 'create',
|
|
19
|
+
kind: 'Async'
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
channelName: 'nr_completionsCreate',
|
|
24
|
+
module: { name: 'openai', versionRange: '>=4.0.0', filePath: 'resources/chat/completions/completions.js' },
|
|
25
|
+
functionQuery: {
|
|
26
|
+
className: 'Completions',
|
|
27
|
+
methodName: 'create',
|
|
28
|
+
kind: 'Async'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
path: './openai/chat-responses.js',
|
|
35
|
+
instrumentations: [
|
|
36
|
+
{
|
|
37
|
+
channelName: 'nr_responses',
|
|
38
|
+
module: { name: 'openai', versionRange: '>=4.87.0', filePath: 'resources/responses/responses.js' },
|
|
39
|
+
functionQuery: {
|
|
40
|
+
className: 'Responses',
|
|
41
|
+
methodName: 'create',
|
|
42
|
+
kind: 'Async'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
path: './openai/client.js',
|
|
49
|
+
instrumentations: [
|
|
50
|
+
{
|
|
51
|
+
channelName: 'nr_makeRequest',
|
|
52
|
+
module: { name: 'openai', versionRange: '>=4.0.0', filePath: 'core.js' },
|
|
53
|
+
functionQuery: {
|
|
54
|
+
className: 'APIClient',
|
|
55
|
+
methodName: 'makeRequest',
|
|
56
|
+
kind: 'Async'
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
channelName: 'nr_makeRequest',
|
|
61
|
+
module: { name: 'openai', versionRange: '>=4.0.0', filePath: 'client.js' },
|
|
62
|
+
functionQuery: {
|
|
63
|
+
className: 'OpenAI',
|
|
64
|
+
methodName: 'makeRequest',
|
|
65
|
+
kind: 'Async'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
path: './openai/embeddings.js',
|
|
72
|
+
instrumentations: [
|
|
73
|
+
{
|
|
74
|
+
channelName: 'nr_embeddingsCreate',
|
|
75
|
+
module: { name: 'openai', versionRange: '>=4.0.0', filePath: 'resources/embeddings.js' },
|
|
76
|
+
functionQuery: {
|
|
77
|
+
className: 'Embeddings',
|
|
78
|
+
methodName: 'create',
|
|
79
|
+
kind: 'Async'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const OpenAISubscriber = require('./base')
|
|
8
|
+
const { AI } = require('../../metrics/names')
|
|
9
|
+
const { OPENAI } = AI
|
|
10
|
+
const {
|
|
11
|
+
addLlmMeta,
|
|
12
|
+
recordEmbeddingMessage
|
|
13
|
+
} = require('./utils')
|
|
14
|
+
|
|
15
|
+
class OpenAIEmbeddings extends OpenAISubscriber {
|
|
16
|
+
constructor({ agent, logger }) {
|
|
17
|
+
super({ agent, logger, channelName: 'nr_embeddingsCreate' })
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
handler(data, ctx) {
|
|
21
|
+
const segment = this.agent.tracer.createSegment({
|
|
22
|
+
name: OPENAI.EMBEDDING,
|
|
23
|
+
parent: ctx.segment,
|
|
24
|
+
transaction: ctx.transaction
|
|
25
|
+
})
|
|
26
|
+
const newCtx = ctx.enterSegment({ segment })
|
|
27
|
+
return newCtx
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
asyncEnd(data) {
|
|
31
|
+
const ctx = this.agent.tracer.getContext()
|
|
32
|
+
if (!ctx?.segment || !ctx?.transaction) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
const { arguments: args, error: err } = data
|
|
36
|
+
const { result: response } = data
|
|
37
|
+
const [request] = args
|
|
38
|
+
const agent = this.agent
|
|
39
|
+
const { segment, transaction } = ctx
|
|
40
|
+
recordEmbeddingMessage({
|
|
41
|
+
agent,
|
|
42
|
+
logger: this.logger,
|
|
43
|
+
segment,
|
|
44
|
+
transaction,
|
|
45
|
+
request,
|
|
46
|
+
response,
|
|
47
|
+
headers: ctx.extras?.headers,
|
|
48
|
+
err
|
|
49
|
+
})
|
|
50
|
+
addLlmMeta({ agent, transaction, version: data.moduleVersion })
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = OpenAIEmbeddings
|