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
|
@@ -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
|
-
|
|
272
|
-
|
|
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,
|
|
60
|
+
this.wrapEventEmitter({ args: data.arguments, index: 0, ctx: newCtx })
|
|
61
61
|
}
|
|
62
62
|
return newCtx
|
|
63
63
|
}
|
package/package.json
CHANGED
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
|
-
}
|