newrelic 13.6.2 → 13.6.4
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 +33 -7
- package/README.md +6 -11
- package/lib/config/default.js +46 -4
- package/lib/config/index.js +110 -1
- package/lib/instrumentation/@google/genai.js +15 -24
- package/lib/instrumentation/aws-sdk/v3/bedrock.js +5 -0
- package/lib/instrumentations.js +0 -1
- package/lib/llm-events/aws-bedrock/bedrock-response.js +25 -1
- package/lib/llm-events/aws-bedrock/chat-completion-message.js +2 -10
- package/lib/llm-events/aws-bedrock/chat-completion-summary.js +11 -15
- package/lib/llm-events/aws-bedrock/converse-stream-handler.js +11 -4
- package/lib/llm-events/aws-bedrock/embedding.js +3 -20
- package/lib/llm-events/aws-bedrock/event.js +3 -20
- package/lib/llm-events/aws-bedrock/stream-handler.js +21 -28
- package/lib/llm-events/aws-bedrock/utils.js +1 -59
- package/lib/llm-events/event.js +108 -0
- package/lib/llm-events/google-genai/chat-completion-message.js +3 -10
- package/lib/llm-events/google-genai/chat-completion-summary.js +4 -5
- package/lib/llm-events/google-genai/embedding.js +0 -34
- package/lib/llm-events/google-genai/event.js +7 -0
- package/lib/llm-events/openai/chat-completion-message.js +3 -9
- package/lib/llm-events/openai/chat-completion-summary.js +4 -5
- package/lib/llm-events/openai/embedding.js +4 -15
- package/lib/llm-events/openai/event.js +7 -0
- package/lib/shim/datastore-shim.js +5 -7
- package/lib/subscriber-configs.js +2 -0
- package/lib/subscribers/base.js +1 -1
- package/lib/subscribers/message-consumer.js +9 -2
- package/lib/subscribers/mysql/config.js +73 -0
- package/lib/subscribers/mysql/connection-query.js +56 -0
- package/lib/subscribers/mysql/helper.js +102 -0
- package/lib/subscribers/mysql/pool-get-connection.js +20 -0
- package/lib/subscribers/mysql/pool-namespace-query.js +19 -0
- package/lib/subscribers/mysql/pool-query.js +41 -0
- package/lib/subscribers/mysql2/config.js +127 -0
- package/lib/subscribers/mysql2/connection-execute.js +18 -0
- package/lib/subscribers/mysql2/connection-query.js +17 -0
- package/lib/subscribers/mysql2/pool-get-connection.js +20 -0
- package/lib/subscribers/mysql2/pool-namespace-query.js +19 -0
- package/lib/subscribers/mysql2/pool-query.js +19 -0
- package/lib/subscribers/openai/utils.js +11 -2
- package/lib/subscribers/pg/query.js +1 -1
- package/package.json +1 -1
- package/lib/db/utils.js +0 -19
- package/lib/instrumentation/mysql/mysql.js +0 -333
- package/lib/instrumentation/mysql/nr-hooks.js +0 -26
- package/lib/llm-events/google-genai/utils.js +0 -32
- package/lib/llm-events/openai/utils.js +0 -34
- package/lib/llm-events/utils.js +0 -110
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict'
|
|
7
|
-
|
|
8
|
-
const dbutils = require('../../db/utils')
|
|
9
|
-
const properties = require('../../util/properties')
|
|
10
|
-
const symbols = require('../../symbols')
|
|
11
|
-
const { QuerySpec } = require('../../shim/specs')
|
|
12
|
-
const DatastoreParameters = require('../../shim/specs/params/datastore')
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Used to instrument `mysql` and `mysql2` packages
|
|
16
|
-
* the `mysql2/promise` instrumentation is below in `promiseInitialize`
|
|
17
|
-
*
|
|
18
|
-
* @param {Shim} shim instance of shim
|
|
19
|
-
* @param {object} mysql package to instrument
|
|
20
|
-
*/
|
|
21
|
-
function callbackInitialize(shim, mysql) {
|
|
22
|
-
shim.setDatastore(shim.MYSQL)
|
|
23
|
-
shim[symbols.wrappedPoolConnection] = false
|
|
24
|
-
|
|
25
|
-
shim.wrapReturn(mysql, 'createConnection', wrapCreateConnection)
|
|
26
|
-
shim.wrapReturn(mysql, 'createPool', wrapCreatePool)
|
|
27
|
-
shim.wrapReturn(mysql, 'createPoolCluster', wrapCreatePoolCluster)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Used to instrument `mysql2/promise`
|
|
32
|
-
*
|
|
33
|
-
* @param {Shim} shim instance of shim
|
|
34
|
-
* @param {object} mysql2 package to instrument
|
|
35
|
-
*/
|
|
36
|
-
function promiseInitialize(shim, mysql2) {
|
|
37
|
-
shim.setDatastore(shim.MYSQL)
|
|
38
|
-
shim[symbols.wrappedPoolConnection] = false
|
|
39
|
-
shim.wrap(
|
|
40
|
-
mysql2,
|
|
41
|
-
'createConnection',
|
|
42
|
-
function wrapPromiseCreateConnection(shim, createConnection) {
|
|
43
|
-
return async function wrappedPromiseCreateConnection() {
|
|
44
|
-
const promiseConnection = await createConnection.apply(this, arguments)
|
|
45
|
-
wrapCreateConnection(
|
|
46
|
-
shim,
|
|
47
|
-
createConnection,
|
|
48
|
-
'createConnection',
|
|
49
|
-
promiseConnection.connection
|
|
50
|
-
)
|
|
51
|
-
return promiseConnection
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
shim.wrap(mysql2, 'createPool', function wrapPromiseCreatePool(shim, createPool) {
|
|
57
|
-
return function wrappedPromiseCreatePool() {
|
|
58
|
-
const promisePool = createPool.apply(this, arguments)
|
|
59
|
-
wrapCreatePool(shim, createPool, 'createPool', promisePool.pool)
|
|
60
|
-
return promisePool
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
shim.wrap(
|
|
65
|
-
mysql2,
|
|
66
|
-
'createPoolCluster',
|
|
67
|
-
function wrapPromiseCreatePoolCluster(shim, createPoolCluster) {
|
|
68
|
-
return function wrappedPromiseCreatePoolCluster() {
|
|
69
|
-
const promisePoolCluster = createPoolCluster.apply(this, arguments)
|
|
70
|
-
wrapCreatePoolCluster(
|
|
71
|
-
shim,
|
|
72
|
-
createPoolCluster,
|
|
73
|
-
'createPoolCluster',
|
|
74
|
-
promisePoolCluster.poolCluster
|
|
75
|
-
)
|
|
76
|
-
return promisePoolCluster
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function wrapCreateConnection(shim, fn, fnName, connection) {
|
|
83
|
-
if (shim[symbols.unwrapConnection]) {
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
shim.logger.debug('Wrapping Connection#query')
|
|
87
|
-
if (wrapQueryable(shim, connection, false)) {
|
|
88
|
-
const connProto = Object.getPrototypeOf(connection)
|
|
89
|
-
connProto[symbols.storeDatabase] = true
|
|
90
|
-
shim[symbols.unwrapConnection] = true
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function wrapCreatePool(shim, fn, fnName, pool) {
|
|
95
|
-
if (shim[symbols.unwrapPool]) {
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
shim.logger.debug('Wrapping Pool#query and Pool#getConnection')
|
|
99
|
-
if (wrapQueryable(shim, pool, true) && wrapGetConnection(shim, pool)) {
|
|
100
|
-
shim[symbols.unwrapPool] = true
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function wrapCreatePoolCluster(shim, fn, fnName, poolCluster) {
|
|
105
|
-
if (shim[symbols.createPoolCluster]) {
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
shim.logger.debug('Wrapping PoolCluster#of')
|
|
109
|
-
const proto = Object.getPrototypeOf(poolCluster)
|
|
110
|
-
shim.wrapReturn(proto, 'of', wrapPoolClusterOf)
|
|
111
|
-
function wrapPoolClusterOf(shim, of, _n, poolNamespace) {
|
|
112
|
-
if (poolNamespace[symbols.clusterOf]) {
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (wrapGetConnection(shim, poolNamespace) && wrapQueryable(shim, poolNamespace, false)) {
|
|
117
|
-
poolNamespace[symbols.clusterOf] = true
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
shim.logger.debug('Wrapping PoolCluster#getConnection')
|
|
122
|
-
if (wrapGetConnection(shim, poolCluster)) {
|
|
123
|
-
shim[symbols.createPoolCluster] = true
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function wrapGetConnection(shim, connectable) {
|
|
128
|
-
if (!connectable || !connectable.getConnection || shim.isWrapped(connectable.getConnection)) {
|
|
129
|
-
shim.logger.trace(
|
|
130
|
-
{
|
|
131
|
-
connectable: !!connectable,
|
|
132
|
-
getConnection: !!(connectable && connectable.getConnection),
|
|
133
|
-
isWrapped: !!(connectable && shim.isWrapped(connectable.getConnection))
|
|
134
|
-
},
|
|
135
|
-
'Not wrapping getConnection'
|
|
136
|
-
)
|
|
137
|
-
return false
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const proto = Object.getPrototypeOf(connectable)
|
|
141
|
-
shim.wrap(proto, 'getConnection', function doWrapGetConnection(shim, fn) {
|
|
142
|
-
return function wrappedGetConnection() {
|
|
143
|
-
const args = shim.toArray(arguments)
|
|
144
|
-
const cbIdx = args.length - 1
|
|
145
|
-
|
|
146
|
-
// avoid an infinite loop and check both the cb and the "original" cb before re-wrapping
|
|
147
|
-
// this is only applicable now with the security agent + us doing the same thing
|
|
148
|
-
const original = shim.getOriginalOnce(args[cbIdx])
|
|
149
|
-
if (
|
|
150
|
-
shim.isFunction(args[cbIdx]) &&
|
|
151
|
-
!(shim.isWrapped(args[cbIdx]) || shim.isWrapped(original))
|
|
152
|
-
) {
|
|
153
|
-
shim.logger.trace(
|
|
154
|
-
{
|
|
155
|
-
hasSegment: !!shim.getSegment()
|
|
156
|
-
},
|
|
157
|
-
'Wrapping callback with segment'
|
|
158
|
-
)
|
|
159
|
-
let cb = args[cbIdx]
|
|
160
|
-
if (!shim[symbols.wrappedPoolConnection]) {
|
|
161
|
-
cb = shim.wrap(cb, wrapGetConnectionCallback)
|
|
162
|
-
}
|
|
163
|
-
args[cbIdx] = shim.bindSegment(cb)
|
|
164
|
-
}
|
|
165
|
-
return fn.apply(this, args)
|
|
166
|
-
}
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
return true
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function wrapGetConnectionCallback(shim, cb) {
|
|
173
|
-
return function wrappedGetConnectionCallback(err, conn) {
|
|
174
|
-
try {
|
|
175
|
-
shim.logger.debug('Wrapping PoolConnection#query')
|
|
176
|
-
if (!err && wrapQueryable(shim, conn, false)) {
|
|
177
|
-
// Leave getConnection wrapped in order to maintain TX state, but we can
|
|
178
|
-
// simplify the wrapping of its callback in future calls.
|
|
179
|
-
shim[symbols.wrappedPoolConnection] = true
|
|
180
|
-
}
|
|
181
|
-
} catch (_err) {
|
|
182
|
-
shim.logger.debug(
|
|
183
|
-
{ error: _err },
|
|
184
|
-
'Attempt to wrap PoolConnection#query resulted in thrown error'
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
return cb.apply(this, arguments)
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function wrapQueryable(shim, queryable, isPoolQuery) {
|
|
192
|
-
if (!queryable || !queryable.query || shim.isWrapped(queryable.query)) {
|
|
193
|
-
shim.logger.debug(
|
|
194
|
-
{
|
|
195
|
-
queryable: !!queryable,
|
|
196
|
-
query: !!(queryable && queryable.query),
|
|
197
|
-
isWrapped: !!(queryable && shim.isWrapped(queryable.query))
|
|
198
|
-
},
|
|
199
|
-
'Not wrapping queryable'
|
|
200
|
-
)
|
|
201
|
-
return false
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const proto = Object.getPrototypeOf(queryable)
|
|
205
|
-
|
|
206
|
-
let describe
|
|
207
|
-
if (isPoolQuery) {
|
|
208
|
-
describe = describePoolQuery
|
|
209
|
-
} else {
|
|
210
|
-
describe = describeQuery
|
|
211
|
-
proto[symbols.databaseName] = null
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
shim.recordQuery(proto, 'query', describe)
|
|
215
|
-
|
|
216
|
-
if (queryable.execute) {
|
|
217
|
-
shim.recordQuery(proto, 'execute', describe)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return true
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function extractQueryArgs(shim, args) {
|
|
224
|
-
let query = ''
|
|
225
|
-
let callback = null
|
|
226
|
-
|
|
227
|
-
// Figure out the query parameter.
|
|
228
|
-
if (shim.isString(args[0])) {
|
|
229
|
-
// query(sql [, values], callback)
|
|
230
|
-
query = args[0]
|
|
231
|
-
} else {
|
|
232
|
-
// query(opts [, values], callback)
|
|
233
|
-
query = args[0].sql
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Then determine the query values and callback parameters.
|
|
237
|
-
if (shim.isArray(args[1])) {
|
|
238
|
-
// query({opts|sql}, values, callback)
|
|
239
|
-
callback = 2
|
|
240
|
-
} else {
|
|
241
|
-
// query({opts|sql}, callback)
|
|
242
|
-
callback = 1
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return {
|
|
246
|
-
query,
|
|
247
|
-
callback
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function describeQuery(shim, queryFn, fnName, args) {
|
|
252
|
-
shim.logger.trace('Recording query')
|
|
253
|
-
const extractedArgs = extractQueryArgs(shim, args)
|
|
254
|
-
|
|
255
|
-
// Pull out instance attributes.
|
|
256
|
-
const parameters = getInstanceParameters(shim, this, extractedArgs.query)
|
|
257
|
-
|
|
258
|
-
shim.logger.trace(
|
|
259
|
-
{
|
|
260
|
-
query: !!extractedArgs.query,
|
|
261
|
-
callback: !!extractedArgs.callback,
|
|
262
|
-
parameters: !!parameters
|
|
263
|
-
},
|
|
264
|
-
'Query segment descriptor'
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
return new QuerySpec({
|
|
268
|
-
stream: true,
|
|
269
|
-
query: extractedArgs.query,
|
|
270
|
-
callback: extractedArgs.callback,
|
|
271
|
-
parameters,
|
|
272
|
-
record: true
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function describePoolQuery(shim, queryFn, fnName, args) {
|
|
277
|
-
shim.logger.trace('Recording pool query')
|
|
278
|
-
const extractedArgs = extractQueryArgs(shim, args)
|
|
279
|
-
return new QuerySpec({
|
|
280
|
-
internal: false,
|
|
281
|
-
stream: true,
|
|
282
|
-
query: null,
|
|
283
|
-
callback: extractedArgs.callback,
|
|
284
|
-
name: 'MySQL Pool#query',
|
|
285
|
-
record: false
|
|
286
|
-
})
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function getInstanceParameters(shim, queryable, query) {
|
|
290
|
-
const parameters = new DatastoreParameters()
|
|
291
|
-
let conf = queryable.config
|
|
292
|
-
conf = conf?.connectionConfig || conf
|
|
293
|
-
const databaseName = queryable[symbols.databaseName] || null
|
|
294
|
-
if (conf) {
|
|
295
|
-
parameters.database_name = databaseName || conf.database
|
|
296
|
-
|
|
297
|
-
if (properties.hasOwn(conf, 'socketPath') && conf.socketPath) {
|
|
298
|
-
// In the unix domain socket case we force the host to be localhost
|
|
299
|
-
parameters.host = 'localhost'
|
|
300
|
-
parameters.port_path_or_id = conf.socketPath
|
|
301
|
-
} else {
|
|
302
|
-
parameters.host = conf.host
|
|
303
|
-
parameters.port_path_or_id = conf.port
|
|
304
|
-
}
|
|
305
|
-
} else {
|
|
306
|
-
shim.logger.trace('No query config detected, not collecting db instance data')
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
storeDatabaseName(queryable, query)
|
|
310
|
-
return parameters
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function storeDatabaseName(queryable, query) {
|
|
314
|
-
if (queryable[symbols.storeDatabase]) {
|
|
315
|
-
const databaseName = dbutils.extractDatabaseChangeFromUse(query)
|
|
316
|
-
if (databaseName) {
|
|
317
|
-
queryable[symbols.databaseName] = databaseName
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
module.exports = {
|
|
323
|
-
callbackInitialize,
|
|
324
|
-
promiseInitialize,
|
|
325
|
-
wrapGetConnection,
|
|
326
|
-
wrapGetConnectionCallback,
|
|
327
|
-
wrapQueryable,
|
|
328
|
-
extractQueryArgs,
|
|
329
|
-
describeQuery,
|
|
330
|
-
describePoolQuery,
|
|
331
|
-
getInstanceParameters,
|
|
332
|
-
storeDatabaseName
|
|
333
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2022 New Relic Corporation. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict'
|
|
7
|
-
const instrumentation = require('./mysql')
|
|
8
|
-
const InstrumentationDescriptor = require('../../instrumentation-descriptor')
|
|
9
|
-
|
|
10
|
-
module.exports = [
|
|
11
|
-
{
|
|
12
|
-
type: InstrumentationDescriptor.TYPE_DATASTORE,
|
|
13
|
-
moduleName: 'mysql',
|
|
14
|
-
onRequire: instrumentation.callbackInitialize
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
type: InstrumentationDescriptor.TYPE_DATASTORE,
|
|
18
|
-
moduleName: 'mysql2',
|
|
19
|
-
onRequire: instrumentation.callbackInitialize
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
type: InstrumentationDescriptor.TYPE_DATASTORE,
|
|
23
|
-
moduleName: 'mysql2/promise',
|
|
24
|
-
onRequire: instrumentation.promiseInitialize
|
|
25
|
-
}
|
|
26
|
-
]
|
|
@@ -1,32 +0,0 @@
|
|
|
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 { setTokensInResponse } = require('../utils')
|
|
9
|
-
|
|
10
|
-
function setUsageTokens(response, context) {
|
|
11
|
-
// prompt and completion token counts must available in order to add all usage attributes to response
|
|
12
|
-
// if total tokens is not available, we can manually add it up (from input and output token count)
|
|
13
|
-
if (tokenUsageAttributesExist(response) === false) {
|
|
14
|
-
return
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const promptTokens = Number(response?.usageMetadata?.promptTokenCount)
|
|
18
|
-
const completionTokens = Number(response?.usageMetadata?.candidatesTokenCount)
|
|
19
|
-
const totalTokens = Number(response?.usageMetadata?.totalTokenCount)
|
|
20
|
-
|
|
21
|
-
setTokensInResponse(context, { promptTokens, completionTokens, totalTokens })
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function tokenUsageAttributesExist(response) {
|
|
25
|
-
const tokens = response?.usageMetadata?.promptTokenCount && response?.usageMetadata?.candidatesTokenCount
|
|
26
|
-
|
|
27
|
-
return tokens !== undefined
|
|
28
|
-
}
|
|
29
|
-
module.exports = {
|
|
30
|
-
tokenUsageAttributesExist,
|
|
31
|
-
setUsageTokens
|
|
32
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2024 New Relic Corporation. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict'
|
|
7
|
-
|
|
8
|
-
const { setTokensInResponse } = require('../utils')
|
|
9
|
-
|
|
10
|
-
function setUsageTokens(response, context) {
|
|
11
|
-
// input and output token counts must available in order to add all usage attributes to response
|
|
12
|
-
// if total tokens is not available, we can manually add it up (from input and output token count)
|
|
13
|
-
if (tokenUsageAttributesExist(response) === false) {
|
|
14
|
-
return
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const promptTokens = Number(response?.usage?.prompt_tokens || response?.usage?.input_tokens)
|
|
18
|
-
const completionTokens = Number(response?.usage?.completion_tokens || response?.usage?.output_tokens)
|
|
19
|
-
const totalTokens = Number(response?.usage?.total_tokens || response?.usage?.totalTokens)
|
|
20
|
-
|
|
21
|
-
setTokensInResponse(context, { promptTokens, completionTokens, totalTokens })
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function tokenUsageAttributesExist(response) {
|
|
25
|
-
const tokensA = response?.usage?.prompt_tokens && response?.usage?.completion_tokens
|
|
26
|
-
const tokensB = response?.usage?.input_tokens && response?.usage?.output_tokens
|
|
27
|
-
|
|
28
|
-
return tokensA !== undefined || tokensB !== undefined
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
module.exports = {
|
|
32
|
-
tokenUsageAttributesExist,
|
|
33
|
-
setUsageTokens
|
|
34
|
-
}
|
package/lib/llm-events/utils.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Determines if the provided token count is valid.
|
|
10
|
-
* A valid token count is greater than 0 and not null.
|
|
11
|
-
* @param {number} tokenCount The token count obtained from the token callback
|
|
12
|
-
* @returns {boolean} Whether the token count is valid
|
|
13
|
-
*/
|
|
14
|
-
function validCallbackTokenCount(tokenCount) {
|
|
15
|
-
return tokenCount !== null && tokenCount > 0
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Calculates the total token count from the prompt tokens and completion tokens
|
|
20
|
-
* set in the context.
|
|
21
|
-
* @param {LlmEvent} context The context object containing token counts
|
|
22
|
-
* @returns {number} The total token count
|
|
23
|
-
*/
|
|
24
|
-
function getTotalTokenCount(context) {
|
|
25
|
-
return Number(context['response.usage.prompt_tokens']) + Number(context['response.usage.completion_tokens'])
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Sets the provided tokens counts on the LLM event.
|
|
30
|
-
* @param {LlmChatCompletionMessage} context The context object to set token usage counts on.
|
|
31
|
-
* @param {object} tokens The object contains the token prompt, completion and total counts.
|
|
32
|
-
*/
|
|
33
|
-
function setTokensInResponse(context, tokens) {
|
|
34
|
-
context['response.usage.prompt_tokens'] = tokens.promptTokens
|
|
35
|
-
context['response.usage.completion_tokens'] = tokens.completionTokens
|
|
36
|
-
context['response.usage.total_tokens'] = tokens.totalTokens || getTotalTokenCount(context)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Calculates prompt and completion token counts using the provided callback and models.
|
|
41
|
-
* If both counts are valid, sets context.token_count to 0.
|
|
42
|
-
*
|
|
43
|
-
* @param {object} options - The params object.
|
|
44
|
-
* @param {LlmChatCompletionMessage} options.context - The context object to set token count on.
|
|
45
|
-
* @param {Function} options.tokenCB - The token counting callback function.
|
|
46
|
-
* @param {string} options.reqModel - The model used for the prompt.
|
|
47
|
-
* @param {string} options.resModel - The model used for the completion.
|
|
48
|
-
* @param {string} options.promptContent - The prompt content to count tokens for.
|
|
49
|
-
* @param {string} options.completionContent - The completion content to count tokens for.
|
|
50
|
-
* @returns {void}
|
|
51
|
-
*/
|
|
52
|
-
function setTokenFromCallback({ context, tokenCB, reqModel, resModel, promptContent, completionContent }) {
|
|
53
|
-
const promptToken = calculateCallbackTokens(tokenCB, reqModel, promptContent)
|
|
54
|
-
const completionToken = calculateCallbackTokens(tokenCB, resModel, completionContent)
|
|
55
|
-
|
|
56
|
-
const hasValidCallbackCounts =
|
|
57
|
-
validCallbackTokenCount(promptToken) && validCallbackTokenCount(completionToken)
|
|
58
|
-
|
|
59
|
-
if (hasValidCallbackCounts) {
|
|
60
|
-
context.token_count = 0
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Calculates prompt and completion token counts using the provided callback and models.
|
|
66
|
-
* If both counts are valid, sets token prompt, completion and total counts on the context.
|
|
67
|
-
*
|
|
68
|
-
* @param {object} options - The params object.
|
|
69
|
-
* @param {LlmEvent} options.context - The context object (llm summary or llm embedding) to set token count on.
|
|
70
|
-
* @param {Function} options.tokenCB - The token counting callback function.
|
|
71
|
-
* @param {string} options.reqModel - The model used for the prompt.
|
|
72
|
-
* @param {string} options.resModel - The model used for the completion.
|
|
73
|
-
* @param {string} options.promptContent - The prompt content to count tokens for.
|
|
74
|
-
* @param {string} options.completionContent - The completion content to count tokens for.
|
|
75
|
-
* @returns {void}
|
|
76
|
-
*/
|
|
77
|
-
function setTokenUsageFromCallback({ context, tokenCB, reqModel, resModel, promptContent, completionContent }) {
|
|
78
|
-
const promptTokens = calculateCallbackTokens(tokenCB, reqModel, promptContent)
|
|
79
|
-
const completionTokens = calculateCallbackTokens(tokenCB, resModel, completionContent)
|
|
80
|
-
|
|
81
|
-
const hasValidCallbackCounts =
|
|
82
|
-
validCallbackTokenCount(promptTokens) && validCallbackTokenCount(completionTokens)
|
|
83
|
-
|
|
84
|
-
if (hasValidCallbackCounts) {
|
|
85
|
-
setTokensInResponse(context, { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens })
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Calculate the token counts using the provided callback.
|
|
91
|
-
* @param {Function} tokenCB - The token count callback function.
|
|
92
|
-
* @param {string} model - The model.
|
|
93
|
-
* @param {string} content - The content to calculate tokens for, such as prompt or completion response.
|
|
94
|
-
* @returns {number|undefined} - The calculated token count or undefined if callback is not a function.
|
|
95
|
-
*/
|
|
96
|
-
function calculateCallbackTokens(tokenCB, model, content) {
|
|
97
|
-
if (typeof tokenCB === 'function') {
|
|
98
|
-
return tokenCB(model, content)
|
|
99
|
-
}
|
|
100
|
-
return undefined
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
module.exports = {
|
|
104
|
-
validCallbackTokenCount,
|
|
105
|
-
getTotalTokenCount,
|
|
106
|
-
setTokensInResponse,
|
|
107
|
-
setTokenFromCallback,
|
|
108
|
-
setTokenUsageFromCallback,
|
|
109
|
-
calculateCallbackTokens
|
|
110
|
-
}
|