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.
- package/NEWS.md +12 -0
- package/api.js +121 -135
- package/lib/agent.js +11 -2
- package/lib/context-manager/create-context-manager.js +32 -0
- package/lib/context-manager/diagnostics/legacy-diagnostic-context-manager.js +36 -0
- package/lib/context-manager/legacy-context-manager.js +66 -0
- package/lib/instrumentation/promise.js +28 -41
- package/lib/shim/message-shim.js +45 -90
- package/lib/shim/shim.js +139 -324
- package/lib/shim/transaction-shim.js +9 -39
- package/lib/shimmer.js +110 -10
- package/lib/transaction/tracer/index.js +24 -22
- package/package.json +2 -1
|
@@ -16,15 +16,13 @@ const TRANSACTION_TYPES_SET = Transaction.TYPES_SET
|
|
|
16
16
|
/**
|
|
17
17
|
* Constructs a transaction managing shim.
|
|
18
18
|
*
|
|
19
|
-
* @
|
|
20
|
-
* @
|
|
19
|
+
* @class
|
|
20
|
+
* @augments Shim
|
|
21
21
|
* @classdesc
|
|
22
22
|
* A helper class for working with transactions.
|
|
23
|
-
*
|
|
24
23
|
* @param {Agent} agent - The agent the shim will use.
|
|
25
24
|
* @param {string} moduleName - The name of the module being instrumented.
|
|
26
25
|
* @param {string} resolvedName - The full path to the loaded module.
|
|
27
|
-
*
|
|
28
26
|
* @see Shim
|
|
29
27
|
* @see WebFrameworkShim
|
|
30
28
|
*/
|
|
@@ -75,22 +73,18 @@ TransactionShim.prototype.insertCATRequestHeaders = insertCATRequestHeaders
|
|
|
75
73
|
|
|
76
74
|
/**
|
|
77
75
|
* @interface TransactionSpec
|
|
78
|
-
*
|
|
79
76
|
* @description
|
|
80
77
|
* Describes the type of transaction to be created by the function being
|
|
81
78
|
* wrapped by {@link Shim#bindCreateTransaction}.
|
|
82
|
-
*
|
|
83
79
|
* @property {string} type
|
|
84
80
|
* The type of transaction to create. Must be one of the values from
|
|
85
81
|
* {@link Shim#TRANSACTION_TYPES}.
|
|
86
|
-
*
|
|
87
82
|
* @property {bool} [nest=false]
|
|
88
83
|
* Indicates if the transaction being created is allowed to be nested within
|
|
89
84
|
* another transaction of the same type. If `false`, the default, the transaction
|
|
90
85
|
* will only be created if there is no existing transaction, or the current
|
|
91
86
|
* transaction is of a different type. If `true`, the transaction will be
|
|
92
87
|
* created regardless of the current transaction's type.
|
|
93
|
-
*
|
|
94
88
|
* @see Shim#bindCreateTransaction
|
|
95
89
|
* @see Shim#TRANSACTION_TYPES
|
|
96
90
|
*/
|
|
@@ -105,18 +99,14 @@ TransactionShim.prototype.insertCATRequestHeaders = insertCATRequestHeaders
|
|
|
105
99
|
* - `bindCreateTransaction(func, spec)`
|
|
106
100
|
*
|
|
107
101
|
* @memberof TransactionShim.prototype
|
|
108
|
-
*
|
|
109
|
-
* @param {Object|Function} nodule
|
|
102
|
+
* @param {object | Function} nodule
|
|
110
103
|
* The source for the property to wrap, or a single function to wrap.
|
|
111
|
-
*
|
|
112
104
|
* @param {string} [property]
|
|
113
105
|
* The property to wrap. If omitted, the `nodule` parameter is assumed to be
|
|
114
106
|
* the function to wrap.
|
|
115
|
-
*
|
|
116
107
|
* @param {TransactionSpec} spec
|
|
117
108
|
* The spec for creating the transaction.
|
|
118
|
-
*
|
|
119
|
-
* @return {Object|Function} The first parameter to this function, after
|
|
109
|
+
* @returns {object | Function} The first parameter to this function, after
|
|
120
110
|
* wrapping it or its property.
|
|
121
111
|
*/
|
|
122
112
|
function bindCreateTransaction(nodule, property, spec) {
|
|
@@ -164,7 +154,6 @@ function bindCreateTransaction(nodule, property, spec) {
|
|
|
164
154
|
* back off when resolution exits the item.
|
|
165
155
|
*
|
|
166
156
|
* @memberof TransactionShim.prototype
|
|
167
|
-
*
|
|
168
157
|
* @param {string} pathSegment - The path segment to add to the naming stack.
|
|
169
158
|
*/
|
|
170
159
|
function pushTransactionName(pathSegment) {
|
|
@@ -183,7 +172,6 @@ function pushTransactionName(pathSegment) {
|
|
|
183
172
|
* this function, but we do not live in an ideal world.
|
|
184
173
|
*
|
|
185
174
|
* @memberof TransactionShim.prototype
|
|
186
|
-
*
|
|
187
175
|
* @param {string} [pathSegment]
|
|
188
176
|
* Optional. Path segment to pop the stack repeatedly until a segment matching
|
|
189
177
|
* `pathSegment` is removed.
|
|
@@ -203,7 +191,6 @@ function popTransactionName(pathSegment) {
|
|
|
203
191
|
* Either this _or_ the naming stack should be used. Do not use them together.
|
|
204
192
|
*
|
|
205
193
|
* @memberof TransactionShim.prototype
|
|
206
|
-
*
|
|
207
194
|
* @param {string} name - The name to use for the transaction.
|
|
208
195
|
*/
|
|
209
196
|
function setTransactionName(name) {
|
|
@@ -222,14 +209,11 @@ function setTransactionName(name) {
|
|
|
222
209
|
*
|
|
223
210
|
* This will check for either header naming style, and both request and reply
|
|
224
211
|
* CAT headers.
|
|
225
|
-
*
|
|
226
212
|
* @param {object} headers
|
|
227
213
|
* The request/response headers object to look in.
|
|
228
|
-
*
|
|
229
214
|
* @param {TraceSegment} [segment=null]
|
|
230
215
|
* The trace segment to associate the header data with. If no segment is
|
|
231
216
|
* provided then the currently active segment is used.
|
|
232
|
-
*
|
|
233
217
|
* @param {string} [transportType='Unknown']
|
|
234
218
|
* The transport type that brought the headers. Usually `HTTP` or `HTTPS`.
|
|
235
219
|
*/
|
|
@@ -282,10 +266,8 @@ function handleCATHeaders(headers, segment, transportType) {
|
|
|
282
266
|
* - `insertCATRequestHeaders(headers [, useAlternateHeaderNames])`
|
|
283
267
|
*
|
|
284
268
|
* @memberof TransactionShim.prototype
|
|
285
|
-
*
|
|
286
269
|
* @param {object} headers
|
|
287
270
|
* The outbound request headers object to inject our CAT headers into.
|
|
288
|
-
*
|
|
289
271
|
* @param {bool} [useAlternateHeaderNames=false]
|
|
290
272
|
* Indicates if HTTP-style headers should be used or alternate style. Some
|
|
291
273
|
* transport protocols are more strict on the characters allowed in headers
|
|
@@ -327,10 +309,8 @@ function insertCATRequestHeaders(headers, useAlternateHeaderNames) {
|
|
|
327
309
|
* - `insertCATReplyHeaders(headers [, useAlternateHeaderNames])`
|
|
328
310
|
*
|
|
329
311
|
* @memberof TransactionShim.prototype
|
|
330
|
-
*
|
|
331
312
|
* @param {object} headers
|
|
332
313
|
* The outbound response headers object to inject our CAT headers into.
|
|
333
|
-
*
|
|
334
314
|
* @param {bool} [useAlternateHeaderNames=false]
|
|
335
315
|
* Indicates if HTTP-style headers should be used or alternate style. Some
|
|
336
316
|
* transport protocols are more strict on the characters allowed in headers
|
|
@@ -388,20 +368,15 @@ function insertCATReplyHeader(headers, useAlternateHeaderNames) {
|
|
|
388
368
|
* `spec.type` is not the same as the current transaction's type.
|
|
389
369
|
*
|
|
390
370
|
* @private
|
|
391
|
-
*
|
|
392
371
|
* @param {Shim} shim
|
|
393
372
|
* The shim used for the binding.
|
|
394
|
-
*
|
|
395
|
-
* @param {function} fn
|
|
373
|
+
* @param {Function} fn
|
|
396
374
|
* The function link with the transaction.
|
|
397
|
-
*
|
|
398
375
|
* @param {string} name
|
|
399
376
|
* The name of the wrapped function.
|
|
400
|
-
*
|
|
401
377
|
* @param {TransactionSpec} spec
|
|
402
378
|
* The spec for the transaction to create.
|
|
403
|
-
*
|
|
404
|
-
* @return {function} A function which wraps `fn` and creates potentially nested
|
|
379
|
+
* @returns {Function} A function which wraps `fn` and creates potentially nested
|
|
405
380
|
* transactions linked to its execution.
|
|
406
381
|
*/
|
|
407
382
|
function _makeNestedTransWrapper(shim, fn, name, spec) {
|
|
@@ -412,7 +387,7 @@ function _makeNestedTransWrapper(shim, fn, name, spec) {
|
|
|
412
387
|
|
|
413
388
|
// Reuse existing transactions only if the type matches.
|
|
414
389
|
let transaction = shim.tracer.getTransaction()
|
|
415
|
-
let segment = shim.
|
|
390
|
+
let segment = shim.getSegment()
|
|
416
391
|
|
|
417
392
|
// Only create a new transaction if we either do not have a current
|
|
418
393
|
// transaction _or_ the current transaction is not of the type we want.
|
|
@@ -433,20 +408,15 @@ function _makeNestedTransWrapper(shim, fn, name, spec) {
|
|
|
433
408
|
* A transaction will only be created if there is not a currently active one.
|
|
434
409
|
*
|
|
435
410
|
* @private
|
|
436
|
-
*
|
|
437
411
|
* @param {Shim} shim
|
|
438
412
|
* The shim used for the binding.
|
|
439
|
-
*
|
|
440
|
-
* @param {function} fn
|
|
413
|
+
* @param {Function} fn
|
|
441
414
|
* The function link with the transaction.
|
|
442
|
-
*
|
|
443
415
|
* @param {string} name
|
|
444
416
|
* The name of the wrapped function.
|
|
445
|
-
*
|
|
446
417
|
* @param {TransactionSpec} spec
|
|
447
418
|
* The spec for the transaction to create.
|
|
448
|
-
*
|
|
449
|
-
* @return {function} A function which wraps `fn` and potentially creates a new
|
|
419
|
+
* @returns {Function} A function which wraps `fn` and potentially creates a new
|
|
450
420
|
* transaction linked to the function's execution.
|
|
451
421
|
*/
|
|
452
422
|
function _makeTransWrapper(shim, fn, name, spec) {
|
package/lib/shimmer.js
CHANGED
|
@@ -90,9 +90,8 @@ const shimmer = (module.exports = {
|
|
|
90
90
|
/**
|
|
91
91
|
* Detects if the given function has already been wrapped.
|
|
92
92
|
*
|
|
93
|
-
* @param {
|
|
94
|
-
*
|
|
95
|
-
* @return {bool} True if `fn` exists and has an attached original, else false.
|
|
93
|
+
* @param {Function} fn - The function to look for a wrapper on.
|
|
94
|
+
* @returns {bool} True if `fn` exists and has an attached original, else false.
|
|
96
95
|
*/
|
|
97
96
|
isWrapped: function isWrapped(fn) {
|
|
98
97
|
return !!(fn && fn.__NR_original)
|
|
@@ -111,7 +110,7 @@ const shimmer = (module.exports = {
|
|
|
111
110
|
* helpful than you'd think.
|
|
112
111
|
* @param {string} methods One or more names of methods or functions to extract
|
|
113
112
|
* and wrap.
|
|
114
|
-
* @param {
|
|
113
|
+
* @param {Function} wrapper A generator that, when called, returns a
|
|
115
114
|
* wrapped version of the original function.
|
|
116
115
|
*/
|
|
117
116
|
wrapMethod: function wrapMethod(nodule, noduleName, methods, wrapper) {
|
|
@@ -177,8 +176,7 @@ const shimmer = (module.exports = {
|
|
|
177
176
|
* @param {object} noduleName Human-readable module / Class name. More
|
|
178
177
|
* helpful than you'd think.
|
|
179
178
|
* @param {string} property The property to replace with the accessor.
|
|
180
|
-
* @param {
|
|
181
|
-
*
|
|
179
|
+
* @param {Function} options Optional getter and setter to use for the accessor.
|
|
182
180
|
* @returns {object} The original value of the property.
|
|
183
181
|
*/
|
|
184
182
|
wrapDeprecated: function wrapDeprecated(nodule, noduleName, property, options) {
|
|
@@ -275,6 +273,8 @@ const shimmer = (module.exports = {
|
|
|
275
273
|
/**
|
|
276
274
|
* Patch the module.load function so that we see modules loading and
|
|
277
275
|
* have an opportunity to patch them with instrumentation.
|
|
276
|
+
*
|
|
277
|
+
* @param agent
|
|
278
278
|
*/
|
|
279
279
|
patchModule: function patchModule(agent) {
|
|
280
280
|
logger.trace('Wrapping module loader.')
|
|
@@ -287,6 +287,9 @@ const shimmer = (module.exports = {
|
|
|
287
287
|
// we can examine it after the load call has returned.
|
|
288
288
|
const resolvedFilepath = resolve.apply(this, arguments)
|
|
289
289
|
filepathMap[file] = resolvedFilepath
|
|
290
|
+
|
|
291
|
+
_onResolveFileName(agent, file, resolvedFilepath)
|
|
292
|
+
|
|
290
293
|
return resolvedFilepath
|
|
291
294
|
}
|
|
292
295
|
})
|
|
@@ -306,6 +309,7 @@ const shimmer = (module.exports = {
|
|
|
306
309
|
* their parent has already been loaded/cached by Node.
|
|
307
310
|
* Provides a fall-back for unexpected cases that may occur.
|
|
308
311
|
* Also provides flexibility for testing now that node 11+ caches these.
|
|
312
|
+
*
|
|
309
313
|
* @param {*} request
|
|
310
314
|
* @param {*} parent
|
|
311
315
|
* @param {*} isMain
|
|
@@ -398,6 +402,10 @@ const shimmer = (module.exports = {
|
|
|
398
402
|
},
|
|
399
403
|
|
|
400
404
|
registerInstrumentation: function registerInstrumentation(opts) {
|
|
405
|
+
if (!hasValidRegisterOptions(opts)) {
|
|
406
|
+
return
|
|
407
|
+
}
|
|
408
|
+
|
|
401
409
|
shimmer.registeredInstrumentations[opts.moduleName] = opts
|
|
402
410
|
},
|
|
403
411
|
|
|
@@ -419,6 +427,9 @@ const shimmer = (module.exports = {
|
|
|
419
427
|
* re-wrap them.
|
|
420
428
|
*
|
|
421
429
|
* Use this to re-apply any applicable instrumentation.
|
|
430
|
+
*
|
|
431
|
+
* @param agent
|
|
432
|
+
* @param modulePath
|
|
422
433
|
*/
|
|
423
434
|
reinstrument: function reinstrument(agent, modulePath) {
|
|
424
435
|
return _postLoad(agent, require(modulePath), modulePath)
|
|
@@ -428,6 +439,8 @@ const shimmer = (module.exports = {
|
|
|
428
439
|
* Given a NodeJS module name, return the name/identifier of our
|
|
429
440
|
* instrumentation. These two things are usually, but not always,
|
|
430
441
|
* the same.
|
|
442
|
+
*
|
|
443
|
+
* @param moduleName
|
|
431
444
|
*/
|
|
432
445
|
getInstrumentationNameFromModuleName(moduleName) {
|
|
433
446
|
let instrumentation
|
|
@@ -467,8 +480,13 @@ function applyDebugState(shim, nodule) {
|
|
|
467
480
|
* All instrumentation files must export the same interface: a single
|
|
468
481
|
* initialization function that takes the agent and the module to be
|
|
469
482
|
* instrumented.
|
|
483
|
+
*
|
|
484
|
+
* @param agent
|
|
485
|
+
* @param nodule
|
|
486
|
+
* @param moduleName
|
|
487
|
+
* @param resolvedName
|
|
470
488
|
*/
|
|
471
|
-
function
|
|
489
|
+
function instrumentPostLoad(agent, nodule, moduleName, resolvedName) {
|
|
472
490
|
const instrumentation = shimmer.registeredInstrumentations[moduleName]
|
|
473
491
|
if (
|
|
474
492
|
properties.hasOwn(nodule, '__NR_instrumented') ||
|
|
@@ -536,11 +554,93 @@ function _firstPartyInstrumentation(agent, fileName, shim, nodule, moduleName) {
|
|
|
536
554
|
function _postLoad(agent, nodule, name, resolvedName) {
|
|
537
555
|
const instrumentation = shimmer.getInstrumentationNameFromModuleName(name)
|
|
538
556
|
|
|
557
|
+
const registeredInstrumentation = shimmer.registeredInstrumentations[instrumentation]
|
|
558
|
+
const hasPostLoadInstrumentation =
|
|
559
|
+
registeredInstrumentation && registeredInstrumentation.onRequire
|
|
560
|
+
|
|
539
561
|
// Check if this is a known instrumentation and then run it.
|
|
540
|
-
if (
|
|
541
|
-
logger.trace('Instrumenting %s.', name)
|
|
542
|
-
return
|
|
562
|
+
if (hasPostLoadInstrumentation) {
|
|
563
|
+
logger.trace('Instrumenting %s with onRequire (module loaded) hook.', name)
|
|
564
|
+
return instrumentPostLoad(agent, nodule, instrumentation, resolvedName)
|
|
543
565
|
}
|
|
544
566
|
|
|
545
567
|
return nodule
|
|
546
568
|
}
|
|
569
|
+
|
|
570
|
+
function _onResolveFileName(agent, requiredNameOrPath, resolvedFilepath) {
|
|
571
|
+
const instrumentation = shimmer.getInstrumentationNameFromModuleName(requiredNameOrPath)
|
|
572
|
+
|
|
573
|
+
const registeredInstrumentation = shimmer.registeredInstrumentations[instrumentation]
|
|
574
|
+
const hasResolvedFileInstrumentation =
|
|
575
|
+
registeredInstrumentation && registeredInstrumentation.onResolved
|
|
576
|
+
|
|
577
|
+
// Check if this is a known instrumentation and then run it.
|
|
578
|
+
if (hasResolvedFileInstrumentation) {
|
|
579
|
+
logger.trace('Instrumenting %s with onResolved hook.', requiredNameOrPath)
|
|
580
|
+
_instrumentOnResolved(agent, instrumentation, resolvedFilepath)
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Invokes the onResolved handler with a shim instance.
|
|
586
|
+
*
|
|
587
|
+
* Given Node.js caches resolvedFilePaths in versions we support and we cache as well
|
|
588
|
+
* for the cases we force resolution, we should not run into the case of multiple
|
|
589
|
+
* invocations for the same module. As such, this function does not defend against multiple runs.
|
|
590
|
+
*
|
|
591
|
+
* @param agent
|
|
592
|
+
* @param moduleName
|
|
593
|
+
* @param resolvedFilepath
|
|
594
|
+
*/
|
|
595
|
+
function _instrumentOnResolved(agent, moduleName, resolvedFilepath) {
|
|
596
|
+
const instrumentation = shimmer.registeredInstrumentations[moduleName]
|
|
597
|
+
|
|
598
|
+
const shim = shims.createShimFromType(instrumentation.type, agent, moduleName, resolvedFilepath)
|
|
599
|
+
|
|
600
|
+
try {
|
|
601
|
+
instrumentation.onResolved(shim, moduleName, resolvedFilepath)
|
|
602
|
+
} catch (instrumentationError) {
|
|
603
|
+
if (instrumentation.onError) {
|
|
604
|
+
try {
|
|
605
|
+
instrumentation.onError(instrumentationError)
|
|
606
|
+
} catch (error) {
|
|
607
|
+
logger.warn(
|
|
608
|
+
error,
|
|
609
|
+
instrumentationError,
|
|
610
|
+
'OnResolved instrumentation for %s failed, then the onError handler threw an error',
|
|
611
|
+
moduleName
|
|
612
|
+
)
|
|
613
|
+
}
|
|
614
|
+
} else {
|
|
615
|
+
logger.warn(
|
|
616
|
+
instrumentationError,
|
|
617
|
+
'OnResolved instrumentation for %s failed. Please report this to the ' +
|
|
618
|
+
'maintainers of the custom instrumentation.',
|
|
619
|
+
moduleName
|
|
620
|
+
)
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function hasValidRegisterOptions(opts) {
|
|
626
|
+
if (!opts) {
|
|
627
|
+
logger.warn('Instrumentation registration failed, no options provided')
|
|
628
|
+
return false
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (!opts.moduleName) {
|
|
632
|
+
logger.warn(`Instrumentation registration failed, 'moduleName' not provided`)
|
|
633
|
+
return false
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (!opts.onRequire && !opts.onResolved) {
|
|
637
|
+
logger.warn(
|
|
638
|
+
'Instrumentation registration for %s failed, no require hooks provided.',
|
|
639
|
+
opts.moduleName
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
return false
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
return true
|
|
646
|
+
}
|
|
@@ -16,13 +16,13 @@ const SEGMENT = '__NR_segment'
|
|
|
16
16
|
|
|
17
17
|
module.exports = Tracer
|
|
18
18
|
|
|
19
|
-
function Tracer(agent) {
|
|
19
|
+
function Tracer(agent, contextManager) {
|
|
20
20
|
if (!agent) {
|
|
21
21
|
throw new Error('Must be initialized with an agent.')
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
this.agent = agent
|
|
25
|
-
this.
|
|
25
|
+
this._contextManager = contextManager
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
Tracer.prototype.getTransaction = getTransaction
|
|
@@ -47,33 +47,35 @@ Tracer.prototype.wrapCallback = wrapCallback
|
|
|
47
47
|
|
|
48
48
|
Object.defineProperty(Tracer.prototype, 'segment', {
|
|
49
49
|
get: function segmentGetter() {
|
|
50
|
-
return this.
|
|
50
|
+
return this._contextManager.getContext()
|
|
51
51
|
},
|
|
52
52
|
set: function segmentSetter(segment) {
|
|
53
|
-
this.
|
|
54
|
-
|
|
55
|
-
return (this._segment = segment)
|
|
53
|
+
this._contextManager.setContext(segment)
|
|
54
|
+
return segment
|
|
56
55
|
}
|
|
57
56
|
})
|
|
58
57
|
|
|
59
58
|
function getTransaction() {
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
const currentSegment = this._contextManager.getContext()
|
|
60
|
+
if (currentSegment && currentSegment.transaction && currentSegment.transaction.isActive()) {
|
|
61
|
+
return currentSegment.transaction
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
return null
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
// TODO: Remove/replace external uses to tracer.getSegment()
|
|
67
68
|
function getSegment() {
|
|
68
|
-
return this.
|
|
69
|
+
return this._contextManager.getContext()
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
function getSpanContext() {
|
|
72
|
-
|
|
73
|
+
const currentSegment = this.getSegment()
|
|
74
|
+
return currentSegment && currentSegment.getSpanContext()
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
function createSegment(name, recorder, _parent) {
|
|
76
|
-
const parent = _parent || this.
|
|
78
|
+
const parent = _parent || this.getSegment()
|
|
77
79
|
if (!parent || !parent.transaction.isActive()) {
|
|
78
80
|
logger.trace(
|
|
79
81
|
{
|
|
@@ -111,7 +113,7 @@ function transactionProxy(handler) {
|
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
// don't nest transactions, reuse existing ones
|
|
114
|
-
const segment = tracer.
|
|
116
|
+
const segment = tracer.getSegment()
|
|
115
117
|
if (segment) {
|
|
116
118
|
if (segment.transaction.traceStacks) {
|
|
117
119
|
segment.probe('!!! Nested transaction creation !!!')
|
|
@@ -143,9 +145,9 @@ function transactionProxy(handler) {
|
|
|
143
145
|
* if there is an in play segment and uses that as the root instead of
|
|
144
146
|
* transaction.trace.root.
|
|
145
147
|
*
|
|
146
|
-
* @param {
|
|
147
|
-
*
|
|
148
|
-
* @
|
|
148
|
+
* @param {string} type - Type of transaction to create. 'web' or 'bg'.
|
|
149
|
+
* @param {Function} handler - Generator to proxy.
|
|
150
|
+
* @returns {Function} Proxy.
|
|
149
151
|
*/
|
|
150
152
|
function transactionNestProxy(type, handler) {
|
|
151
153
|
if (handler === undefined && typeof type === 'function') {
|
|
@@ -165,7 +167,7 @@ function transactionNestProxy(type, handler) {
|
|
|
165
167
|
|
|
166
168
|
// don't nest transactions, reuse existing ones
|
|
167
169
|
let transaction = tracer.getTransaction()
|
|
168
|
-
let segment = tracer.
|
|
170
|
+
let segment = tracer.getSegment()
|
|
169
171
|
|
|
170
172
|
let createNew = false
|
|
171
173
|
|
|
@@ -192,7 +194,7 @@ function bindFunction(handler, segment, full) {
|
|
|
192
194
|
return handler
|
|
193
195
|
}
|
|
194
196
|
|
|
195
|
-
return _makeWrapped(this, handler, segment || this.
|
|
197
|
+
return _makeWrapped(this, handler, segment || this.getSegment(), !!full)
|
|
196
198
|
}
|
|
197
199
|
function _makeWrapped(tracer, handler, active, full) {
|
|
198
200
|
wrapped[ORIGINAL] = getOriginal(handler)
|
|
@@ -201,18 +203,19 @@ function _makeWrapped(tracer, handler, active, full) {
|
|
|
201
203
|
return wrapped
|
|
202
204
|
|
|
203
205
|
function wrapped() {
|
|
204
|
-
const prev = tracer.
|
|
205
|
-
|
|
206
|
+
const prev = tracer.getSegment()
|
|
207
|
+
|
|
206
208
|
if (active && full) {
|
|
207
209
|
active.start()
|
|
208
210
|
}
|
|
211
|
+
|
|
209
212
|
try {
|
|
210
|
-
return
|
|
213
|
+
return tracer._contextManager.runInContext(active, handler, this, arguments)
|
|
211
214
|
} catch (err) {
|
|
212
215
|
logger.trace(err, 'Error from wrapped function:')
|
|
213
216
|
|
|
214
217
|
if (prev === null && process.domain != null) {
|
|
215
|
-
process.domain.__NR_transactionSegment = tracer.
|
|
218
|
+
process.domain.__NR_transactionSegment = tracer.getSegment()
|
|
216
219
|
}
|
|
217
220
|
|
|
218
221
|
throw err // Re-throwing application error, this is not an agent error.
|
|
@@ -220,7 +223,6 @@ function _makeWrapped(tracer, handler, active, full) {
|
|
|
220
223
|
if (active && full) {
|
|
221
224
|
active.touch()
|
|
222
225
|
}
|
|
223
|
-
tracer.segment = prev
|
|
224
226
|
}
|
|
225
227
|
}
|
|
226
228
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newrelic",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.0",
|
|
4
4
|
"author": "New Relic Node.js agent team <nodejs@newrelic.com>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"contributors": [
|
|
@@ -149,6 +149,7 @@
|
|
|
149
149
|
"versioned-tests": "./bin/run-versioned-tests.sh",
|
|
150
150
|
"update-changelog-version": "node ./bin/update-changelog-version",
|
|
151
151
|
"versioned": "npm run versioned:npm7",
|
|
152
|
+
"versioned:major": "npm run prepare-test && VERSIONED_MODE=--major NPM7=1 time ./bin/run-versioned-tests.sh",
|
|
152
153
|
"versioned:npm6": "npm run prepare-test && time ./bin/run-versioned-tests.sh",
|
|
153
154
|
"versioned:npm7": "npm run prepare-test && NPM7=1 time ./bin/run-versioned-tests.sh",
|
|
154
155
|
"prepare": "husky install"
|