newrelic 11.22.0 → 11.23.1
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 +37 -0
- package/lib/config/index.js +10 -4
- package/lib/errors/error-collector.js +49 -59
- package/lib/errors/index.js +9 -10
- package/lib/instrumentation/@node-redis/client.js +69 -39
- package/lib/instrumentation/aws-sdk/v3/bedrock.js +23 -2
- package/lib/instrumentation/langchain/runnable.js +13 -1
- package/lib/instrumentation/langchain/tools.js +10 -1
- package/lib/instrumentation/langchain/vectorstore.js +14 -4
- package/lib/instrumentation/openai.js +21 -2
- package/lib/symbols.js +1 -0
- package/package.json +1 -1
package/NEWS.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
|
+
### v11.23.1 (2024-07-11)
|
|
2
|
+
|
|
3
|
+
#### Bug fixes
|
|
4
|
+
|
|
5
|
+
* Updated redis v4 instrumentation to work with transactions(multi/exec) ([#2343](https://github.com/newrelic/node-newrelic/pull/2343)) ([39eb842](https://github.com/newrelic/node-newrelic/commit/39eb8421b84f7fe298acf5c9c89de31ee0cc2604))
|
|
6
|
+
|
|
7
|
+
#### Documentation
|
|
8
|
+
|
|
9
|
+
* Updated compatibility report ([#2342](https://github.com/newrelic/node-newrelic/pull/2342)) ([5c9e3e6](https://github.com/newrelic/node-newrelic/commit/5c9e3e6bfa8a388c7dd071ecb0231b069f065645))
|
|
10
|
+
|
|
11
|
+
### v11.23.0 (2024-07-10)
|
|
12
|
+
|
|
13
|
+
#### Features
|
|
14
|
+
|
|
15
|
+
* Added support for account level governance of AI Monitoring ([#2326](https://github.com/newrelic/node-newrelic/pull/2326)) ([7069335](https://github.com/newrelic/node-newrelic/commit/7069335bfee38b1774da00bdbb63138ebf38da90))
|
|
16
|
+
|
|
17
|
+
#### Code refactoring
|
|
18
|
+
|
|
19
|
+
* Removed redundant isExpected in the Exception class ([#2328](https://github.com/newrelic/node-newrelic/pull/2328)) ([38f9825](https://github.com/newrelic/node-newrelic/commit/38f982564c0e0b93f17146be8beed005f9405ead))
|
|
20
|
+
* Reduced duplication in the error-collector ([#2323](https://github.com/newrelic/node-newrelic/pull/2323)) ([10581bf](https://github.com/newrelic/node-newrelic/commit/10581bf8cdad5c61c25dc1309ad97ca36d58cf79))
|
|
21
|
+
* Refactored benchmark tests to complete async functions ([#2334](https://github.com/newrelic/node-newrelic/pull/2334)) ([57a4dfb](https://github.com/newrelic/node-newrelic/commit/57a4dfb77c0408cbd81291c71db770005a0f2b5a))
|
|
22
|
+
|
|
23
|
+
#### Documentation
|
|
24
|
+
|
|
25
|
+
* Included commands and links for Mac setup ([#2327](https://github.com/newrelic/node-newrelic/pull/2327)) ([6eddb72](https://github.com/newrelic/node-newrelic/commit/6eddb721b676b246e5ace28bea75c6cd723d5ddb))
|
|
26
|
+
* Updated compatibility report ([#2318](https://github.com/newrelic/node-newrelic/pull/2318)) ([3a910ef](https://github.com/newrelic/node-newrelic/commit/3a910ef29c76cfd05903f01fb84d6775f8669578))
|
|
27
|
+
|
|
28
|
+
#### Miscellaneous chores
|
|
29
|
+
|
|
30
|
+
* Fixed copy paste error in post release workflow ([#2329](https://github.com/newrelic/node-newrelic/pull/2329)) ([6f2da7a](https://github.com/newrelic/node-newrelic/commit/6f2da7a2a07ce699f8d6ef859b4a90f0bd68df15))
|
|
31
|
+
* Implemented split jobs for post release docs publishing ([#2319](https://github.com/newrelic/node-newrelic/pull/2319)) ([c14ec3b](https://github.com/newrelic/node-newrelic/commit/c14ec3b7020f43f6515609346f3b2f9586e63430))
|
|
32
|
+
|
|
33
|
+
#### Tests
|
|
34
|
+
|
|
35
|
+
* Fixed recordMiddlewawre benchmark test ([#2338](https://github.com/newrelic/node-newrelic/pull/2338)) ([fb55ac7](https://github.com/newrelic/node-newrelic/commit/fb55ac7e19a26c76d19ead169664e40e0df4b822))
|
|
36
|
+
|
|
1
37
|
### v11.22.0 (2024-06-28)
|
|
2
38
|
|
|
39
|
+
|
|
3
40
|
#### Features
|
|
4
41
|
|
|
5
42
|
* Added support for Node 22([#2305](https://github.com/newrelic/node-newrelic/pull/2305)) ([0bf8908](https://github.com/newrelic/node-newrelic/commit/0bf89081a59fe598b22613257f519c171149c454))
|
package/lib/config/index.js
CHANGED
|
@@ -306,6 +306,12 @@ Config.prototype._fromServer = function _fromServer(params, key) {
|
|
|
306
306
|
case 'high_security':
|
|
307
307
|
break
|
|
308
308
|
|
|
309
|
+
// interpret AI Monitoring account setting
|
|
310
|
+
case 'collect_ai':
|
|
311
|
+
this._disableOption(params.collect_ai, 'ai_monitoring')
|
|
312
|
+
this.emit('change', this)
|
|
313
|
+
break
|
|
314
|
+
|
|
309
315
|
// always accept these settings
|
|
310
316
|
case 'cross_process_id':
|
|
311
317
|
case 'encoding_key':
|
|
@@ -1071,10 +1077,10 @@ function setFromEnv({ config, key, envVar, formatter, paths }) {
|
|
|
1071
1077
|
/**
|
|
1072
1078
|
* Recursively visit the nodes of the config definition and look for environment variable names, overriding any configuration values that are found.
|
|
1073
1079
|
*
|
|
1074
|
-
* @param {object} [config
|
|
1075
|
-
* @param {object} [data
|
|
1076
|
-
* @param {Array} [paths
|
|
1077
|
-
* @param {number} [objectKeys
|
|
1080
|
+
* @param {object} [config] The current level of the configuration object.
|
|
1081
|
+
* @param {object} [data] The current level of the config definition object.
|
|
1082
|
+
* @param {Array} [paths] keeps track of the nested path to properly derive the env var
|
|
1083
|
+
* @param {number} [objectKeys] indicator of how many keys exist in current node to know when to remove current node after all keys are processed
|
|
1078
1084
|
*/
|
|
1079
1085
|
Config.prototype._fromEnvironment = function _fromEnvironment(
|
|
1080
1086
|
config = this,
|
|
@@ -89,75 +89,62 @@ class ErrorCollector {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
*
|
|
92
|
+
* Gets the iterable property from the transaction based on the error type
|
|
93
93
|
*
|
|
94
94
|
* @param {Transaction} transaction the collected exception's transaction
|
|
95
|
-
* @param {
|
|
96
|
-
* @
|
|
97
|
-
* @returns {Array.<number>} the updated [collectedErrors, expectedErrors] numbers post-processing
|
|
95
|
+
* @param {string} errorType the type of error: "user", "transactionException", "transaction"
|
|
96
|
+
* @returns {object[]} the iterable property from the transaction based on the error type
|
|
98
97
|
*/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (this.collect(transaction, exception)) {
|
|
104
|
-
++collectedErrors
|
|
105
|
-
// if we could collect it, then check if expected
|
|
106
|
-
if (
|
|
107
|
-
urltils.isExpectedError(this.config, transaction.statusCode) ||
|
|
108
|
-
errorHelper.isExpectedException(transaction, exception, this.config, urltils)
|
|
109
|
-
) {
|
|
110
|
-
++expectedErrors
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
98
|
+
_getIterableProperty(transaction, errorType) {
|
|
99
|
+
let iterableProperty = null
|
|
100
|
+
if (errorType === 'user') {
|
|
101
|
+
iterableProperty = transaction.userErrors
|
|
114
102
|
}
|
|
115
|
-
|
|
116
|
-
|
|
103
|
+
if (errorType === 'transactionException') {
|
|
104
|
+
iterableProperty = transaction.exceptions
|
|
105
|
+
}
|
|
106
|
+
return iterableProperty
|
|
117
107
|
}
|
|
118
108
|
|
|
119
109
|
/**
|
|
120
|
-
* Helper method for processing
|
|
110
|
+
* Helper method for processing errors that are created with .noticeError(), exceptions
|
|
111
|
+
* on the transaction (transaction.exceptions array), and inferred errors based on Transaction metadata.
|
|
121
112
|
*
|
|
122
|
-
* @param {Transaction} transaction the
|
|
123
|
-
* @param {number} collectedErrors the number of errors successfully .collect()-ed
|
|
124
|
-
* @param {number} expectedErrors the number of
|
|
125
|
-
* @
|
|
113
|
+
* @param {Transaction} transaction the collected exception's transaction
|
|
114
|
+
* @param {number} collectedErrors the number of errors we've successfully .collect()-ed
|
|
115
|
+
* @param {number} expectedErrors the number of errors marked as expected in noticeError
|
|
116
|
+
* @param {string} errorType the type of error to be processed; "user", "transactionException", "transaction"
|
|
117
|
+
* @returns {Array.<number>} the updated [collectedErrors, expectedErrors] numbers post processing
|
|
126
118
|
*/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (this.collect(transaction
|
|
131
|
-
++
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
urltils.isExpectedError(this.config, transaction.statusCode) ||
|
|
135
|
-
errorHelper.isExpectedException(transaction, exception, this.config, urltils)
|
|
136
|
-
) {
|
|
137
|
-
++expectedErrors
|
|
119
|
+
_processErrors(transaction, collectedErrors, expectedErrors, errorType) {
|
|
120
|
+
const iterableProperty = this._getIterableProperty(transaction, errorType)
|
|
121
|
+
if (iterableProperty === null && errorType === 'transaction') {
|
|
122
|
+
if (this.collect(transaction)) {
|
|
123
|
+
collectedErrors++
|
|
124
|
+
if (urltils.isExpectedError(this.config, transaction.statusCode)) {
|
|
125
|
+
expectedErrors++
|
|
138
126
|
}
|
|
139
127
|
}
|
|
128
|
+
return [collectedErrors, expectedErrors]
|
|
140
129
|
}
|
|
141
130
|
|
|
142
|
-
|
|
143
|
-
|
|
131
|
+
if (iterableProperty === null) {
|
|
132
|
+
return [collectedErrors, expectedErrors]
|
|
133
|
+
}
|
|
144
134
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (urltils.isExpectedError(this.config, transaction.statusCode)) {
|
|
157
|
-
++expectedErrors
|
|
135
|
+
for (let i = 0; i < iterableProperty.length; i++) {
|
|
136
|
+
const exception = iterableProperty[i]
|
|
137
|
+
if (!this.collect(transaction, exception)) {
|
|
138
|
+
continue
|
|
139
|
+
}
|
|
140
|
+
collectedErrors++
|
|
141
|
+
if (
|
|
142
|
+
urltils.isExpectedError(this.config, transaction.statusCode) ||
|
|
143
|
+
errorHelper.isExpectedException(transaction, exception, this.config, urltils)
|
|
144
|
+
) {
|
|
145
|
+
expectedErrors++
|
|
158
146
|
}
|
|
159
147
|
}
|
|
160
|
-
|
|
161
148
|
return [collectedErrors, expectedErrors]
|
|
162
149
|
}
|
|
163
150
|
|
|
@@ -183,10 +170,11 @@ class ErrorCollector {
|
|
|
183
170
|
|
|
184
171
|
// errors from noticeError are currently exempt from
|
|
185
172
|
// ignore and exclude rules
|
|
186
|
-
;[collectedErrors, expectedErrors] = this.
|
|
173
|
+
;[collectedErrors, expectedErrors] = this._processErrors(
|
|
187
174
|
transaction,
|
|
188
175
|
collectedErrors,
|
|
189
|
-
expectedErrors
|
|
176
|
+
expectedErrors,
|
|
177
|
+
'user'
|
|
190
178
|
)
|
|
191
179
|
|
|
192
180
|
const isErroredTransaction = urltils.isError(this.config, transaction.statusCode)
|
|
@@ -194,16 +182,18 @@ class ErrorCollector {
|
|
|
194
182
|
|
|
195
183
|
// collect other exceptions only if status code is not ignored
|
|
196
184
|
if (transaction.exceptions.length && !isIgnoredErrorStatusCode) {
|
|
197
|
-
;[collectedErrors, expectedErrors] = this.
|
|
185
|
+
;[collectedErrors, expectedErrors] = this._processErrors(
|
|
198
186
|
transaction,
|
|
199
187
|
collectedErrors,
|
|
200
|
-
expectedErrors
|
|
188
|
+
expectedErrors,
|
|
189
|
+
'transactionException'
|
|
201
190
|
)
|
|
202
191
|
} else if (isErroredTransaction) {
|
|
203
|
-
;[collectedErrors, expectedErrors] = this.
|
|
192
|
+
;[collectedErrors, expectedErrors] = this._processErrors(
|
|
204
193
|
transaction,
|
|
205
194
|
collectedErrors,
|
|
206
|
-
expectedErrors
|
|
195
|
+
expectedErrors,
|
|
196
|
+
'transaction'
|
|
207
197
|
)
|
|
208
198
|
}
|
|
209
199
|
|
package/lib/errors/index.js
CHANGED
|
@@ -31,19 +31,18 @@ class Exception {
|
|
|
31
31
|
|
|
32
32
|
getErrorDetails(config) {
|
|
33
33
|
const errorDetails = errorHelper.extractErrorInformation(null, this.error, config)
|
|
34
|
-
errorDetails.expected = this.isExpected(config, errorDetails)
|
|
35
|
-
|
|
36
|
-
return errorDetails
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
isExpected(config, { type, message }) {
|
|
40
34
|
if (typeof this._expected === 'undefined') {
|
|
41
|
-
this._expected =
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
this._expected = errorHelper.isExpected(
|
|
36
|
+
errorDetails.type,
|
|
37
|
+
errorDetails.message,
|
|
38
|
+
null,
|
|
39
|
+
config,
|
|
40
|
+
urltils
|
|
41
|
+
)
|
|
44
42
|
}
|
|
43
|
+
errorDetails.expected = this._expected
|
|
45
44
|
|
|
46
|
-
return
|
|
45
|
+
return errorDetails
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -7,63 +7,78 @@
|
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
9
|
OperationSpec,
|
|
10
|
-
params: { DatastoreParameters }
|
|
10
|
+
params: { DatastoreParameters },
|
|
11
|
+
ClassWrapSpec
|
|
11
12
|
} = require('../../shim/specs')
|
|
12
|
-
const
|
|
13
|
-
const opts = Symbol('clientOptions')
|
|
13
|
+
const { redisClientOpts } = require('../../symbols')
|
|
14
14
|
|
|
15
15
|
module.exports = function initialize(_agent, redis, _moduleName, shim) {
|
|
16
16
|
shim.setDatastore(shim.REDIS)
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
shim.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
client.v4[opts] = getRedisParams(client.options)
|
|
26
|
-
CMDS_TO_INSTRUMENT.forEach(instrumentClientCommand.bind(null, shim, client.v4))
|
|
17
|
+
const commandsQueue = shim.require('dist/lib/client/commands-queue.js')
|
|
18
|
+
|
|
19
|
+
shim.wrapClass(
|
|
20
|
+
commandsQueue,
|
|
21
|
+
'default',
|
|
22
|
+
new ClassWrapSpec({
|
|
23
|
+
post: function postConstructor(shim) {
|
|
24
|
+
instrumentAddCommand({ shim, commandsQueue: this })
|
|
27
25
|
}
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
shim.wrap(redis, 'createClient', function wrapCreateClient(_shim, createClient) {
|
|
30
|
+
return function wrappedCreateClient(options) {
|
|
31
|
+
// saving connection opts to shim
|
|
32
|
+
// since the RedisCommandsQueue gets constructed at createClient
|
|
33
|
+
// we can delete the symbol afterwards to ensure the appropriate
|
|
34
|
+
// connection options are for the given RedisCommandsQueue
|
|
35
|
+
shim[redisClientOpts] = getRedisParams(options)
|
|
36
|
+
const client = createClient.apply(this, arguments)
|
|
37
|
+
delete shim[redisClientOpts]
|
|
28
38
|
return client
|
|
29
39
|
}
|
|
30
40
|
})
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
/**
|
|
34
|
-
* Instruments a given command
|
|
44
|
+
* Instruments a given command when added to the command queue by calling `shim.recordOperation`
|
|
35
45
|
*
|
|
36
|
-
* @param {
|
|
37
|
-
* @param {
|
|
38
|
-
* @param {
|
|
46
|
+
* @param {object} params
|
|
47
|
+
* @param {Shim} params.shim shim instance
|
|
48
|
+
* @param {object} params.commandsQueue instance
|
|
39
49
|
*/
|
|
40
|
-
function
|
|
50
|
+
function instrumentAddCommand({ shim, commandsQueue }) {
|
|
41
51
|
const { agent } = shim
|
|
52
|
+
const clientOpts = shim[redisClientOpts]
|
|
42
53
|
|
|
43
|
-
shim.recordOperation(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
parameters.key = JSON.stringify(key)
|
|
54
|
+
shim.recordOperation(
|
|
55
|
+
commandsQueue,
|
|
56
|
+
'addCommand',
|
|
57
|
+
function wrapAddCommand(_shim, _fn, _fnName, args) {
|
|
58
|
+
const [cmd, key, value] = args[0]
|
|
59
|
+
const parameters = Object.assign({}, clientOpts)
|
|
60
|
+
// If selecting a database, subsequent commands
|
|
61
|
+
// will be using said database, update the clientOpts
|
|
62
|
+
// but not the current parameters(feature parity with v3)
|
|
63
|
+
if (cmd.toLowerCase() === 'select') {
|
|
64
|
+
clientOpts.database_name = key
|
|
55
65
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
66
|
+
if (agent.config.attributes.enabled) {
|
|
67
|
+
if (key) {
|
|
68
|
+
parameters.key = JSON.stringify(key)
|
|
69
|
+
}
|
|
70
|
+
if (value) {
|
|
71
|
+
parameters.value = JSON.stringify(value)
|
|
72
|
+
}
|
|
58
73
|
}
|
|
59
|
-
}
|
|
60
74
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
return new OperationSpec({
|
|
76
|
+
name: (cmd && cmd.toLowerCase()) || 'other',
|
|
77
|
+
parameters,
|
|
78
|
+
promise: true
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
)
|
|
67
82
|
}
|
|
68
83
|
|
|
69
84
|
/**
|
|
@@ -73,6 +88,21 @@ function instrumentClientCommand(shim, client, cmd) {
|
|
|
73
88
|
* @returns {object} params
|
|
74
89
|
*/
|
|
75
90
|
function getRedisParams(clientOpts) {
|
|
91
|
+
// need to replicate logic done in RedisClient
|
|
92
|
+
// to parse the url to assign to socket.host/port
|
|
93
|
+
// see: https://github.com/redis/node-redis/blob/5576a0db492cda2cd88e09881bc330aa956dd0f5/packages/client/lib/client/index.ts#L160
|
|
94
|
+
if (clientOpts?.url) {
|
|
95
|
+
const parsedURL = new URL(clientOpts.url)
|
|
96
|
+
clientOpts.socket = { host: parsedURL.hostname }
|
|
97
|
+
if (parsedURL.port) {
|
|
98
|
+
clientOpts.socket.port = parsedURL.port
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (parsedURL.pathname) {
|
|
102
|
+
clientOpts.database = parsedURL.pathname.substring(1)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
76
106
|
return new DatastoreParameters({
|
|
77
107
|
host: clientOpts?.socket?.host || 'localhost',
|
|
78
108
|
port_path_or_id: clientOpts?.socket?.path || clientOpts?.socket?.port || '6379',
|
|
@@ -85,8 +85,21 @@ function addLlmMeta({ agent, segment }) {
|
|
|
85
85
|
* @param {BedrockCommand} params.bedrockCommand parsed input
|
|
86
86
|
* @param {Error|null} params.err error from request if exists
|
|
87
87
|
* @param params.bedrockResponse
|
|
88
|
+
* @param params.shim
|
|
88
89
|
*/
|
|
89
|
-
function recordChatCompletionMessages({
|
|
90
|
+
function recordChatCompletionMessages({
|
|
91
|
+
agent,
|
|
92
|
+
shim,
|
|
93
|
+
segment,
|
|
94
|
+
bedrockCommand,
|
|
95
|
+
bedrockResponse,
|
|
96
|
+
err
|
|
97
|
+
}) {
|
|
98
|
+
if (shouldSkipInstrumentation(agent.config) === true) {
|
|
99
|
+
shim.logger.debug('skipping sending of ai data')
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
90
103
|
const summary = new LlmChatCompletionSummary({
|
|
91
104
|
agent,
|
|
92
105
|
bedrockResponse,
|
|
@@ -133,12 +146,18 @@ function recordChatCompletionMessages({ agent, segment, bedrockCommand, bedrockR
|
|
|
133
146
|
*
|
|
134
147
|
* @param {object} params function params
|
|
135
148
|
* @param {object} params.agent instance of agent
|
|
149
|
+
* @param {object} params.shim current shim instance
|
|
136
150
|
* @param {object} params.segment active segment
|
|
137
151
|
* @param {BedrockCommand} params.bedrockCommand parsed input
|
|
138
152
|
* @param {Error|null} params.err error from request if exists
|
|
139
153
|
* @param params.bedrockResponse
|
|
140
154
|
*/
|
|
141
|
-
function recordEmbeddingMessage({ agent, segment, bedrockCommand, bedrockResponse, err }) {
|
|
155
|
+
function recordEmbeddingMessage({ agent, shim, segment, bedrockCommand, bedrockResponse, err }) {
|
|
156
|
+
if (shouldSkipInstrumentation(agent.config) === true) {
|
|
157
|
+
shim.logger.debug('skipping sending of ai data')
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
142
161
|
const embedding = new LlmEmbedding({
|
|
143
162
|
agent,
|
|
144
163
|
segment,
|
|
@@ -239,6 +258,7 @@ function handleResponse({ shim, err, response, segment, bedrockCommand, modelTyp
|
|
|
239
258
|
if (modelType === 'completion') {
|
|
240
259
|
recordChatCompletionMessages({
|
|
241
260
|
agent,
|
|
261
|
+
shim,
|
|
242
262
|
segment,
|
|
243
263
|
bedrockCommand,
|
|
244
264
|
bedrockResponse,
|
|
@@ -247,6 +267,7 @@ function handleResponse({ shim, err, response, segment, bedrockCommand, modelTyp
|
|
|
247
267
|
} else if (modelType === 'embedding') {
|
|
248
268
|
recordEmbeddingMessage({
|
|
249
269
|
agent,
|
|
270
|
+
shim,
|
|
250
271
|
segment,
|
|
251
272
|
bedrockCommand,
|
|
252
273
|
bedrockResponse,
|
|
@@ -16,13 +16,14 @@ const LlmErrorMessage = require('../../llm-events/error-message')
|
|
|
16
16
|
const { DESTINATIONS } = require('../../config/attribute-filter')
|
|
17
17
|
const { langchainRunId } = require('../../symbols')
|
|
18
18
|
const { RecorderSpec } = require('../../shim/specs')
|
|
19
|
+
const { shouldSkipInstrumentation } = require('./common')
|
|
19
20
|
|
|
20
21
|
module.exports = function initialize(shim, langchain) {
|
|
21
22
|
const { agent, pkgVersion } = shim
|
|
22
23
|
|
|
23
24
|
if (common.shouldSkipInstrumentation(agent.config)) {
|
|
24
25
|
shim.logger.debug(
|
|
25
|
-
'langchain instrumentation is disabled.
|
|
26
|
+
'langchain instrumentation is disabled. To enable set `config.ai_monitoring.enabled` to true'
|
|
26
27
|
)
|
|
27
28
|
return
|
|
28
29
|
}
|
|
@@ -186,6 +187,15 @@ function wrapNextHandler({ shim, output, segment, request, metadata, tags }) {
|
|
|
186
187
|
function recordChatCompletionEvents({ segment, messages, events, metadata, tags, err, shim }) {
|
|
187
188
|
const { pkgVersion, agent } = shim
|
|
188
189
|
segment.end()
|
|
190
|
+
|
|
191
|
+
if (shouldSkipInstrumentation(shim.agent.config) === true) {
|
|
192
|
+
// We need this check inside the wrapper because it is possible for monitoring
|
|
193
|
+
// to be disabled at the account level. In such a case, the value is set
|
|
194
|
+
// after the instrumentation has been initialized.
|
|
195
|
+
shim.logger.debug('skipping sending of ai data')
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
|
|
189
199
|
const completionSummary = new LangChainCompletionSummary({
|
|
190
200
|
agent,
|
|
191
201
|
messages,
|
|
@@ -198,6 +208,7 @@ function recordChatCompletionEvents({ segment, messages, events, metadata, tags,
|
|
|
198
208
|
|
|
199
209
|
common.recordEvent({
|
|
200
210
|
agent,
|
|
211
|
+
shim,
|
|
201
212
|
type: 'LlmChatCompletionSummary',
|
|
202
213
|
pkgVersion,
|
|
203
214
|
msg: completionSummary
|
|
@@ -266,6 +277,7 @@ function recordCompletions({ events, completionSummary, agent, segment, shim })
|
|
|
266
277
|
|
|
267
278
|
common.recordEvent({
|
|
268
279
|
agent,
|
|
280
|
+
shim,
|
|
269
281
|
type: 'LlmChatCompletionMessage',
|
|
270
282
|
pkgVersion: shim.pkgVersion,
|
|
271
283
|
msg: completionMsg
|
|
@@ -35,6 +35,15 @@ module.exports = function initialize(shim, tools) {
|
|
|
35
35
|
const metadata = mergeMetadata(instanceMeta, paramsMeta)
|
|
36
36
|
const tags = mergeTags(instanceTags, paramsTags)
|
|
37
37
|
segment.end()
|
|
38
|
+
|
|
39
|
+
if (shouldSkipInstrumentation(shim.agent.config) === true) {
|
|
40
|
+
// We need this check inside the wrapper because it is possible for monitoring
|
|
41
|
+
// to be disabled at the account level. In such a case, the value is set
|
|
42
|
+
// after the instrumentation has been initialized.
|
|
43
|
+
shim.logger.debug('skipping sending of ai data')
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
const toolEvent = new LangChainTool({
|
|
39
48
|
agent,
|
|
40
49
|
description,
|
|
@@ -47,7 +56,7 @@ module.exports = function initialize(shim, tools) {
|
|
|
47
56
|
segment,
|
|
48
57
|
error: err != null
|
|
49
58
|
})
|
|
50
|
-
recordEvent({ agent, type: 'LlmTool', pkgVersion, msg: toolEvent })
|
|
59
|
+
recordEvent({ agent, shim, type: 'LlmTool', pkgVersion, msg: toolEvent })
|
|
51
60
|
|
|
52
61
|
if (err) {
|
|
53
62
|
agent.errors.add(
|
|
@@ -23,11 +23,12 @@ const LlmErrorMessage = require('../../llm-events/error-message')
|
|
|
23
23
|
* @param {number} params.k vector search top k
|
|
24
24
|
* @param {object} params.output vector search documents
|
|
25
25
|
* @param {Agent} params.agent NR agent instance
|
|
26
|
+
* @param {Shim} params.shim current shim instance
|
|
26
27
|
* @param {TraceSegment} params.segment active segment from vector search
|
|
27
28
|
* @param {string} params.pkgVersion langchain version
|
|
28
|
-
* @param {
|
|
29
|
+
* @param {Error} params.err if it exists
|
|
29
30
|
*/
|
|
30
|
-
function recordVectorSearch({ request, k, output, agent, segment, pkgVersion, err }) {
|
|
31
|
+
function recordVectorSearch({ request, k, output, agent, shim, segment, pkgVersion, err }) {
|
|
31
32
|
const vectorSearch = new LangChainVectorSearch({
|
|
32
33
|
agent,
|
|
33
34
|
segment,
|
|
@@ -37,7 +38,7 @@ function recordVectorSearch({ request, k, output, agent, segment, pkgVersion, er
|
|
|
37
38
|
error: err !== null
|
|
38
39
|
})
|
|
39
40
|
|
|
40
|
-
recordEvent({ agent, type: 'LlmVectorSearch', pkgVersion, msg: vectorSearch })
|
|
41
|
+
recordEvent({ agent, shim, type: 'LlmVectorSearch', pkgVersion, msg: vectorSearch })
|
|
41
42
|
|
|
42
43
|
output.forEach((document, sequence) => {
|
|
43
44
|
const vectorSearchResult = new LangChainVectorSearchResult({
|
|
@@ -51,6 +52,7 @@ function recordVectorSearch({ request, k, output, agent, segment, pkgVersion, er
|
|
|
51
52
|
|
|
52
53
|
recordEvent({
|
|
53
54
|
agent,
|
|
55
|
+
shim,
|
|
54
56
|
type: 'LlmVectorSearchResult',
|
|
55
57
|
pkgVersion,
|
|
56
58
|
msg: vectorSearchResult
|
|
@@ -97,7 +99,15 @@ module.exports = function initialize(shim, vectorstores) {
|
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
segment.end()
|
|
100
|
-
|
|
102
|
+
if (shouldSkipInstrumentation(shim.agent.config) === true) {
|
|
103
|
+
// We need this check inside the wrapper because it is possible for monitoring
|
|
104
|
+
// to be disabled at the account level. In such a case, the value is set
|
|
105
|
+
// after the instrumentation has been initialized.
|
|
106
|
+
shim.logger.debug('skipping sending of ai data')
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
recordVectorSearch({ request, k, output, agent, shim, segment, pkgVersion, err })
|
|
101
111
|
|
|
102
112
|
segment.transaction.trace.attributes.addAttribute(DESTINATIONS.TRANS_EVENT, 'llm', true)
|
|
103
113
|
}
|
|
@@ -99,12 +99,18 @@ function addLlmMeta({ agent, segment }) {
|
|
|
99
99
|
*
|
|
100
100
|
* @param {object} params input params
|
|
101
101
|
* @param {Agent} params.agent NR agent instance
|
|
102
|
+
* @param {Shim} params.shim the current shim instance
|
|
102
103
|
* @param {TraceSegment} params.segment active segment from chat completion
|
|
103
104
|
* @param {object} params.request chat completion params
|
|
104
105
|
* @param {object} params.response chat completion response
|
|
105
106
|
* @param {boolean} [params.err] err if it exists
|
|
106
107
|
*/
|
|
107
|
-
function recordChatCompletionMessages({ agent, segment, request, response, err }) {
|
|
108
|
+
function recordChatCompletionMessages({ agent, shim, segment, request, response, err }) {
|
|
109
|
+
if (shouldSkipInstrumentation(agent.config, shim) === true) {
|
|
110
|
+
shim.logger.debug('skipping sending of ai data')
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
108
114
|
if (!response) {
|
|
109
115
|
// If we get an error, it is possible that `response = null`.
|
|
110
116
|
// In that case, we define it to be an empty object.
|
|
@@ -195,6 +201,7 @@ function instrumentStream({ agent, shim, request, response, segment }) {
|
|
|
195
201
|
|
|
196
202
|
recordChatCompletionMessages({
|
|
197
203
|
agent: shim.agent,
|
|
204
|
+
shim,
|
|
198
205
|
segment,
|
|
199
206
|
request,
|
|
200
207
|
response: chunk,
|
|
@@ -205,6 +212,7 @@ function instrumentStream({ agent, shim, request, response, segment }) {
|
|
|
205
212
|
})
|
|
206
213
|
}
|
|
207
214
|
|
|
215
|
+
/* eslint-disable sonarjs/cognitive-complexity */
|
|
208
216
|
module.exports = function initialize(agent, openai, moduleName, shim) {
|
|
209
217
|
if (shouldSkipInstrumentation(agent.config, shim)) {
|
|
210
218
|
shim.logger.debug(
|
|
@@ -268,6 +276,7 @@ module.exports = function initialize(agent, openai, moduleName, shim) {
|
|
|
268
276
|
} else {
|
|
269
277
|
recordChatCompletionMessages({
|
|
270
278
|
agent,
|
|
279
|
+
shim,
|
|
271
280
|
segment,
|
|
272
281
|
request,
|
|
273
282
|
response,
|
|
@@ -301,10 +310,20 @@ module.exports = function initialize(agent, openai, moduleName, shim) {
|
|
|
301
310
|
// In that case, we define it to be an empty object.
|
|
302
311
|
response = {}
|
|
303
312
|
}
|
|
313
|
+
|
|
314
|
+
segment.end()
|
|
315
|
+
if (shouldSkipInstrumentation(shim.agent.config, shim) === true) {
|
|
316
|
+
// We need this check inside the wrapper because it is possible for monitoring
|
|
317
|
+
// to be disabled at the account level. In such a case, the value is set
|
|
318
|
+
// after the instrumentation has been initialized.
|
|
319
|
+
shim.logger.debug('skipping sending of ai data')
|
|
320
|
+
return
|
|
321
|
+
}
|
|
322
|
+
|
|
304
323
|
response.headers = segment[openAiHeaders]
|
|
305
324
|
// explicitly end segment to get consistent duration
|
|
306
325
|
// for both LLM events and the segment
|
|
307
|
-
|
|
326
|
+
|
|
308
327
|
const embedding = new LlmEmbedding({
|
|
309
328
|
agent,
|
|
310
329
|
segment,
|
package/lib/symbols.js
CHANGED
|
@@ -27,6 +27,7 @@ module.exports = {
|
|
|
27
27
|
langchainRunId: Symbol('runId'),
|
|
28
28
|
prismaConnection: Symbol('prismaConnection'),
|
|
29
29
|
prismaModelCall: Symbol('modelCall'),
|
|
30
|
+
redisClientOpts: Symbol('clientOptions'),
|
|
30
31
|
segment: Symbol('segment'),
|
|
31
32
|
shim: Symbol('shim'),
|
|
32
33
|
storeDatabase: Symbol('storeDatabase'),
|