newrelic 8.5.2 → 8.6.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.
@@ -11,28 +11,22 @@ const shimmer = require('../shimmer')
11
11
 
12
12
  /**
13
13
  * @namespace Library.Spec
14
- *
15
14
  * @property {string} name
16
15
  * The name of this promise library.
17
- *
18
16
  * @property {?string} constructor
19
17
  * Optional. The name of the property that is the Promise constructor. Default
20
18
  * is to use the library itself as the Promise constructor.
21
- *
22
19
  * @property {?bool} executor
23
20
  * Optional. If true, the Promise constructor itself will be wrapped for the
24
21
  * executor. If false then `_proto`, `_static`, or `_library` must have an
25
22
  * `executor` field whose value is the name of the executor function. Default
26
23
  * is false.
27
- *
28
24
  * @property {Library.Spec.Mapping} $proto
29
25
  * The mapping for Promise instance method concepts (i.e. `then`). These are
30
26
  * mapped on the Promise class' prototype.
31
- *
32
27
  * @property {Library.Spec.Mapping} $static
33
28
  * The mapping for Promise static method concepts (i.e. `all`, `race`). These
34
29
  * are mapped on the Promise class itself.
35
- *
36
30
  * @property {?Library.Spec.Mapping} $library
37
31
  * The mapping for library-level static method concepts (i.e. `fcall`, `when`).
38
32
  * These are mapped on the library containing the Promise class. NOTE: in most
@@ -42,35 +36,23 @@ const shimmer = require('../shimmer')
42
36
 
43
37
  /**
44
38
  * @namespace Library.Spec.Mapping
45
- *
46
- * @desc
39
+ * @description
47
40
  * A mapping of promise concepts (i.e. `then`) to this library's implementation
48
41
  * name(s) (i.e. `["then", "chain"]`). Each value can by either a single string
49
42
  * or an array of strings if the concept exists under multiple keys. If any
50
43
  * given concept doesn't exist in this library, it is simply skipped.
51
- *
52
- * @property {array} $copy
44
+ * @property {Array} $copy
53
45
  * An array of properties or methods to just directly copy without wrapping.
54
46
  * This field only matters when `Library.Spec.executor` is `true`.
55
- *
56
- * @property {string|array} executor
57
- *
58
- *
59
- * @property {string|array} then
60
- *
61
- *
62
- * @property {string|array} all
63
- *
64
- *
65
- * @property {string|array} race
66
- *
67
- *
68
- * @property {string|array} resolve
47
+ * @property {string | Array} executor
48
+ * @property {string | Array} then
49
+ * @property {string | Array} all
50
+ * @property {string | Array} race
51
+ * @property {string | Array} resolve
69
52
  * Indicates methods to wrap which are resolve factories. This method only
70
53
  * requires wrapping if the library doesn't use an executor internally to
71
54
  * implement it.
72
- *
73
- * @property {string|array} reject
55
+ * @property {string | Array} reject
74
56
  * Indicates methods to wrap which are reject factories. Like `resolve`, this
75
57
  * method only requires wrapping if the library doesn't use an executor
76
58
  * internally to implement it.
@@ -80,11 +62,13 @@ const shimmer = require('../shimmer')
80
62
  * Instruments a promise library.
81
63
  *
82
64
  * @param {Agent} agent - The New Relic APM agent.
83
- * @param {function} library - The promise library.
65
+ * @param {Function} library - The promise library.
84
66
  * @param {?Library.Spec} spec - Spec for this promise library mapping.
85
67
  */
86
68
  /* eslint-disable camelcase */
