newrelic 11.23.2 → 12.0.0
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 +39 -0
- package/README.md +31 -0
- package/THIRD_PARTY_NOTICES.md +262 -31
- package/index.js +1 -10
- package/lib/context-manager/create-context-manager.js +0 -11
- package/lib/feature_flags.js +1 -2
- package/lib/instrumentation/amqplib/amqplib.js +4 -243
- package/lib/instrumentation/amqplib/channel-model.js +129 -0
- package/lib/instrumentation/amqplib/channel.js +70 -0
- package/lib/instrumentation/amqplib/utils.js +141 -0
- package/lib/instrumentation/core/globals.js +0 -5
- package/lib/instrumentation/core/timers.js +1 -72
- package/lib/instrumentation/kafkajs/consumer.js +64 -48
- package/lib/instrumentation/kafkajs/index.js +13 -13
- package/lib/instrumentation/kafkajs/producer.js +68 -52
- package/lib/instrumentation/kafkajs/record-linking-metrics.js +17 -0
- package/lib/instrumentation/kafkajs/record-method-metric.js +21 -0
- package/lib/instrumentation/mongodb.js +9 -10
- package/lib/instrumentation/nextjs/next-server.js +178 -0
- package/lib/instrumentation/nextjs/nr-hooks.js +22 -0
- package/lib/instrumentation/nextjs/utils.js +71 -0
- package/lib/instrumentation/redis.js +13 -59
- package/lib/instrumentations.js +1 -1
- package/lib/metrics/names.js +1 -2
- package/lib/shim/message-shim/consume.js +9 -4
- package/lib/shim/message-shim/index.js +7 -14
- package/lib/shim/message-shim/subscribe-consume.js +25 -6
- package/lib/shim/specs/params/queue-message.js +2 -0
- package/lib/spans/span-event.js +17 -11
- package/lib/spans/streaming-span-event.js +15 -13
- package/lib/symbols.js +1 -0
- package/load-externals.js +15 -0
- package/package.json +10 -10
- package/lib/context-manager/legacy-context-manager.js +0 -66
- package/lib/instrumentation/core/async-hooks.js +0 -132
- package/lib/instrumentation/director.js +0 -64
- package/lib/instrumentation/mongodb/v2-mongo.js +0 -118
- package/lib/instrumentation/mongodb/v3-mongo.js +0 -85
|
@@ -6,38 +6,17 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
|
-
MessageSpec,
|
|
10
|
-
MessageSubscribeSpec,
|
|
11
9
|
OperationSpec,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
params: { QueueMessageParameters, DatastoreParameters }
|
|
10
|
+
params: { DatastoreParameters }
|
|
15
11
|
} = require('../../shim/specs')
|
|
16
12
|
const url = require('url')
|
|
13
|
+
const wrapModel = require('./channel-model')
|
|
14
|
+
const { setCallback } = require('./utils')
|
|
15
|
+
const wrapChannel = require('./channel')
|
|
17
16
|
|
|
18
17
|
module.exports.instrumentPromiseAPI = instrumentChannelAPI
|
|
19
18
|
module.exports.instrumentCallbackAPI = instrumentCallbackAPI
|
|
20
19
|
|
|
21
|
-
const CHANNEL_METHODS = [
|
|
22
|
-
'close',
|
|
23
|
-
'open',
|
|
24
|
-
'assertQueue',
|
|
25
|
-
'checkQueue',
|
|
26
|
-
'deleteQueue',
|
|
27
|
-
'bindQueue',
|
|
28
|
-
'unbindQueue',
|
|
29
|
-
'assertExchange',
|
|
30
|
-
'checkExchange',
|
|
31
|
-
'deleteExchange',
|
|
32
|
-
'bindExchange',
|
|
33
|
-
'unbindExchange',
|
|
34
|
-
'cancel',
|
|
35
|
-
'prefetch',
|
|
36
|
-
'recover'
|
|
37
|
-
]
|
|
38
|
-
|
|
39
|
-
const TEMP_RE = /^amq\./
|
|
40
|
-
|
|
41
20
|
/**
|
|
42
21
|
* Register all the necessary instrumentation when using
|
|
43
22
|
* promise based methods
|
|
@@ -91,18 +70,6 @@ function instrumentAMQP(shim, amqp, promiseMode) {
|
|
|
91
70
|
wrapChannel(shim)
|
|
92
71
|
}
|
|
93
72
|
|
|
94
|
-
/**
|
|
95
|
-
* Helper to set the appropriate value of the callback property
|
|
96
|
-
* in the spec. If it's a promise set to null otherwise set it to `shim.LAST`
|
|
97
|
-
*
|
|
98
|
-
* @param {Shim} shim instance of shim
|
|
99
|
-
* @param {boolean} promiseMode is this promise based?
|
|
100
|
-
* @returns {string|null} appropriate value
|
|
101
|
-
*/
|
|
102
|
-
function setCallback(shim, promiseMode) {
|
|
103
|
-
return promiseMode ? null : shim.LAST
|
|
104
|
-
}
|
|
105
|
-
|
|
106
73
|
/**
|
|
107
74
|
*
|
|
108
75
|
* Instruments the connect method
|
|
@@ -134,209 +101,3 @@ function wrapConnect(shim, amqp, promiseMode) {
|
|
|
134
101
|
})
|
|
135
102
|
})
|
|
136
103
|
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
*
|
|
140
|
-
* Instruments the sendOrEnqueue and sendMessage methods of the ampqlib channel.
|
|
141
|
-
*
|
|
142
|
-
* @param {Shim} shim instance of shim
|
|
143
|
-
*/
|
|
144
|
-
function wrapChannel(shim) {
|
|
145
|
-
const libChannel = shim.require('./lib/channel')
|
|
146
|
-
if (!libChannel?.Channel?.prototype) {
|
|
147
|
-
shim.logger.debug('Could not get Channel class to instrument.')
|
|
148
|
-
return
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const proto = libChannel.Channel.prototype
|
|
152
|
-
if (shim.isWrapped(proto.sendMessage)) {
|
|
153
|
-
shim.logger.trace('Channel already instrumented.')
|
|
154
|
-
return
|
|
155
|
-
}
|
|
156
|
-
shim.logger.trace('Instrumenting basic Channel class.')
|
|
157
|
-
|
|
158
|
-
shim.wrap(proto, 'sendOrEnqueue', function wrapSendOrEnqueue(shim, fn) {
|
|
159
|
-
if (!shim.isFunction(fn)) {
|
|
160
|
-
return fn
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return function wrappedSendOrEnqueue() {
|
|
164
|
-
const segment = shim.getSegment()
|
|
165
|
-
const cb = arguments[arguments.length - 1]
|
|
166
|
-
if (!shim.isFunction(cb) || !segment) {
|
|
167
|
-
shim.logger.debug({ cb: !!cb, segment: !!segment }, 'Not binding sendOrEnqueue callback')
|
|
168
|
-
return fn.apply(this, arguments)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
shim.logger.trace('Binding sendOrEnqueue callback to %s', segment.name)
|
|
172
|
-
const args = shim.argsToArray.apply(shim, arguments)
|
|
173
|
-
args[args.length - 1] = shim.bindSegment(cb, segment)
|
|
174
|
-
return fn.apply(this, args)
|
|
175
|
-
}
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
shim.recordProduce(proto, 'sendMessage', function recordSendMessage(shim, fn, n, args) {
|
|
179
|
-
const fields = args[0]
|
|
180
|
-
if (!fields) {
|
|
181
|
-
return null
|
|
182
|
-
}
|
|
183
|
-
const isDefault = fields.exchange === ''
|
|
184
|
-
let exchange = 'Default'
|
|
185
|
-
if (!isDefault) {
|
|
186
|
-
exchange = TEMP_RE.test(fields.exchange) ? null : fields.exchange
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return new MessageSpec({
|
|
190
|
-
destinationName: exchange,
|
|
191
|
-
destinationType: shim.EXCHANGE,
|
|
192
|
-
routingKey: fields.routingKey,
|
|
193
|
-
headers: fields.headers,
|
|
194
|
-
parameters: getParameters(Object.create(null), fields)
|
|
195
|
-
})
|
|
196
|
-
})
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Sets the relevant message parameters
|
|
201
|
-
*
|
|
202
|
-
* @param {object} parameters object used to store the message parameters
|
|
203
|
-
* @param {object} fields fields from the sendMessage method
|
|
204
|
-
* @returns {QueueMessageParameters} parameters updated parameters
|
|
205
|
-
*/
|
|
206
|
-
function getParameters(parameters, fields) {
|
|
207
|
-
if (fields.routingKey) {
|
|
208
|
-
parameters.routing_key = fields.routingKey
|
|
209
|
-
}
|
|
210
|
-
if (fields.correlationId) {
|
|
211
|
-
parameters.correlation_id = fields.correlationId
|
|
212
|
-
}
|
|
213
|
-
if (fields.replyTo) {
|
|
214
|
-
parameters.reply_to = fields.replyTo
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return new QueueMessageParameters(parameters)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Sets the QueueMessageParameters from the amqp message
|
|
222
|
-
*
|
|
223
|
-
* @param {object} message queue message
|
|
224
|
-
* @returns {QueueMessageParameters} parameters from message
|
|
225
|
-
*/
|
|
226
|
-
function getParametersFromMessage(message) {
|
|
227
|
-
const parameters = Object.create(null)
|
|
228
|
-
getParameters(parameters, message.fields)
|
|
229
|
-
getParameters(parameters, message.properties)
|
|
230
|
-
return parameters
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
*
|
|
235
|
-
* Instruments the relevant channel callback_model or channel_model.
|
|
236
|
-
*
|
|
237
|
-
* @param {Shim} shim instance of shim
|
|
238
|
-
* @param {object} Model either channel or callback model
|
|
239
|
-
* @param {boolean} promiseMode is this promise based?
|
|
240
|
-
*/
|
|
241
|
-
function wrapModel(shim, Model, promiseMode) {
|
|
242
|
-
if (!Model.Channel?.prototype) {
|
|
243
|
-
shim.logger.debug(
|
|
244
|
-
`Could not get ${promiseMode ? 'promise' : 'callback'} model Channel to instrument.`
|
|
245
|
-
)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const proto = Model.Channel.prototype
|
|
249
|
-
if (shim.isWrapped(proto.consume)) {
|
|
250
|
-
shim.logger.trace(`${promiseMode ? 'promise' : 'callback'} model already instrumented.`)
|
|
251
|
-
return
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
shim.record(proto, CHANNEL_METHODS, function recordChannelMethod(shim, fn, name) {
|
|
255
|
-
return new RecorderSpec({
|
|
256
|
-
name: 'Channel#' + name,
|
|
257
|
-
callback: setCallback(shim, promiseMode),
|
|
258
|
-
promise: promiseMode
|
|
259
|
-
})
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
shim.recordConsume(
|
|
263
|
-
proto,
|
|
264
|
-
'get',
|
|
265
|
-
new MessageSpec({
|
|
266
|
-
destinationName: shim.FIRST,
|
|
267
|
-
callback: setCallback(shim, promiseMode),
|
|
268
|
-
promise: promiseMode,
|
|
269
|
-
after: function handleConsumedMessage({ shim, result, args, segment }) {
|
|
270
|
-
if (!shim.agent.config.message_tracer.segment_parameters.enabled) {
|
|
271
|
-
shim.logger.trace('Not capturing segment parameters')
|
|
272
|
-
return
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// the message is the param when using the promised based model
|
|
276
|
-
const message = promiseMode ? result : args?.[1]
|
|
277
|
-
if (!message) {
|
|
278
|
-
shim.logger.trace('No results from consume.')
|
|
279
|
-
return null
|
|
280
|
-
}
|
|
281
|
-
const parameters = getParametersFromMessage(message)
|
|
282
|
-
shim.copySegmentParameters(segment, parameters)
|
|
283
|
-
}
|
|
284
|
-
})
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
shim.recordPurgeQueue(proto, 'purgeQueue', function recordPurge(shim, fn, name, args) {
|
|
288
|
-
let queue = args[0]
|
|
289
|
-
if (TEMP_RE.test(queue)) {
|
|
290
|
-
queue = null
|
|
291
|
-
}
|
|
292
|
-
return new MessageSpec({
|
|
293
|
-
queue,
|
|
294
|
-
promise: promiseMode,
|
|
295
|
-
callback: setCallback(shim, promiseMode)
|
|
296
|
-
})
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
shim.recordSubscribedConsume(
|
|
300
|
-
proto,
|
|
301
|
-
'consume',
|
|
302
|
-
new MessageSubscribeSpec({
|
|
303
|
-
name: 'amqplib.Channel#consume',
|
|
304
|
-
queue: shim.FIRST,
|
|
305
|
-
consumer: shim.SECOND,
|
|
306
|
-
promise: promiseMode,
|
|
307
|
-
callback: promiseMode ? null : shim.FOURTH,
|
|
308
|
-
messageHandler: describeMessage
|
|
309
|
-
})
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Extracts the appropriate messageHandler parameters for the consume method.
|
|
315
|
-
*
|
|
316
|
-
* @param {Shim} shim instance of shim
|
|
317
|
-
* @param {Array} args arguments passed to the consume method
|
|
318
|
-
* @returns {object} message params
|
|
319
|
-
*/
|
|
320
|
-
function describeMessage(shim, args) {
|
|
321
|
-
const [message] = args
|
|
322
|
-
|
|
323
|
-
if (!message?.properties) {
|
|
324
|
-
shim.logger.debug({ message: message }, 'Failed to find message in consume arguments.')
|
|
325
|
-
return null
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const parameters = getParametersFromMessage(message)
|
|
329
|
-
let exchangeName = message?.fields?.exchange || 'Default'
|
|
330
|
-
|
|
331
|
-
if (TEMP_RE.test(exchangeName)) {
|
|
332
|
-
exchangeName = null
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return new MessageSpec({
|
|
336
|
-
destinationName: exchangeName,
|
|
337
|
-
destinationType: shim.EXCHANGE,
|
|
338
|
-
routingKey: message?.fields?.routingKey,
|
|
339
|
-
headers: message.properties.headers,
|
|
340
|
-
parameters
|
|
341
|
-
})
|
|
342
|
-
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const { MessageSpec, MessageSubscribeSpec, RecorderSpec } = require('../../shim/specs')
|
|
8
|
+
const CHANNEL_METHODS = [
|
|
9
|
+
'close',
|
|
10
|
+
'open',
|
|
11
|
+
'assertQueue',
|
|
12
|
+
'checkQueue',
|
|
13
|
+
'deleteQueue',
|
|
14
|
+
'bindQueue',
|
|
15
|
+
'unbindQueue',
|
|
16
|
+
'assertExchange',
|
|
17
|
+
'checkExchange',
|
|
18
|
+
'deleteExchange',
|
|
19
|
+
'bindExchange',
|
|
20
|
+
'unbindExchange',
|
|
21
|
+
'cancel',
|
|
22
|
+
'prefetch',
|
|
23
|
+
'recover'
|
|
24
|
+
]
|
|
25
|
+
const {
|
|
26
|
+
describeMessage,
|
|
27
|
+
setCallback,
|
|
28
|
+
parseConnect,
|
|
29
|
+
getParametersFromMessage,
|
|
30
|
+
TEMP_RE
|
|
31
|
+
} = require('./utils')
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* Instruments the relevant channel callback_model or channel_model.
|
|
36
|
+
*
|
|
37
|
+
* @param {Shim} shim instance of shim
|
|
38
|
+
* @param {object} Model either channel or callback model
|
|
39
|
+
* @param {boolean} promiseMode is this promise based?
|
|
40
|
+
*/
|
|
41
|
+
module.exports = function wrapModel(shim, Model, promiseMode) {
|
|
42
|
+
if (!Model.Channel?.prototype) {
|
|
43
|
+
shim.logger.debug(
|
|
44
|
+
`Could not get ${promiseMode ? 'promise' : 'callback'} model Channel to instrument.`
|
|
45
|
+
)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const proto = Model.Channel.prototype
|
|
50
|
+
if (shim.isWrapped(proto.consume)) {
|
|
51
|
+
shim.logger.trace(`${promiseMode ? 'promise' : 'callback'} model already instrumented.`)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
recordChannelMethods({ shim, proto, promiseMode })
|
|
56
|
+
recordPurge({ shim, proto, promiseMode })
|
|
57
|
+
recordGet({ shim, proto, promiseMode })
|
|
58
|
+
recordConsume({ shim, proto, promiseMode })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Record spans for common methods on channel
|
|
63
|
+
*
|
|
64
|
+
* @param {Channel} proto prototype of Model.Channel
|
|
65
|
+
*/
|
|
66
|
+
function recordChannelMethods({ shim, proto, promiseMode }) {
|
|
67
|
+
shim.record(proto, CHANNEL_METHODS, function recordChannelMethod(shim, fn, name) {
|
|
68
|
+
return new RecorderSpec({
|
|
69
|
+
name: 'Channel#' + name,
|
|
70
|
+
callback: setCallback(shim, promiseMode),
|
|
71
|
+
promise: promiseMode
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function recordPurge({ shim, proto, promiseMode }) {
|
|
77
|
+
shim.recordPurgeQueue(proto, 'purgeQueue', function purge(shim, fn, name, args) {
|
|
78
|
+
let queue = args[0]
|
|
79
|
+
if (TEMP_RE.test(queue)) {
|
|
80
|
+
queue = null
|
|
81
|
+
}
|
|
82
|
+
return new MessageSpec({
|
|
83
|
+
queue,
|
|
84
|
+
promise: promiseMode,
|
|
85
|
+
callback: setCallback(shim, promiseMode)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function recordGet({ shim, proto, promiseMode }) {
|
|
91
|
+
shim.recordConsume(proto, 'get', function wrapGet() {
|
|
92
|
+
const { host, port } = parseConnect(this?.connection?.stream)
|
|
93
|
+
return new MessageSpec({
|
|
94
|
+
destinationName: shim.FIRST,
|
|
95
|
+
callback: setCallback(shim, promiseMode),
|
|
96
|
+
promise: promiseMode,
|
|
97
|
+
after: function handleConsumedMessage({ shim, result, args, segment }) {
|
|
98
|
+
if (!shim.agent.config.message_tracer.segment_parameters.enabled) {
|
|
99
|
+
shim.logger.trace('Not capturing segment parameters')
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// the message is the param when using the promised based model
|
|
104
|
+
const message = promiseMode ? result : args?.[1]
|
|
105
|
+
if (!message) {
|
|
106
|
+
shim.logger.trace('No results from consume.')
|
|
107
|
+
return null
|
|
108
|
+
}
|
|
109
|
+
const parameters = getParametersFromMessage({ message, host, port })
|
|
110
|
+
shim.copySegmentParameters(segment, parameters)
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function recordConsume({ shim, proto, promiseMode }) {
|
|
117
|
+
shim.recordSubscribedConsume(proto, 'consume', function consume() {
|
|
118
|
+
const { host, port } = parseConnect(this?.connection?.stream)
|
|
119
|
+
return new MessageSubscribeSpec({
|
|
120
|
+
name: 'amqplib.Channel#consume',
|
|
121
|
+
queue: shim.FIRST,
|
|
122
|
+
consumer: shim.SECOND,
|
|
123
|
+
promise: promiseMode,
|
|
124
|
+
parameters: { host, port },
|
|
125
|
+
callback: promiseMode ? null : shim.FOURTH,
|
|
126
|
+
messageHandler: describeMessage({ host, port })
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const { MessageSpec } = require('../../shim/specs')
|
|
8
|
+
const { parseConnect, getParameters, TEMP_RE } = require('./utils')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* Instruments the sendOrEnqueue and sendMessage methods of the ampqlib channel.
|
|
13
|
+
*
|
|
14
|
+
* @param {Shim} shim instance of shim
|
|
15
|
+
*/
|
|
16
|
+
module.exports = function wrapChannel(shim) {
|
|
17
|
+
const libChannel = shim.require('./lib/channel')
|
|
18
|
+
if (!libChannel?.Channel?.prototype) {
|
|
19
|
+
shim.logger.debug('Could not get Channel class to instrument.')
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const proto = libChannel.Channel.prototype
|
|
24
|
+
if (shim.isWrapped(proto.sendMessage)) {
|
|
25
|
+
shim.logger.trace('Channel already instrumented.')
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
shim.logger.trace('Instrumenting basic Channel class.')
|
|
29
|
+
|
|
30
|
+
shim.wrap(proto, 'sendOrEnqueue', function wrapSendOrEnqueue(shim, fn) {
|
|
31
|
+
if (!shim.isFunction(fn)) {
|
|
32
|
+
return fn
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return function wrappedSendOrEnqueue() {
|
|
36
|
+
const segment = shim.getSegment()
|
|
37
|
+
const cb = arguments[arguments.length - 1]
|
|
38
|
+
if (!shim.isFunction(cb) || !segment) {
|
|
39
|
+
shim.logger.debug({ cb: !!cb, segment: !!segment }, 'Not binding sendOrEnqueue callback')
|
|
40
|
+
return fn.apply(this, arguments)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
shim.logger.trace('Binding sendOrEnqueue callback to %s', segment.name)
|
|
44
|
+
const args = shim.argsToArray.apply(shim, arguments)
|
|
45
|
+
args[args.length - 1] = shim.bindSegment(cb, segment)
|
|
46
|
+
return fn.apply(this, args)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
shim.recordProduce(proto, 'sendMessage', function recordSendMessage(shim, fn, n, args) {
|
|
51
|
+
const fields = args[0]
|
|
52
|
+
if (!fields) {
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
const isDefault = fields.exchange === ''
|
|
56
|
+
let exchange = 'Default'
|
|
57
|
+
if (!isDefault) {
|
|
58
|
+
exchange = TEMP_RE.test(fields.exchange) ? null : fields.exchange
|
|
59
|
+
}
|
|
60
|
+
const { host, port } = parseConnect(this?.connection?.stream)
|
|
61
|
+
|
|
62
|
+
return new MessageSpec({
|
|
63
|
+
destinationName: exchange,
|
|
64
|
+
destinationType: shim.EXCHANGE,
|
|
65
|
+
routingKey: fields.routingKey,
|
|
66
|
+
headers: fields.headers,
|
|
67
|
+
parameters: getParameters({ parameters: Object.create(null), fields, host, port })
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const {
|
|
8
|
+
MessageSpec,
|
|
9
|
+
params: { QueueMessageParameters }
|
|
10
|
+
} = require('../../shim/specs')
|
|
11
|
+
const { amqpConnection } = require('../../symbols')
|
|
12
|
+
const TEMP_RE = /^amq\./
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Wrapper around message handler to pass host/port
|
|
16
|
+
*
|
|
17
|
+
* @param {object} params to function
|
|
18
|
+
* @param {string} params.host hostname
|
|
19
|
+
* @param {number} params.port port
|
|
20
|
+
* @returns {function} message handler
|
|
21
|
+
*/
|
|
22
|
+
function describeMessage({ host, port }) {
|
|
23
|
+
/**
|
|
24
|
+
* Extracts the appropriate messageHandler parameters for the consume method.
|
|
25
|
+
*
|
|
26
|
+
* @param {Shim} shim instance of shim
|
|
27
|
+
* @param {Array} args arguments passed to the consume method
|
|
28
|
+
* @returns {object} message params
|
|
29
|
+
*/
|
|
30
|
+
return function messageHandler(shim, args) {
|
|
31
|
+
const [message] = args
|
|
32
|
+
|
|
33
|
+
if (!message?.properties) {
|
|
34
|
+
shim.logger.debug({ message: message }, 'Failed to find message in consume arguments.')
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const parameters = getParametersFromMessage({ message, host, port })
|
|
39
|
+
let exchangeName = message?.fields?.exchange || 'Default'
|
|
40
|
+
|
|
41
|
+
if (TEMP_RE.test(exchangeName)) {
|
|
42
|
+
exchangeName = null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return new MessageSpec({
|
|
46
|
+
destinationName: exchangeName,
|
|
47
|
+
destinationType: shim.EXCHANGE,
|
|
48
|
+
routingKey: message?.fields?.routingKey,
|
|
49
|
+
headers: message.properties.headers,
|
|
50
|
+
parameters
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Sets the relevant message parameters
|
|
57
|
+
*
|
|
58
|
+
* @param {object} params to function
|
|
59
|
+
* @param {object} params.parameters object used to store the message parameters
|
|
60
|
+
* @param {object} params.fields fields from the sendMessage method
|
|
61
|
+
* @param {string} params.host hostname
|
|
62
|
+
* @param {number} params.port port
|
|
63
|
+
* @returns {QueueMessageParameters} parameters updated parameters
|
|
64
|
+
*/
|
|
65
|
+
function getParameters({ parameters, fields, host, port }) {
|
|
66
|
+
if (fields.routingKey) {
|
|
67
|
+
parameters.routing_key = fields.routingKey
|
|
68
|
+
}
|
|
69
|
+
if (fields.correlationId) {
|
|
70
|
+
parameters.correlation_id = fields.correlationId
|
|
71
|
+
}
|
|
72
|
+
if (fields.replyTo) {
|
|
73
|
+
parameters.reply_to = fields.replyTo
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (host) {
|
|
77
|
+
parameters.host = host
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (port) {
|
|
81
|
+
parameters.port = port
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return new QueueMessageParameters(parameters)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Sets the QueueMessageParameters from the amqp message
|
|
89
|
+
*
|
|
90
|
+
* @param {object} params to function
|
|
91
|
+
* @param {object} params.message queue message
|
|
92
|
+
* @param {string} params.host host
|
|
93
|
+
* @param {number} params.port port
|
|
94
|
+
* @returns {QueueMessageParameters} parameters from message
|
|
95
|
+
*/
|
|
96
|
+
function getParametersFromMessage({ message, host, port }) {
|
|
97
|
+
const parameters = Object.create(null)
|
|
98
|
+
getParameters({ parameters, fields: message.fields, host, port })
|
|
99
|
+
getParameters({ parameters, fields: message.properties })
|
|
100
|
+
return parameters
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Extracts the host/port from the amqp socket connection.
|
|
105
|
+
* Stores on connection as symbol to only parse once.
|
|
106
|
+
*
|
|
107
|
+
* @param {Socket} socket amqp connection
|
|
108
|
+
* @returns {object} {host, port } of connection
|
|
109
|
+
*/
|
|
110
|
+
function parseConnect(socket) {
|
|
111
|
+
if (socket[amqpConnection]) {
|
|
112
|
+
return socket[amqpConnection]
|
|
113
|
+
}
|
|
114
|
+
const host = ['127.0.0.1', '::1', '[::1]'].includes(socket?.remoteAddress)
|
|
115
|
+
? 'localhost'
|
|
116
|
+
: socket?.remoteAddress
|
|
117
|
+
const port = socket?.remotePort
|
|
118
|
+
socket[amqpConnection] = { host, port }
|
|
119
|
+
return { host, port }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Helper to set the appropriate value of the callback property
|
|
124
|
+
* in the spec. If it's a promise set to null otherwise set it to `shim.LAST`
|
|
125
|
+
*
|
|
126
|
+
* @param {Shim} shim instance of shim
|
|
127
|
+
* @param {boolean} promiseMode is this promise based?
|
|
128
|
+
* @returns {string|null} appropriate value
|
|
129
|
+
*/
|
|
130
|
+
function setCallback(shim, promiseMode) {
|
|
131
|
+
return promiseMode ? null : shim.LAST
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = {
|
|
135
|
+
describeMessage,
|
|
136
|
+
getParameters,
|
|
137
|
+
getParametersFromMessage,
|
|
138
|
+
parseConnect,
|
|
139
|
+
setCallback,
|
|
140
|
+
TEMP_RE
|
|
141
|
+
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
const asyncHooks = require('./async-hooks')
|
|
9
8
|
const symbols = require('../../symbols')
|
|
10
9
|
|
|
11
10
|
module.exports = initialize
|
|
@@ -63,8 +62,4 @@ function initialize(agent, nodule, name, shim) {
|
|
|
63
62
|
return original.apply(this, arguments)
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
|
-
|
|
67
|
-
// This will initialize the most optimal native-promise instrumentation that
|
|
68
|
-
// we have available.
|
|
69
|
-
asyncHooks(agent, shim)
|
|
70
65
|
}
|