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.
Files changed (49) hide show
  1. package/NEWS.md +33 -7
  2. package/README.md +6 -11
  3. package/lib/config/default.js +46 -4
  4. package/lib/config/index.js +110 -1
  5. package/lib/instrumentation/@google/genai.js +15 -24
  6. package/lib/instrumentation/aws-sdk/v3/bedrock.js +5 -0
  7. package/lib/instrumentations.js +0 -1
  8. package/lib/llm-events/aws-bedrock/bedrock-response.js +25 -1
  9. package/lib/llm-events/aws-bedrock/chat-completion-message.js +2 -10
  10. package/lib/llm-events/aws-bedrock/chat-completion-summary.js +11 -15
  11. package/lib/llm-events/aws-bedrock/converse-stream-handler.js +11 -4
  12. package/lib/llm-events/aws-bedrock/embedding.js +3 -20
  13. package/lib/llm-events/aws-bedrock/event.js +3 -20
  14. package/lib/llm-events/aws-bedrock/stream-handler.js +21 -28
  15. package/lib/llm-events/aws-bedrock/utils.js +1 -59
  16. package/lib/llm-events/event.js +108 -0
  17. package/lib/llm-events/google-genai/chat-completion-message.js +3 -10
  18. package/lib/llm-events/google-genai/chat-completion-summary.js +4 -5
  19. package/lib/llm-events/google-genai/embedding.js +0 -34
  20. package/lib/llm-events/google-genai/event.js +7 -0
  21. package/lib/llm-events/openai/chat-completion-message.js +3 -9
  22. package/lib/llm-events/openai/chat-completion-summary.js +4 -5
  23. package/lib/llm-events/openai/embedding.js +4 -15
  24. package/lib/llm-events/openai/event.js +7 -0
  25. package/lib/shim/datastore-shim.js +5 -7
  26. package/lib/subscriber-configs.js +2 -0
  27. package/lib/subscribers/base.js +1 -1
  28. package/lib/subscribers/message-consumer.js +9 -2
  29. package/lib/subscribers/mysql/config.js +73 -0
  30. package/lib/subscribers/mysql/connection-query.js +56 -0
  31. package/lib/subscribers/mysql/helper.js +102 -0
  32. package/lib/subscribers/mysql/pool-get-connection.js +20 -0
  33. package/lib/subscribers/mysql/pool-namespace-query.js +19 -0
  34. package/lib/subscribers/mysql/pool-query.js +41 -0
  35. package/lib/subscribers/mysql2/config.js +127 -0
  36. package/lib/subscribers/mysql2/connection-execute.js +18 -0
  37. package/lib/subscribers/mysql2/connection-query.js +17 -0
  38. package/lib/subscribers/mysql2/pool-get-connection.js +20 -0
  39. package/lib/subscribers/mysql2/pool-namespace-query.js +19 -0
  40. package/lib/subscribers/mysql2/pool-query.js +19 -0
  41. package/lib/subscribers/openai/utils.js +11 -2
  42. package/lib/subscribers/pg/query.js +1 -1
  43. package/package.json +1 -1
  44. package/lib/db/utils.js +0 -19
  45. package/lib/instrumentation/mysql/mysql.js +0 -333
  46. package/lib/instrumentation/mysql/nr-hooks.js +0 -26
  47. package/lib/llm-events/google-genai/utils.js +0 -32
  48. package/lib/llm-events/openai/utils.js +0 -34
  49. package/lib/llm-events/utils.js +0 -110
@@ -0,0 +1,73 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const connectionQuery = {
7
+ path: './mysql/connection-query.js',
8
+ instrumentations: [
9
+ {
10
+ channelName: 'nr_connectionQuery',
11
+ module: { name: 'mysql', versionRange: '>=2.16.0', filePath: 'lib/Connection.js' },
12
+ functionQuery: {
13
+ moduleName: 'Connection',
14
+ expressionName: 'query',
15
+ kind: 'Sync'
16
+ }
17
+ }
18
+ ]
19
+ }
20
+
21
+ const poolQuery = {
22
+ path: './mysql/pool-query.js',
23
+ instrumentations: [
24
+ {
25
+ channelName: 'nr_poolQuery',
26
+ module: { name: 'mysql', versionRange: '>=2.16.0', filePath: 'lib/Pool.js' },
27
+ functionQuery: {
28
+ moduleName: 'Pool',
29
+ expressionName: 'query',
30
+ kind: 'Sync'
31
+ }
32
+ }
33
+ ]
34
+ }
35
+
36
+ const poolNamespaceQuery = {
37
+ path: './mysql/pool-namespace-query.js',
38
+ instrumentations: [
39
+ {
40
+ channelName: 'nr_poolNamespaceQuery',
41
+ module: { name: 'mysql', versionRange: '>=2.16.0', filePath: 'lib/PoolNamespace.js' },
42
+ functionQuery: {
43
+ moduleName: 'PoolNamespace',
44
+ expressionName: 'query',
45
+ kind: 'Sync'
46
+ }
47
+ }
48
+ ]
49
+ }
50
+
51
+ const poolGetConnection = {
52
+ path: './mysql/pool-get-connection.js',
53
+ instrumentations: [
54
+ {
55
+ channelName: 'nr_poolGetConnection',
56
+ module: { name: 'mysql', versionRange: '>=2.16.0', filePath: 'lib/Pool.js' },
57
+ functionQuery: {
58
+ moduleName: 'Pool',
59
+ expressionName: 'getConnection',
60
+ kind: 'Sync'
61
+ }
62
+ }
63
+ ]
64
+ }
65
+
66
+ module.exports = {
67
+ mysql: [
68
+ connectionQuery,
69
+ poolQuery,
70
+ poolNamespaceQuery,
71
+ poolGetConnection,
72
+ ]
73
+ }
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const DbQuerySubscriber = require('../db-query')
7
+ const { MYSQL } = require('#agentlib/metrics/names.js')
8
+ const { extractQuery, getInstanceParameters } = require('./helper.js')
9
+ const symbols = require('../../symbols')
10
+ const { EventEmitter } = require('node:events')
11
+
12
+ /**
13
+ * Subscribes to `mysql`'s `Connection#query` events and creates the
14
+ * coordinating Datastore query segment.
15
+ *
16
+ * Also provides a base for other `Connection#query` subscribers.
17
+ */
18
+ class MySQLConnectionQuerySubscriber extends DbQuerySubscriber {
19
+ constructor({ agent, logger, channelName = 'nr_connectionQuery', packageName = 'mysql' }) {
20
+ super({ agent, logger, channelName, packageName, system: MYSQL.PREFIX })
21
+ this.events = ['asyncStart', 'asyncEnd', 'end']
22
+ this.operation = 'query'
23
+ this.callback = -1
24
+ this.propagateContext = true
25
+ }
26
+
27
+ handler(data, ctx) {
28
+ const Connection = data?.self
29
+ // Setting this symbol is necessary because we
30
+ // may need to track the databaseName across multiple
31
+ // consecutive queries; see `getInstanceParameters`.
32
+ Connection[symbols.storeDatabase] = true
33
+
34
+ // Set database attributes
35
+ this.queryString = extractQuery(data?.arguments)
36
+ this.parameters = getInstanceParameters(this.logger, Connection, this.queryString)
37
+ this.parameters.product = this.system
38
+
39
+ // Call DbQuerySubscriber.handler to make the segment
40
+ return super.handler(data, ctx)
41
+ }
42
+
43
+ end(data) {
44
+ const ctx = this.agent.tracer.getContext()
45
+ if (ctx?.transaction?.isActive() !== true) {
46
+ return
47
+ }
48
+
49
+ if (data?.result instanceof EventEmitter) {
50
+ const ctx = this.agent.tracer.getContext()
51
+ this.wrapEventEmitter({ args: data, index: 'result', ctx })
52
+ }
53
+ }
54
+ }
55
+
56
+ module.exports = MySQLConnectionQuerySubscriber
@@ -0,0 +1,102 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const properties = require('../../util/properties')
7
+ const symbols = require('../../symbols')
8
+
9
+ /**
10
+ * @typedef {object} DatastoreParameters
11
+ * @property {string} host
12
+ * The host of the database server being interacted with. If provided, along
13
+ * with `port_path_or_id`, then an instance metric will also be generated for
14
+ * this database.
15
+ * @property {number|string} port_path_or_id
16
+ * The port number or path to domain socket used to connect to the database
17
+ * server.
18
+ * @property {string} database_name
19
+ * The name of the database being queried or operated on.
20
+ * @property {string} collection
21
+ * The name of the collection or table being queried or operated on.
22
+ */
23
+
24
+ /**
25
+ * Extracts the query string from the function arguments.
26
+ * @param {object[]} args the original query arguments
27
+ * @returns {string} the extracted query string
28
+ */
29
+ function extractQuery(args) {
30
+ let query = ''
31
+
32
+ // Figure out the query parameter.
33
+ if (args[0] && typeof args[0] === 'string') {
34
+ // query(sql [, values], callback)
35
+ query = args[0]
36
+ } else {
37
+ // query(opts [, values], callback)
38
+ query = args[0].sql
39
+ }
40
+
41
+ return query
42
+ }
43
+
44
+ /**
45
+ *
46
+ * @param {object} logger an instance of the New Relic agent logger
47
+ * @param {object} queryable a MySQL object that has a `query` function e.g. `Connection` or `Pool`
48
+ * @param {string} query the query string
49
+ * @returns {DatastoreParameters} the relevant datastore parameters
50
+ */
51
+ function getInstanceParameters(logger, queryable, query) {
52
+ const parameters = {}
53
+ let conf = queryable.config
54
+ conf = conf?.connectionConfig || conf
55
+ const databaseName = queryable[symbols.databaseName] || null
56
+
57
+ // Look at config for parameters
58
+ if (conf) {
59
+ parameters.database_name = databaseName || conf.database
60
+
61
+ if (properties.hasOwn(conf, 'socketPath') && conf.socketPath) {
62
+ // In the unix domain socket case we force the host to be localhost
63
+ parameters.host = 'localhost'
64
+ parameters.port_path_or_id = conf.socketPath
65
+ } else {
66
+ parameters.host = conf.host
67
+ parameters.port_path_or_id = conf.port
68
+ }
69
+ } else {
70
+ logger.trace('No query config detected, not collecting db instance data')
71
+ }
72
+
73
+ storeDatabaseName(queryable, query)
74
+ return parameters
75
+ }
76
+
77
+ function extractDatabaseChangeFromUse(sql) {
78
+ // The character ranges for this were pulled from
79
+ // http://dev.mysql.com/doc/refman/5.7/en/identifiers.html
80
+
81
+ // The lint rule being suppressed here has been evaluated, and it has been
82
+ // determined that the regular expression is sufficient for our use case.
83
+ // eslint-disable-next-line sonarjs/slow-regex
84
+ const match = /^\s*use[^\w`]+([\w$\u0080-\uFFFF]+|`[^`]+`)[\s;]*$/i.exec(sql)
85
+ return (match && match[1]) || null
86
+ }
87
+
88
+ function storeDatabaseName(queryable, query) {
89
+ if (queryable[symbols.storeDatabase]) {
90
+ const databaseName = extractDatabaseChangeFromUse(query)
91
+ if (databaseName) {
92
+ queryable[symbols.databaseName] = databaseName
93
+ }
94
+ }
95
+ }
96
+
97
+ module.exports = {
98
+ extractQuery,
99
+ getInstanceParameters,
100
+ // exported for testing purposes
101
+ extractDatabaseChangeFromUse
102
+ }
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const PropagationSubscriber = require('../propagation')
7
+
8
+ /**
9
+ * This subscriber is only required to propagate the context within
10
+ * `Pool#getConnection`.
11
+ *
12
+ * Will be deleted when MySQL Pool#query segments are removed (@see https://github.com/newrelic/node-newrelic/issues/3482).
13
+ */
14
+ class MySQLPoolGetConnectionSubscriber extends PropagationSubscriber {
15
+ constructor({ agent, logger, packageName = 'mysql', channelName = 'nr_poolGetConnection' }) {
16
+ super({ agent, logger, packageName, channelName, callback: -1 })
17
+ }
18
+ }
19
+
20
+ module.exports = MySQLPoolGetConnectionSubscriber
@@ -0,0 +1,19 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MySQLPoolQuerySubscriber = require('./pool-query.js')
7
+
8
+ /**
9
+ * Subscribes to the events produced by `mysql`'s `PoolNamespace#query`.
10
+ *
11
+ * Will be deleted when MySQL Pool#query segments are removed (@see https://github.com/newrelic/node-newrelic/issues/3482).
12
+ */
13
+ class MySQLPoolNamespaceQuerySubscriber extends MySQLPoolQuerySubscriber {
14
+ constructor({ agent, logger, channelName = 'nr_poolNamespaceQuery', packageName = 'mysql' }) {
15
+ super({ agent, logger, channelName, packageName })
16
+ }
17
+ }
18
+
19
+ module.exports = MySQLPoolNamespaceQuerySubscriber
@@ -0,0 +1,41 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const Subscriber = require('../base')
7
+ const symbols = require('../../symbols')
8
+
9
+ /**
10
+ * Subscribes to the events produced by `mysql`'s `Pool#query`
11
+ * and creates a special segment named 'MySQL Pool#query'.
12
+ *
13
+ * Also provides a base for other `Pool#query` subscribers.
14
+ *
15
+ * Will be deleted when MySQL Pool#query segments are removed (@see https://github.com/newrelic/node-newrelic/issues/3482).
16
+ */
17
+ class MySQLPoolQuerySubscriber extends Subscriber {
18
+ constructor({ agent, logger, channelName = 'nr_poolQuery', packageName = 'mysql' }) {
19
+ super({ agent, logger, channelName, packageName })
20
+ this.events = ['asyncStart', 'asyncEnd']
21
+ this.callback = -1
22
+ this.propagateContext = true
23
+ }
24
+
25
+ handler(data, ctx) {
26
+ const Pool = data?.self
27
+ // Setting this symbol is necessary because we
28
+ // may need to track the databaseName across multiple
29
+ // consecutive queries; see `getInstanceParameters`.
30
+ Pool[symbols.storeDatabase] = true
31
+
32
+ // Create the segment, but don't supply a recorder
33
+ const name = 'MySQL Pool#query'
34
+ return this.createSegment({
35
+ name,
36
+ ctx
37
+ })
38
+ }
39
+ }
40
+
41
+ module.exports = MySQLPoolQuerySubscriber
@@ -0,0 +1,127 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ // MySQL2 subscriber configs
7
+ const connectionQuery2 = {
8
+ path: './mysql2/connection-query.js',
9
+ instrumentations: [
10
+ {
11
+ channelName: 'nr_connectionQuery',
12
+ module: { name: 'mysql2', versionRange: '>=2.0.0 <3.11.5', filePath: 'lib/connection.js' },
13
+ functionQuery: {
14
+ className: 'Connection',
15
+ methodName: 'query',
16
+ kind: 'Sync'
17
+ }
18
+ },
19
+ {
20
+ channelName: 'nr_connectionQuery',
21
+ module: { name: 'mysql2', versionRange: '>=3.11.5', filePath: 'lib/base/connection.js' },
22
+ functionQuery: {
23
+ className: 'BaseConnection',
24
+ methodName: 'query',
25
+ kind: 'Sync'
26
+ }
27
+ }
28
+ ]
29
+ }
30
+
31
+ const poolQuery2 = {
32
+ path: './mysql2/pool-query.js',
33
+ instrumentations: [
34
+ {
35
+ channelName: 'nr_poolQuery',
36
+ module: { name: 'mysql2', versionRange: '>2.0.0 <3.11.5', filePath: 'lib/pool.js' },
37
+ functionQuery: {
38
+ className: 'Pool',
39
+ methodName: 'query',
40
+ kind: 'Sync'
41
+ }
42
+ },
43
+ {
44
+ channelName: 'nr_poolQuery',
45
+ module: { name: 'mysql2', versionRange: '>=3.11.5', filePath: 'lib/base/pool.js' },
46
+ functionQuery: {
47
+ className: 'BasePool',
48
+ methodName: 'query',
49
+ kind: 'Sync'
50
+ }
51
+ }
52
+ ]
53
+ }
54
+
55
+ const poolNamespaceQuery2 = {
56
+ path: './mysql2/pool-namespace-query.js',
57
+ instrumentations: [
58
+ {
59
+ channelName: 'nr_poolNamespaceQuery',
60
+ // The `PoolNamespace` class did not get moved into lib/base in mysql2@3.11.5.
61
+ module: { name: 'mysql2', versionRange: '>=3.0.0', filePath: 'lib/pool_cluster.js' },
62
+ functionQuery: {
63
+ className: 'PoolNamespace',
64
+ methodName: 'query',
65
+ kind: 'Sync'
66
+ }
67
+ }
68
+ ]
69
+ }
70
+
71
+ const poolGetConnection = {
72
+ path: './mysql2/pool-get-connection.js',
73
+ instrumentations: [
74
+ {
75
+ channelName: 'nr_poolGetConnection',
76
+ module: { name: 'mysql2', versionRange: '>2.0.0 <3.11.5', filePath: 'lib/pool.js' },
77
+ functionQuery: {
78
+ className: 'Pool',
79
+ methodName: 'getConnection',
80
+ kind: 'Sync'
81
+ }
82
+ },
83
+ {
84
+ channelName: 'nr_poolGetConnection',
85
+ module: { name: 'mysql2', versionRange: '>=3.11.5', filePath: 'lib/base/pool.js' },
86
+ functionQuery: {
87
+ className: 'BasePool',
88
+ methodName: 'getConnection',
89
+ kind: 'Sync'
90
+ }
91
+ }
92
+ ]
93
+ }
94
+
95
+ const connectionExecute = {
96
+ path: './mysql2/connection-execute.js',
97
+ instrumentations: [
98
+ {
99
+ channelName: 'nr_connectionExecute',
100
+ module: { name: 'mysql2', versionRange: '>=2.0.0 <3.11.5', filePath: 'lib/connection.js' },
101
+ functionQuery: {
102
+ className: 'Connection',
103
+ methodName: 'execute',
104
+ kind: 'Sync'
105
+ }
106
+ },
107
+ {
108
+ channelName: 'nr_connectionExecute',
109
+ module: { name: 'mysql2', versionRange: '>=3.11.5', filePath: 'lib/base/connection.js' },
110
+ functionQuery: {
111
+ className: 'BaseConnection',
112
+ methodName: 'execute',
113
+ kind: 'Sync'
114
+ }
115
+ }
116
+ ]
117
+ }
118
+
119
+ module.exports = {
120
+ mysql2: [
121
+ connectionQuery2,
122
+ poolQuery2,
123
+ poolNamespaceQuery2,
124
+ poolGetConnection,
125
+ connectionExecute,
126
+ ]
127
+ }
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MySQL2ConnectionQuerySubscriber = require('../mysql/connection-query')
7
+
8
+ /**
9
+ * Subscribes to `mysql2`'s `Connection#execute` events.
10
+ */
11
+ class MySQL2ConnectionExecuteSubscriber extends MySQL2ConnectionQuerySubscriber {
12
+ constructor({ agent, logger }) {
13
+ super({ agent, logger, channelName: 'nr_connectionExecute', packageName: 'mysql2' })
14
+ this.operation = 'execute'
15
+ }
16
+ }
17
+
18
+ module.exports = MySQL2ConnectionExecuteSubscriber
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MySQLConnectionQuerySubscriber = require('../mysql/connection-query')
7
+
8
+ /**
9
+ * Subscribes to `mysql2`'s `Connection#query` events.
10
+ */
11
+ class MySQL2ConnectionQuerySubscriber extends MySQLConnectionQuerySubscriber {
12
+ constructor({ agent, logger }) {
13
+ super({ agent, logger, packageName: 'mysql2' })
14
+ }
15
+ }
16
+
17
+ module.exports = MySQL2ConnectionQuerySubscriber
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MySqlPoolGetConnectionSubscriber = require('../mysql/pool-get-connection')
7
+
8
+ /**
9
+ * This subscriber is only required to propagate the context within
10
+ * `Pool#getConnection`.
11
+ *
12
+ * Will be deleted when MySQL Pool#query segments are removed (@see https://github.com/newrelic/node-newrelic/issues/3482).
13
+ */
14
+ class MySQL2PoolGetConnectionSubscriber extends MySqlPoolGetConnectionSubscriber {
15
+ constructor({ agent, logger }) {
16
+ super({ agent, logger, packageName: 'mysql2' })
17
+ }
18
+ }
19
+
20
+ module.exports = MySQL2PoolGetConnectionSubscriber
@@ -0,0 +1,19 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MySQLPoolNamespaceQuerySubscriber = require('../mysql/pool-namespace-query.js')
7
+
8
+ /**
9
+ * Subscribes to the events produced by `mysql2`'s `PoolNamespace#query`.
10
+ *
11
+ * Will be deleted when MySQL Pool#query segments are removed (@see https://github.com/newrelic/node-newrelic/issues/3482).
12
+ */
13
+ class MySQL2PoolNamespaceQuerySubscriber extends MySQLPoolNamespaceQuerySubscriber {
14
+ constructor({ agent, logger }) {
15
+ super({ agent, logger, packageName: 'mysql2' })
16
+ }
17
+ }
18
+
19
+ module.exports = MySQL2PoolNamespaceQuerySubscriber
@@ -0,0 +1,19 @@
1
+ /*
2
+ * Copyright 2025 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ const MySQLPoolQuerySubscriber = require('../mysql/pool-query.js')
7
+
8
+ /**
9
+ * Subscribes to the events produced by `mysql2`'s `Pool#query`.
10
+ *
11
+ * Will be deleted when MySQL Pool#query segments are removed (@see https://github.com/newrelic/node-newrelic/issues/3482).
12
+ */
13
+ class MySQL2PoolQuerySubscriber extends MySQLPoolQuerySubscriber {
14
+ constructor({ agent, logger }) {
15
+ super({ agent, logger, packageName: 'mysql2' })
16
+ }
17
+ }
18
+
19
+ module.exports = MySQL2PoolQuerySubscriber
@@ -252,6 +252,7 @@ function instrumentStream({ agent, headers, logger, request, response, segment,
252
252
  response.iterator = async function * wrappedIterator() {
253
253
  let content = ''
254
254
  let role = ''
255
+ let finishReason = ''
255
256
  let chunk
256
257
  try {
257
258
  const iterator = orig.apply(this, arguments)
@@ -261,6 +262,10 @@ function instrumentStream({ agent, headers, logger, request, response, segment,
261
262
  role = chunk.choices[0].delta.role
262
263
  }
263
264
 
265
+ if (chunk.choices?.[0]?.finish_reason) {
266
+ finishReason = chunk.choices[0].finish_reason
267
+ }
268
+
264
269
  content += chunk.choices?.[0]?.delta?.content ?? ''
265
270
  yield chunk
266
271
  }
@@ -268,8 +273,12 @@ function instrumentStream({ agent, headers, logger, request, response, segment,
268
273
  err = streamErr
269
274
  throw err
270
275
  } finally {
271
- if (chunk?.choices && chunk?.choices?.length !== 0) {
272
- chunk.choices[0].message = { role, content }
276
+ // when `chunk.choices` is an array that means the completions API is being used
277
+ // we must re-assign the finish reason, and construct a message object with role and content
278
+ // This is because if `include_usage` is enabled, the last chunk only contains usage info and no message deltas
279
+ if (Array.isArray(chunk?.choices)) {
280
+ chunk.choices = [{ finish_reason: finishReason, message: { role, content } }]
281
+ // This means it is the responses API and the entire message is in the response object
273
282
  } else if (chunk?.response) {
274
283
  chunk = chunk.response
275
284
  }
@@ -57,7 +57,7 @@ class PgQuerySubscriber extends DbQuerySubscriber {
57
57
  // then wrap the arguments and bind the new context to the event emitter
58
58
  const newCtx = super.handler(data, ctx)
59
59
  if (data?.arguments[0] instanceof EventEmitter) {
60
- this.wrapEventEmitter({ args: data.arguments, index: 0, name: 'emit', ctx: newCtx })
60
+ this.wrapEventEmitter({ args: data.arguments, index: 0, ctx: newCtx })
61
61
  }
62
62
  return newCtx
63
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "13.6.2",
3
+ "version": "13.6.4",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [
package/lib/db/utils.js DELETED
@@ -1,19 +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
- module.exports.extractDatabaseChangeFromUse = extractDatabaseChangeFromUse
9
-
10
- function extractDatabaseChangeFromUse(sql) {
11
- // The character ranges for this were pulled from
12
- // http://dev.mysql.com/doc/refman/5.7/en/identifiers.html
13
-
14
- // The lint rule being suppressed here has been evaluated, and it has been
15
- // determined that the regular expression is sufficient for our use case.
16
- // eslint-disable-next-line sonarjs/slow-regex
17
- const match = /^\s*use[^\w`]+([\w$\u0080-\uFFFF]+|`[^`]+`)[\s;]*$/i.exec(sql)
18
- return (match && match[1]) || null
19
- }