87
69
  module.exports = function initialize(agent, library, spec) {
70
+ const contextManager = agent._contextManager
71
+
88
72
  if (spec.useFinally == null) {
89
73
  spec.useFinally = true
90
74
  }
@@ -144,7 +128,7 @@ module.exports = function initialize(agent, library, spec) {
144
128
  return Promise(executor) // eslint-disable-line new-cap
145
129
  }
146
130
 
147
- const parent = agent.tracer.segment
131
+ const parent = contextManager.getContext()
148
132
  let promise = null
149
133
  if (
150
134
  !parent ||
@@ -170,15 +154,13 @@ module.exports = function initialize(agent, library, spec) {
170
154
  const segment = _createSegment(segmentName)
171
155
  Contextualizer.link(null, promise, segment, spec.useFinally)
172
156
 
173
- agent.tracer.segment = segment
174
157
  segment.start()
175
158
  try {
176
159
  // Must run after promise is defined so that `__NR_wrapper` can be set.
177
- executor.apply(context.self, context.args)
160
+ contextManager.runInContext(segment, executor, context.self, context.args)
178
161
  } catch (e) {
179
162
  context.args[1](e)
180
163
  } finally {
181
- agent.tracer.segment = parent
182
164
  segment.touch()
183
165
  }
184
166
  }
@@ -259,8 +241,7 @@ module.exports = function initialize(agent, library, spec) {
259
241
  * execution.
260
242
  *
261
243
  * @param {object} context - The object to export the execution context with.
262
- *
263
- * @return {function} A function which, when executed, will add its context
244
+ * @returns {Function} A function which, when executed, will add its context
264
245
  * and arguments to the `context` parameter.
265
246
  */
266
247
  function wrapExecutorContext(context) {
@@ -285,7 +266,9 @@ module.exports = function initialize(agent, library, spec) {
285
266
  /**
286
267
  * Creates a wrapper for `Promise#then` that extends the transaction context.
287
268
  *
288
- * @return {function} A wrapped version of `Promise#then`.
269
+ * @param then
270
+ * @param name
271
+ * @returns {Function} A wrapped version of `Promise#then`.
289
272
  */
290
273
  function wrapThen(then, name) {
291
274
  return _wrapThen(then, name, true)
@@ -294,7 +277,9 @@ module.exports = function initialize(agent, library, spec) {
294
277
  /**
295
278
  * Creates a wrapper for `Promise#catch` that extends the transaction context.
296
279
  *
297
- * @return {function} A wrapped version of `Promise#catch`.
280
+ * @param cach
281
+ * @param name
282
+ * @returns {Function} A wrapped version of `Promise#catch`.
298
283
  */
299
284
  function wrapCatch(cach, name) {
300
285
  return _wrapThen(cach, name, false)
@@ -303,14 +288,13 @@ module.exports = function initialize(agent, library, spec) {
303
288
  /**
304
289
  * Creates a wrapper for promise chain extending methods.
305
290
  *
306
- * @param {function} then
291
+ * @param {Function} then
307
292
  * The function we are to wrap as a chain extender.
308
- *
293
+ * @param name
309
294
  * @param {bool} useAllParams
310
295
  * When true, all parameters which are functions will be wrapped. Otherwise,
311
296
  * only the last parameter will be wrapped.
312
- *
313
- * @return {function} A wrapped version of the function.
297
+ * @returns {Function} A wrapped version of the function.
314
298
  */
315
299
  function _wrapThen(then, name, useAllParams) {
316
300
  // Don't wrap non-functions.
@@ -377,6 +361,9 @@ module.exports = function initialize(agent, library, spec) {
377
361
 
378
362
  /**
379
363
  * Creates a wrapper around the static `Promise` factory method.
364
+ *
365
+ * @param cast
366
+ * @param name
380
367
  */
381
368
  function wrapCast(cast, name) {
382
369
  if (typeof cast !== 'function' || cast.name === '__NR_wrappedCast') {
@@ -437,8 +424,8 @@ module.exports = function initialize(agent, library, spec) {
437
424
  *
438
425
  * @param {object} obj - The source of the methods to wrap.
439
426
  * @param {string} name - The name of this source.
440
- * @param {string|array} methods - The names of the methods to wrap.
441
- * @param {function} wrapper - The function which wraps the methods.
427
+ * @param {string | Array} methods - The names of the methods to wrap.
428
+ * @param {Function} wrapper - The function which wraps the methods.
442
429
  */
443
430
  function _safeWrap(obj, name, methods, wrapper) {
444
431
  if (methods && methods.length) {
@@ -62,20 +62,16 @@ const DESTINATION_TYPES = {
62
62
  /**
63
63
  * Constructs a shim specialized for instrumenting message brokers.
64
64
  *
65
- * @constructor
66
- * @extends TransactionShim
65
+ * @class
66
+ * @augments TransactionShim
67
67
  * @classdesc
68
68
  * Used for instrumenting message broker client libraries.
69
- *
70
69
  * @param {Agent} agent
71
70
  * The agent this shim will use.
72
- *
73
71
  * @param {string} moduleName
74
72
  * The name of the module being instrumented.
75
- *
76
73
  * @param {string} resolvedName
77
74
  * The full path to the loaded module.
78
- *
79
75
  * @see Shim
80
76
  * @see TransactionShim
81
77
  */
@@ -112,124 +108,93 @@ MessageShim.prototype.recordSubscribedConsume = recordSubscribedConsume
112
108
 
113
109
  /**
114
110
  * @callback MessageFunction
115
- *
116
111
  * @summary
117
112
  * Used for determining information about a message either being produced or
118
113
  * consumed.
119
- *
120
114
  * @param {MessageShim} shim
121
115
  * The shim this function was handed to.
122
- *
123
116
  * @param {Function} func
124
117
  * The produce method or message consumer.
125
- *
126
118
  * @param {string} name
127
119
  * The name of the producer or consumer.
128
- *
129
120
  * @param {Array.<*>} args
130
121
  * The arguments being passed into the produce method or consumer.
131
- *
132
- * @return {MessageSpec} The specification for the message being produced or
122
+ * @returns {MessageSpec} The specification for the message being produced or
133
123
  * consumed.
134
- *
135
124
  * @see MessageShim#recordProduce
136
125
  * @see MessageShim#recordConsume
137
126
  */
138
127
 
139
128
  /**
140
129
  * @callback MessageHandlerFunction
141
- *
142
130
  * @summary
143
131
  * A function that is used to extract properties from a consumed message. This
144
132
  * method is handed the results of a consume call. If the consume used a
145
133
  * callback, then this method will receive the arguments to the callback. If
146
134
  * the consume used a promise, then this method will receive the resolved
147
135
  * value.
148
- *
149
136
  * @param {MessageShim} shim
150
137
  * The shim this function was handed to.
151
- *
152
138
  * @param {Function} func
153
139
  * The produce method or message consumer.
154
- *
155
140
  * @param {string} name
156
141
  * The name of the producer or consumer.
157
- *
158
142
  * @param {Array|*} args
159
143
  * Either the arguments for the consumer callback function or the result of
160
144
  * the resolved consume promise, depending on the mode of the instrumented
161
145
  * method.
162
- *
163
- * @return {MessageSpec} The extracted properties of the consumed message.
164
- *
146
+ * @returns {MessageSpec} The extracted properties of the consumed message.
165
147
  * @see MessageShim#recordConsume
166
148
  */
167
149
 
168
150
  /**
169
151
  * @callback MessageConsumerWrapperFunction
170
- *
171
152
  * @summary
172
153
  * Function that is used to wrap message consumer functions. Used along side
173
154
  * the MessageShim#recordSubscribedConsume API method.
174
- *
175
155
  * @param {MessageShim} shim
176
156
  * The shim this function was handed to.
177
- *
178
157
  * @param {Function} consumer
179
158
  * The message consumer to wrap.
180
- *
181
159
  * @param {string} name
182
160
  * The name of the consumer method.
183
- *
184
161
  * @param {string} queue
185
162
  * The name of the queue this consumer is being subscribed to.
186
- *
187
- * @return {Function} The consumer method, possibly wrapped.
188
- *
163
+ * @returns {Function} The consumer method, possibly wrapped.
189
164
  * @see MessageShim#recordSubscribedConsume
190
165
  * @see MessageShim#recordConsume
191
166
  */
192
167
 
193
168
  /**
194
169
  * @interface MessageSpec
195
- * @extends RecorderSpec
196
- *
170
+ * @augments RecorderSpec
197
171
  * @description
198
172
  * The specification for a message being produced or consumed.
199
- *
200
173
  * @property {string} destinationName
201
174
  * The name of the exchange or queue the message is being produced to or
202
175
  * consumed from.
203
- *
204
176
  * @property {MessageShim.DESTINATION_TYPES} [destinationType=null]
205
177
  * The type of the destination. Defaults to `shim.EXCHANGE`.
206
- *
207
- * @property {Object} [headers=null]
178
+ * @property {object} [headers=null]
208
179
  * A reference to the message headers. On produce, more headers will be added
209
180
  * to this object which should be sent along with the message. On consume,
210
181
  * cross-application headers will be read from this object.
211
- *
212
182
  * @property {string} [routingKey=null]
213
183
  * The routing key for the message. If provided on consume, the routing key
214
184
  * will be added to the transaction attributes as `message.routingKey`.
215
- *
216
185
  * @property {string} [queue=null]
217
186
  * The name of the queue the message was consumed from. If provided on
218
187
  * consume, the queue name will be added to the transaction attributes as
219
188
  * `message.queueName`.
220
- *
221
189
  * @property {string} [parameters.correlation_id]
222
190
  * In AMQP, this should be the correlation Id of the message, if it has one.
223
- *
224
191
  * @property {string} [parameters.reply_to]
225
192
  * In AMQP, this should be the name of the queue to reply to, if the message
226
193
  * has one.
227
- *
228
194
  * @property {MessageHandlerFunction} [messageHandler]
229
195
  * An optional function to extract message properties from a consumed message.
230
196
  * This method is only used in the consume case to pull data from the
231
197
  * retrieved message.
232
- *
233
198
  * @see RecorderSpec
234
199
  * @see MessageShim#recordProduce
235
200
  * @see MessageShim#recordConsume
@@ -238,23 +203,19 @@ MessageShim.prototype.recordSubscribedConsume = recordSubscribedConsume
238
203
 
239
204
  /**
240
205
  * @interface MessageSubscribeSpec
241
- * @extends MessageSpec
242
- *
206
+ * @augments MessageSpec
243
207
  * @description
244
208
  * Specification for message subscriber methods. That is, methods which
245
209
  * register a consumer to start receiving messages.
246
- *
247
210
  * @property {number} consumer
248
211
  * The index of the consumer in the method's arguments. Note that if the
249
212
  * consumer and callback indexes point to the same argument, the argument will
250
213
  * be wrapped as a consumer.
251
- *
252
214
  * @property {MessageHandlerFunction} messageHandler
253
215
  * A function to extract message properties from a consumed message.
254
216
  * This method is only used in the consume case to pull data from the
255
217
  * retrieved message. Its return value is combined with the `MessageSubscribeSpec`
256
218
  * to fully describe the consumed message.
257
- *
258
219
  * @see MessageSpec
259
220
  * @see MessageConsumerWrapperFunction
260
221
  * @see MessageShim#recordSubscribedConsume
@@ -269,11 +230,9 @@ MessageShim.prototype.recordSubscribedConsume = recordSubscribedConsume
269
230
  * passed, metric names will be generated using that.
270
231
  *
271
232
  * @memberof MessageShim.prototype
272
- *
273
233
  * @param {MessageShim.LIBRARY_NAMES|string} library
274
234
  * The name of the message broker library. Use one of the well-known constants
275
235
  * listed in {@link MessageShim.LIBRARY_NAMES} if available for the library.
276
- *
277
236
  * @see MessageShim.LIBRARY_NAMES
278
237
  */
279
238
  function setLibrary(library) {
@@ -305,20 +264,15 @@ function setLibrary(library) {
305
264
  * `PRODUCE` metric.
306
265
  *
307
266
  * @memberof MessageShim.prototype
308
- *
309
- * @param {Object|Function} nodule
267
+ * @param {object | Function} nodule
310
268
  * The source for the properties to wrap, or a single function to wrap.
311
- *
312
269
  * @param {string|Array.<string>} [properties]
313
270
  * One or more properties to wrap. If omitted, the `nodule` parameter is
314
271
  * assumed to be the function to wrap.
315
- *
316
272
  * @param {MessageFunction} recordNamer
317
273
  * A function which specifies details of the message.
318
- *
319
- * @return {Object|Function} The first parameter to this function, after
274
+ * @returns {object | Function} The first parameter to this function, after
320
275
  * wrapping it or its properties.
321
- *
322
276
  * @see Shim#wrap
323
277
  * @see Shim#record
324
278
  * @see MessageSpec
@@ -374,21 +328,16 @@ function recordProduce(nodule, properties, recordNamer) {
374
328
  * consumers see {@link MessageShim#recordSubscribedConsume}
375
329
  *
376
330
  * @memberof MessageShim.prototype
377
- *
378
- * @param {Object|Function} nodule
331
+ * @param {object | Function} nodule
379
332
  * The source for the properties to wrap, or a single function to wrap.
380
- *
381
333
  * @param {string|Array.<string>} [properties]
382
334
  * One or more properties to wrap. If omitted, the `nodule` parameter is
383
335
  * assumed to be the function to wrap.
384
- *
385
336
  * @param {MessageSpec|MessageFunction} spec
386
337
  * The spec for the method or a function which returns the details of the
387
338
  * method.
388
- *
389
- * @return {Object|Function} The first parameter to this function, after
339
+ * @returns {object | Function} The first parameter to this function, after
390
340
  * wrapping it or its properties.
391
- *
392
341
  * @see Shim#wrap
393
342
  * @see Shim#record
394
343
  * @see MessageShim#recordSubscribedConsume
@@ -411,6 +360,10 @@ function recordConsume(nodule, properties, spec) {
411
360
  spec = this.setDefaults(spec, DEFAULT_SPEC)
412
361
  }
413
362
 
363
+ // This is using wrap instead of record because the spec allows for a messageHandler
364
+ // which is being used to handle the result of the callback or promise of the
365
+ // original wrapped consume function.
366
+ // TODO: https://github.com/newrelic/node-newrelic/issues/981
414
367
  return this.wrap(nodule, properties, function wrapConsume(shim, fn, fnName) {
415
368
  if (!shim.isFunction(fn)) {
416
369
  shim.logger.debug('Not wrapping %s (%s) as consume', fn, fnName)
@@ -487,15 +440,19 @@ function recordConsume(nodule, properties, spec) {
487
440
  // Call the method in the context of our segment.
488
441
  let ret = shim.applySegment(fn, segment, true, this, args)
489
442
 
490
- // Intercept the promise to handle the result.
491
- if (resHandler && ret && msgDesc.promise && shim.isPromise(ret)) {
492
- ret = ret.then(function interceptValue(res) {
493
- const msgProps = resHandler.call(this, shim, fn, fnName, res)
494
- if (getParams && msgProps && msgProps.parameters) {
495
- shim.copySegmentParameters(segment, msgProps.parameters)
496
- }
497
- return res
498
- })
443
+ if (ret && msgDesc.promise && shim.isPromise(ret)) {
444
+ ret = shim.bindPromise(ret, segment)
445
+
446
+ // Intercept the promise to handle the result.
447
+ if (resHandler) {
448
+ ret = ret.then(function interceptValue(res) {
449
+ const msgProps = resHandler.call(this, shim, fn, fnName, res)
450
+ if (getParams && msgProps && msgProps.parameters) {
451
+ shim.copySegmentParameters(segment, msgProps.parameters)
452
+ }
453
+ return res
454
+ })
455
+ }
499
456
  }
500
457
 
501
458
  return ret
@@ -510,23 +467,17 @@ function recordConsume(nodule, properties, spec) {
510
467
  * - `recordPurgeQueue(func, spec)`
511
468
  *
512
469
  * @memberof MessageShim.prototype
513
- *
514
- * @param {Object|Function} nodule
470
+ * @param {object | Function} nodule
515
471
  * The source for the properties to wrap, or a single function to wrap.
516
- *
517
472
  * @param {string|Array.<string>} [properties]
518
473
  * One or more properties to wrap. If omitted, the `nodule` parameter is
519
474
  * assumed to be the function to wrap.
520
- *
521
475
  * @param {RecorderSpec} spec
522
476
  * The specification for this queue purge method's interface.
523
- *
524
477
  * @param {string} spec.queue
525
478
  * The name of the queue being purged.
526
- *
527
- * @return {Object|Function} The first parameter to this function, after
479
+ * @returns {object | Function} The first parameter to this function, after
528
480
  * wrapping it or its properties.
529
- *
530
481
  * @see Shim#wrap
531
482
  * @see Shim#record
532
483
  * @see RecorderSpec
@@ -598,20 +549,15 @@ function recordPurgeQueue(nodule, properties, spec) {
598
549
  * `spec.wrapper` method even if no transaction is active.
599
550
  *
600
551
  * @memberof MessageShim.prototype
601
- *
602
- * @param {Object|Function} nodule
552
+ * @param {object | Function} nodule
603
553
  * The source for the properties to wrap, or a single function to wrap.
604
- *
605
554
  * @param {string|Array.<string>} [properties]
606
555
  * One or more properties to wrap. If omitted, the `nodule` parameter is
607
556
  * assumed to be the function to wrap.
608
- *
609
557
  * @param {MessageSubscribeSpec} spec
610
558
  * The specification for this subscription method's interface.
611
- *
612
- * @return {Object|Function} The first parameter to this function, after
559
+ * @returns {object | Function} The first parameter to this function, after
613
560
  * wrapping it or its properties.
614
- *
615
561
  * @see Shim#wrap
616
562
  * @see Shim#record
617
563
  * @see MessageShim#recordConsume
@@ -702,6 +648,10 @@ function recordSubscribedConsume(nodule, properties, spec) {
702
648
  }
703
649
  })
704
650
 
651
+ /**
652
+ * @param queue
653
+ * @param destinationName
654
+ */
705
655
  function makeWrapConsumer(queue, destinationName) {
706
656
  const msgDescDefaults = copy.shallow(spec)
707
657
  if (destNameIsArg && destinationName != null) {
@@ -810,6 +760,9 @@ function recordSubscribedConsume(nodule, properties, spec) {
810
760
 
811
761
  return ret
812
762
 
763
+ /**
764
+ *
765
+ */
813
766
  function endTransaction() {
814
767
  tx.finalizeName(null) // Use existing partial name.
815
768
  tx.end()
@@ -830,12 +783,10 @@ function recordSubscribedConsume(nodule, properties, spec) {
830
783
  * Constructs a message segment name from the given message descriptor.
831
784
  *
832
785
  * @private
833
- *
834
786
  * @param {MessageShim} shim - The shim the segment will be constructed by.
835
787
  * @param {MessageSpec} msgDesc - The message descriptor.
836
788
  * @param {string} action - Produce or consume?
837
- *
838
- * @return {string} The generated name of the message segment.
789
+ * @returns {string} The generated name of the message segment.
839
790
  */
840
791
  function _nameMessageSegment(shim, msgDesc, action) {
841
792
  let name =
@@ -855,6 +806,10 @@ function _nameMessageSegment(shim, msgDesc, action) {
855
806
  return name
856
807
  }
857
808
 
809
+ /**
810
+ * @param shim
811
+ * @param msgDesc
812
+ */
858
813
  function _nameMessageTransaction(shim, msgDesc) {
859
814
  let name = shim._metrics.LIBRARY + '/' + (msgDesc.destinationType || shim.EXCHANGE) + '/'
860
815