newrelic 11.23.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 CHANGED
@@ -1,3 +1,13 @@
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
+
1
11
  ### v11.23.0 (2024-07-10)
2
12
 
3
13
  #### Features
@@ -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 CLIENT_COMMANDS = ['select', 'quit', 'SELECT', 'QUIT']
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 COMMANDS = Object.keys(shim.require('dist/lib/client/commands.js').default)
18
- const CMDS_TO_INSTRUMENT = [...COMMANDS, ...CLIENT_COMMANDS]
19
- shim.wrap(redis, 'createClient', function wrapCreateClient(shim, original) {
20
- return function wrappedCreateClient() {
21
- const client = original.apply(this, arguments)
22
- client[opts] = getRedisParams(client.options)
23
- CMDS_TO_INSTRUMENT.forEach(instrumentClientCommand.bind(null, shim, client))
24
- if (client.options.legacyMode) {
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 on the client by calling `shim.recordOperation`
44
+ * Instruments a given command when added to the command queue by calling `shim.recordOperation`
35
45
  *
36
- * @param {Shim} shim shim instance
37
- * @param {object} client redis client instance
38
- * @param {string} cmd command to instrument
46
+ * @param {object} params
47
+ * @param {Shim} params.shim shim instance
48
+ * @param {object} params.commandsQueue instance
39
49
  */
40
- function instrumentClientCommand(shim, client, cmd) {
50
+ function instrumentAddCommand({ shim, commandsQueue }) {
41
51
  const { agent } = shim
52
+ const clientOpts = shim[redisClientOpts]
42
53
 
43
- shim.recordOperation(client, cmd, function wrapCommand(_shim, _fn, _fnName, args) {
44
- const [key, value] = args
45
- const parameters = Object.assign({}, client[opts])
46
- // If selecting a database, subsequent commands
47
- // will be using said database, update the clientOptions
48
- // but not the current parameters(feature parity with v3)
49
- if (cmd.toLowerCase() === 'select') {
50
- client[opts].database_name = key
51
- }
52
- if (agent.config.attributes.enabled) {
53
- if (key) {
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 (value) {
57
- parameters.value = JSON.stringify(value)
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
- return new OperationSpec({
62
- name: (cmd && cmd.toLowerCase()) || 'other',
63
- parameters,
64
- promise: true
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',
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'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "11.23.0",
3
+ "version": "11.23.1",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [