newrelic 8.3.0 → 8.5.2
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 +76 -0
- package/README.md +7 -6
- package/THIRD_PARTY_NOTICES.md +95 -35
- package/api.js +74 -68
- package/bin/test-naming-rules.js +22 -22
- package/lib/agent.js +4 -4
- package/lib/attributes.js +2 -2
- package/lib/collector/api.js +12 -12
- package/lib/collector/facts.js +1 -1
- package/lib/collector/http-agents.js +12 -11
- package/lib/collector/key-parser.js +1 -1
- package/lib/collector/remote-method.js +27 -26
- package/lib/config/attribute-filter.js +23 -23
- package/lib/config/default.js +12 -10
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +82 -66
- package/lib/config/lasp.js +3 -3
- package/lib/config/merge-server-config.js +1 -1
- package/lib/db/parse-sql.js +8 -8
- package/lib/db/parsed-statement.js +9 -8
- package/lib/db/query-parsers/sql.js +7 -7
- package/lib/db/query-sample.js +9 -9
- package/lib/db/query-trace-aggregator.js +4 -4
- package/lib/db/statement-matcher.js +5 -5
- package/lib/db/utils.js +1 -1
- package/lib/environment.js +43 -43
- package/lib/errors/error-collector.js +2 -2
- package/lib/errors/error-trace-aggregator.js +1 -1
- package/lib/errors/helper.js +3 -3
- package/lib/errors/index.js +17 -17
- package/lib/feature_flags.js +7 -5
- package/lib/header-attributes.js +6 -6
- package/lib/header-processing.js +1 -1
- package/lib/instrumentation/amqplib.js +26 -26
- package/lib/instrumentation/bluebird.js +3 -3
- package/lib/instrumentation/cassandra-driver.js +7 -3
- package/lib/instrumentation/connect.js +4 -4
- package/lib/instrumentation/core/async_hooks.js +6 -6
- package/lib/instrumentation/core/domain.js +2 -2
- package/lib/instrumentation/core/globals.js +1 -1
- package/lib/instrumentation/core/http-outbound.js +15 -84
- package/lib/instrumentation/core/http.js +34 -67
- package/lib/instrumentation/core/inspector.js +2 -2
- package/lib/instrumentation/core/timers.js +7 -7
- package/lib/instrumentation/core/zlib.js +2 -2
- package/lib/instrumentation/director.js +4 -4
- package/lib/instrumentation/express.js +8 -8
- package/lib/instrumentation/fastify/spec-builders.js +57 -47
- package/lib/instrumentation/fastify.js +85 -24
- package/lib/instrumentation/generic-pool.js +1 -1
- package/lib/instrumentation/hapi/hapi-17.js +11 -11
- package/lib/instrumentation/hapi/shared.js +1 -1
- package/lib/instrumentation/hapi.js +22 -22
- package/lib/instrumentation/ioredis.js +7 -7
- package/lib/instrumentation/memcached.js +7 -7
- package/lib/instrumentation/mongodb/common.js +16 -5
- package/lib/instrumentation/mysql.js +19 -19
- package/lib/instrumentation/oracle.js +15 -15
- package/lib/instrumentation/pg.js +4 -4
- package/lib/instrumentation/promise.js +46 -46
- package/lib/instrumentation/q.js +2 -2
- package/lib/instrumentation/redis.js +11 -11
- package/lib/instrumentation/restify.js +1 -1
- package/lib/instrumentation/undici.js +242 -0
- package/lib/instrumentation/vision.js +4 -4
- package/lib/instrumentation/when.js +3 -3
- package/lib/instrumentations.js +2 -1
- package/lib/logger.js +5 -5
- package/lib/metrics/index.js +15 -15
- package/lib/metrics/mapper.js +7 -7
- package/lib/metrics/normalizer/rule.js +9 -9
- package/lib/metrics/normalizer/tx_segment.js +17 -17
- package/lib/metrics/normalizer.js +22 -22
- package/lib/metrics/recorders/custom.js +5 -5
- package/lib/metrics/recorders/generic.js +3 -3
- package/lib/metrics/recorders/http.js +7 -7
- package/lib/metrics/recorders/http_external.js +7 -7
- package/lib/metrics/recorders/message-transaction.js +5 -6
- package/lib/metrics/recorders/other.js +5 -5
- package/lib/parse-proc-cpuinfo.js +25 -19
- package/lib/parse-proc-meminfo.js +8 -2
- package/lib/prioritized-attributes.js +2 -2
- package/lib/priority-queue.js +10 -10
- package/lib/reservoir.js +3 -3
- package/lib/sampler.js +26 -26
- package/lib/serverless/aws-lambda.js +8 -2
- package/lib/shim/datastore-shim.js +35 -32
- package/lib/shim/index.js +2 -2
- package/lib/shim/message-shim.js +47 -47
- package/lib/shim/promise-shim.js +1 -1
- package/lib/shim/shim.js +61 -61
- package/lib/shim/specs/index.js +3 -3
- package/lib/shim/transaction-shim.js +44 -192
- package/lib/shim/webframework-shim.js +52 -52
- package/lib/spans/span-event.js +1 -1
- package/lib/spans/streaming-span-attributes.js +1 -1
- package/lib/stats/apdex.js +2 -2
- package/lib/stats/index.js +2 -2
- package/lib/system-info.js +23 -23
- package/lib/timer.js +5 -5
- package/lib/transaction/dt-payload.js +1 -1
- package/lib/transaction/index.js +40 -40
- package/lib/transaction/name-state.js +14 -14
- package/lib/transaction/trace/exclusive-time-calculator.js +6 -6
- package/lib/transaction/trace/index.js +14 -14
- package/lib/transaction/trace/segment.js +18 -18
- package/lib/transaction/tracecontext.js +1 -1
- package/lib/transaction/tracer/index.js +53 -49
- package/lib/uninstrumented.js +7 -7
- package/lib/util/arity.js +2 -2
- package/lib/util/byte-limit.js +4 -4
- package/lib/util/cat.js +269 -24
- package/lib/util/codec.js +2 -2
- package/lib/util/copy.js +2 -2
- package/lib/util/deep-equal.js +10 -10
- package/lib/util/flatten.js +4 -4
- package/lib/util/hashes.js +14 -14
- package/lib/util/label-parser.js +17 -17
- package/lib/util/logger.js +24 -24
- package/lib/util/process-version.js +2 -2
- package/lib/util/properties.js +4 -4
- package/lib/util/sql/obfuscate.js +15 -15
- package/lib/util/stream-sink.js +3 -3
- package/lib/util/unwrapped-core.js +2 -2
- package/lib/util/urltils.js +16 -16
- package/lib/utilization/aws-info.js +7 -7
- package/lib/utilization/azure-info.js +6 -6
- package/lib/utilization/common.js +13 -13
- package/lib/utilization/docker-info.js +11 -11
- package/lib/utilization/gcp-info.js +4 -4
- package/lib/utilization/index.js +5 -5
- package/lib/utilization/pcf-info.js +9 -9
- package/package.json +13 -6
- package/stub_api.js +8 -8
|
@@ -6,31 +6,11 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const cat = require('../util/cat')
|
|
9
|
-
const hashes = require('../util/hashes')
|
|
10
9
|
const logger = require('../logger').child({ component: 'TransactionShim' })
|
|
11
10
|
const Shim = require('./shim')
|
|
12
11
|
const Transaction = require('../transaction')
|
|
13
12
|
const util = require('util')
|
|
14
13
|
|
|
15
|
-
const HTTP_CAT_ID_HEADER = 'X-NewRelic-Id'
|
|
16
|
-
const MQ_CAT_ID_HEADER = 'NewRelicID'
|
|
17
|
-
const MATCH_CAT_ID_HEADER = new RegExp(
|
|
18
|
-
'^(?:' + HTTP_CAT_ID_HEADER + '|' + MQ_CAT_ID_HEADER + ')$',
|
|
19
|
-
'i'
|
|
20
|
-
)
|
|
21
|
-
const HTTP_CAT_TRANSACTION_HEADER = 'X-NewRelic-Transaction'
|
|
22
|
-
const MQ_CAT_TRANSACTION_HEADER = 'NewRelicTransaction'
|
|
23
|
-
const MATCH_CAT_TRANSACTION_HEADER = new RegExp(
|
|
24
|
-
'^(?:' + HTTP_CAT_TRANSACTION_HEADER + '|' + MQ_CAT_TRANSACTION_HEADER + ')$',
|
|
25
|
-
'i'
|
|
26
|
-
)
|
|
27
|
-
const HTTP_CAT_APP_DATA_HEADER = 'X-NewRelic-App-Data'
|
|
28
|
-
const MQ_CAT_APP_DATA_HEADER = 'NewRelicAppData'
|
|
29
|
-
const MATCH_CAT_APP_DATA_HEADER = new RegExp(
|
|
30
|
-
'^(?:' + HTTP_CAT_APP_DATA_HEADER + '|' + MQ_CAT_APP_DATA_HEADER + ')$',
|
|
31
|
-
'i'
|
|
32
|
-
)
|
|
33
|
-
|
|
34
14
|
const TRANSACTION_TYPES_SET = Transaction.TYPES_SET
|
|
35
15
|
|
|
36
16
|
/**
|
|
@@ -88,8 +68,8 @@ TransactionShim.prototype.pushTransactionName = pushTransactionName
|
|
|
88
68
|
TransactionShim.prototype.popTransactionName = popTransactionName
|
|
89
69
|
TransactionShim.prototype.setTransactionName = setTransactionName
|
|
90
70
|
TransactionShim.prototype.handleCATHeaders = handleCATHeaders
|
|
91
|
-
TransactionShim.prototype.insertCATRequestHeaders = insertCATRequestHeaders
|
|
92
71
|
TransactionShim.prototype.insertCATReplyHeader = insertCATReplyHeader
|
|
72
|
+
TransactionShim.prototype.insertCATRequestHeaders = insertCATRequestHeaders
|
|
93
73
|
|
|
94
74
|
// -------------------------------------------------------------------------- //
|
|
95
75
|
|
|
@@ -166,7 +146,7 @@ function bindCreateTransaction(nodule, property, spec) {
|
|
|
166
146
|
|
|
167
147
|
// Is this transaction supposed to be nested? Pick the right wrapper for the
|
|
168
148
|
// job.
|
|
169
|
-
|
|
149
|
+
const makeWrapper = spec.nest ? _makeNestedTransWrapper : _makeTransWrapper
|
|
170
150
|
return makeWrapper(shim, fn, name, spec)
|
|
171
151
|
})
|
|
172
152
|
}
|
|
@@ -188,7 +168,7 @@ function bindCreateTransaction(nodule, property, spec) {
|
|
|
188
168
|
* @param {string} pathSegment - The path segment to add to the naming stack.
|
|
189
169
|
*/
|
|
190
170
|
function pushTransactionName(pathSegment) {
|
|
191
|
-
|
|
171
|
+
const tx = this.tracer.getTransaction()
|
|
192
172
|
if (tx && tx.nameState) {
|
|
193
173
|
tx.nameState.appendPath(pathSegment)
|
|
194
174
|
}
|
|
@@ -209,7 +189,7 @@ function pushTransactionName(pathSegment) {
|
|
|
209
189
|
* `pathSegment` is removed.
|
|
210
190
|
*/
|
|
211
191
|
function popTransactionName(pathSegment) {
|
|
212
|
-
|
|
192
|
+
const tx = this.tracer.getTransaction()
|
|
213
193
|
if (tx && tx.nameState) {
|
|
214
194
|
tx.nameState.popPath(pathSegment)
|
|
215
195
|
}
|
|
@@ -227,7 +207,7 @@ function popTransactionName(pathSegment) {
|
|
|
227
207
|
* @param {string} name - The name to use for the transaction.
|
|
228
208
|
*/
|
|
229
209
|
function setTransactionName(name) {
|
|
230
|
-
|
|
210
|
+
const tx = this.tracer.getTransaction()
|
|
231
211
|
if (tx) {
|
|
232
212
|
tx.setPartialName(name)
|
|
233
213
|
}
|
|
@@ -254,66 +234,46 @@ function setTransactionName(name) {
|
|
|
254
234
|
* The transport type that brought the headers. Usually `HTTP` or `HTTPS`.
|
|
255
235
|
*/
|
|
256
236
|
function handleCATHeaders(headers, segment, transportType) {
|
|
257
|
-
//
|
|
258
|
-
|
|
259
|
-
|
|
237
|
+
// TODO: rename function or replace functionality when CAT fully removed.
|
|
238
|
+
|
|
239
|
+
if (!headers) {
|
|
240
|
+
this.logger.debug('No headers for CAT or DT processing.')
|
|
260
241
|
return
|
|
261
242
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
this.logger.
|
|
243
|
+
|
|
244
|
+
const config = this.agent.config
|
|
245
|
+
|
|
246
|
+
if (!config.cross_application_tracer.enabled && !config.distributed_tracing.enabled) {
|
|
247
|
+
this.logger.trace('CAT and DT disabled, not extracting headers.')
|
|
267
248
|
return
|
|
268
249
|
}
|
|
269
250
|
|
|
270
251
|
// Check that we're in an active transaction.
|
|
271
|
-
|
|
272
|
-
if (!
|
|
273
|
-
this.logger.trace('Not
|
|
252
|
+
const currentSegment = segment || this.getSegment()
|
|
253
|
+
if (!currentSegment || !currentSegment.transaction.isActive()) {
|
|
254
|
+
this.logger.trace('Not processing headers for CAT or DT, not in an active transaction.')
|
|
274
255
|
return
|
|
275
256
|
}
|
|
276
257
|
|
|
277
|
-
const transaction =
|
|
258
|
+
const transaction = currentSegment.transaction
|
|
278
259
|
|
|
279
|
-
if (
|
|
260
|
+
if (config.distributed_tracing.enabled) {
|
|
280
261
|
transaction.acceptDistributedTraceHeaders(transportType, headers)
|
|
281
262
|
return
|
|
282
263
|
}
|
|
283
264
|
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
if (catId && transactionData && appData) {
|
|
298
|
-
break
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
if (catId && transactionData) {
|
|
303
|
-
cat.handleCatHeaders(catId, transactionData, this.agent.config.encoding_key, transaction)
|
|
304
|
-
if (transaction.incomingCatId) {
|
|
305
|
-
this.logger.trace(
|
|
306
|
-
'Got inbound CAT headers in transaction %s from %s',
|
|
307
|
-
transaction.id,
|
|
308
|
-
transaction.incomingCatId
|
|
309
|
-
)
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (appData) {
|
|
314
|
-
_handleCATReplyHeader(this, segment, appData)
|
|
315
|
-
// TODO: Handle adding ExternalTransaction metrics for this segment.
|
|
316
|
-
}
|
|
265
|
+
// Not DT so processing CAT.
|
|
266
|
+
// TODO: Below will be removed when CAT removed.
|
|
267
|
+
const { appData, id, transactionId } = cat.extractCatHeaders(headers)
|
|
268
|
+
const { externalId, externalTransaction } = cat.parseCatData(
|
|
269
|
+
id,
|
|
270
|
+
transactionId,
|
|
271
|
+
config.encoding_key
|
|
272
|
+
)
|
|
273
|
+
cat.assignCatToTransaction(externalId, externalTransaction, transaction)
|
|
274
|
+
const decodedAppData = cat.parseAppData(config, appData)
|
|
275
|
+
cat.assignCatToSegment(decodedAppData, currentSegment)
|
|
276
|
+
// TODO: Handle adding ExternalTransaction metrics for this segment.
|
|
317
277
|
}
|
|
318
278
|
|
|
319
279
|
/**
|
|
@@ -357,46 +317,7 @@ function insertCATRequestHeaders(headers, useAlternateHeaderNames) {
|
|
|
357
317
|
// TODO: Official testing and support.
|
|
358
318
|
tx.insertDistributedTraceHeaders(headers)
|
|
359
319
|
} else {
|
|
360
|
-
|
|
361
|
-
this.logger.warn('Missing encoding key, not adding CAT headers!')
|
|
362
|
-
return
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Determine the names of the headers we'll add.
|
|
366
|
-
let transHeader = HTTP_CAT_TRANSACTION_HEADER
|
|
367
|
-
let idHeader = HTTP_CAT_ID_HEADER
|
|
368
|
-
if (useAlternateHeaderNames) {
|
|
369
|
-
idHeader = MQ_CAT_ID_HEADER
|
|
370
|
-
transHeader = MQ_CAT_TRANSACTION_HEADER
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Add in the application ID.
|
|
374
|
-
if (this.agent.config.obfuscatedId) {
|
|
375
|
-
headers[idHeader] = this.agent.config.obfuscatedId
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Generate an application path hash. This is essentially a snapshot of what
|
|
379
|
-
// the transaction would be named if it ended right now.
|
|
380
|
-
const pathHash = hashes.calculatePathHash(
|
|
381
|
-
this.agent.config.applications()[0],
|
|
382
|
-
tx.getFullName(),
|
|
383
|
-
tx.referringPathHash
|
|
384
|
-
)
|
|
385
|
-
|
|
386
|
-
tx.pushPathHash(pathHash)
|
|
387
|
-
|
|
388
|
-
try {
|
|
389
|
-
const catData = hashes.obfuscateNameUsingKey(
|
|
390
|
-
JSON.stringify([tx.id, false, tx.tripId || tx.id, pathHash]),
|
|
391
|
-
this.agent.config.encoding_key
|
|
392
|
-
)
|
|
393
|
-
if (catData) {
|
|
394
|
-
headers[transHeader] = catData
|
|
395
|
-
this.logger.trace('Added CAT headers for transaction %s', tx.id)
|
|
396
|
-
}
|
|
397
|
-
} catch (e) {
|
|
398
|
-
this.logger.warn({ error: e.stack }, 'Failed to serialize CAT header!')
|
|
399
|
-
}
|
|
320
|
+
cat.addCatHeaders(this.agent.config, tx, headers, useAlternateHeaderNames)
|
|
400
321
|
}
|
|
401
322
|
}
|
|
402
323
|
|
|
@@ -417,7 +338,7 @@ function insertCATRequestHeaders(headers, useAlternateHeaderNames) {
|
|
|
417
338
|
*/
|
|
418
339
|
function insertCATReplyHeader(headers, useAlternateHeaderNames) {
|
|
419
340
|
// Is CAT enabled?
|
|
420
|
-
|
|
341
|
+
const config = this.agent.config
|
|
421
342
|
if (!config.cross_application_tracer.enabled) {
|
|
422
343
|
this.logger.trace('CAT disabled, not adding CAT reply header.')
|
|
423
344
|
return
|
|
@@ -433,100 +354,31 @@ function insertCATReplyHeader(headers, useAlternateHeaderNames) {
|
|
|
433
354
|
}
|
|
434
355
|
|
|
435
356
|
// Are we in a transaction?
|
|
436
|
-
|
|
357
|
+
const segment = this.getSegment()
|
|
437
358
|
if (!segment || !segment.transaction.isActive()) {
|
|
438
359
|
this.logger.trace('Not adding CAT reply header, not in an active transaction.')
|
|
439
360
|
return
|
|
440
361
|
}
|
|
441
|
-
|
|
362
|
+
const tx = segment.transaction
|
|
442
363
|
|
|
443
364
|
// Hunt down the content length.
|
|
444
365
|
// NOTE: In AMQP, content-type and content-encoding are guaranteed fields, but
|
|
445
366
|
// there is no content-length field or header. For that, content length will
|
|
446
367
|
// always be -1.
|
|
447
|
-
|
|
448
|
-
for (
|
|
368
|
+
let contentLength = -1
|
|
369
|
+
for (const key in headers) {
|
|
449
370
|
if (key.toLowerCase() === 'content-length') {
|
|
450
371
|
contentLength = headers[key]
|
|
451
372
|
break
|
|
452
373
|
}
|
|
453
374
|
}
|
|
454
375
|
|
|
455
|
-
|
|
456
|
-
var appData = null
|
|
457
|
-
var txName = tx.getFullName()
|
|
458
|
-
try {
|
|
459
|
-
appData = hashes.obfuscateNameUsingKey(
|
|
460
|
-
JSON.stringify([
|
|
461
|
-
config.cross_process_id,
|
|
462
|
-
txName,
|
|
463
|
-
tx.queueTime / 1000,
|
|
464
|
-
tx.catResponseTime / 1000,
|
|
465
|
-
contentLength,
|
|
466
|
-
tx.id,
|
|
467
|
-
false
|
|
468
|
-
]),
|
|
469
|
-
config.encoding_key
|
|
470
|
-
)
|
|
471
|
-
} catch (e) {
|
|
472
|
-
this.logger.warn({ error: e.stack }, 'Failed to serialize CAT data for %s', txName)
|
|
473
|
-
}
|
|
474
|
-
|
|
376
|
+
const { key, data } = cat.encodeAppData(config, tx, contentLength, useAlternateHeaderNames)
|
|
475
377
|
// Add the header.
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* Parses the given CAT response app-data and links the transaction to it.
|
|
482
|
-
*
|
|
483
|
-
* - `_handleCATReplyHeader(shim, segment, appData)`
|
|
484
|
-
*
|
|
485
|
-
* @private
|
|
486
|
-
*
|
|
487
|
-
* @param {TransactionShim} shim
|
|
488
|
-
* The shim to use in the process of extracting the app data.
|
|
489
|
-
*
|
|
490
|
-
* @param {!TraceSegment} segment
|
|
491
|
-
* The segment to attach the CAT data to.
|
|
492
|
-
*
|
|
493
|
-
* @param {string} appData
|
|
494
|
-
* The application data to parse and use.
|
|
495
|
-
*/
|
|
496
|
-
function _handleCATReplyHeader(shim, segment, appData) {
|
|
497
|
-
// Attempt to parse the app data header.
|
|
498
|
-
var config = shim.agent.config
|
|
499
|
-
try {
|
|
500
|
-
appData = JSON.parse(hashes.deobfuscateNameUsingKey(appData, config.encoding_key))
|
|
501
|
-
} catch (e) {
|
|
502
|
-
shim.logger.warn('Unparsable CAT application data header: %s', appData)
|
|
503
|
-
return
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// Make sure the app data is of the expected format and that we trust the
|
|
507
|
-
// origin application.
|
|
508
|
-
if (!appData.length || !shim.isString(appData[0])) {
|
|
509
|
-
shim.logger.trace('Unknown format for CAT application data header.')
|
|
510
|
-
return
|
|
511
|
-
}
|
|
512
|
-
var accountId = parseInt(appData[0].split('#')[0], 10)
|
|
513
|
-
var trustedIds = config.trusted_account_ids
|
|
514
|
-
if (trustedIds && trustedIds.indexOf(accountId) === -1) {
|
|
515
|
-
shim.logger.trace('CAT headers from untrusted application %s', accountId)
|
|
516
|
-
return
|
|
378
|
+
if (key && data) {
|
|
379
|
+
headers[key] = data
|
|
380
|
+
this.logger.trace('Added outbound response CAT headers for transaction %s', tx.id)
|
|
517
381
|
}
|
|
518
|
-
|
|
519
|
-
// It's good! Pull out the data we care about.
|
|
520
|
-
segment.catId = appData[0]
|
|
521
|
-
segment.catTransaction = appData[1]
|
|
522
|
-
if (appData.length >= 6) {
|
|
523
|
-
segment.addAttribute('transaction_guid', appData[5])
|
|
524
|
-
}
|
|
525
|
-
shim.logger.trace(
|
|
526
|
-
'Got inbound response CAT headers for transaction %s from %s',
|
|
527
|
-
segment.transaction.id,
|
|
528
|
-
appData[5]
|
|
529
|
-
)
|
|
530
382
|
}
|
|
531
383
|
|
|
532
384
|
/**
|
|
@@ -559,8 +411,8 @@ function _makeNestedTransWrapper(shim, fn, name, spec) {
|
|
|
559
411
|
}
|
|
560
412
|
|
|
561
413
|
// Reuse existing transactions only if the type matches.
|
|
562
|
-
|
|
563
|
-
|
|
414
|
+
let transaction = shim.tracer.getTransaction()
|
|
415
|
+
let segment = shim.tracer.segment
|
|
564
416
|
|
|
565
417
|
// Only create a new transaction if we either do not have a current
|
|
566
418
|
// transaction _or_ the current transaction is not of the type we want.
|
|
@@ -606,7 +458,7 @@ function _makeTransWrapper(shim, fn, name, spec) {
|
|
|
606
458
|
}
|
|
607
459
|
|
|
608
460
|
shim.logger.trace('Creating new %s transaction for %s', spec.type, name)
|
|
609
|
-
|
|
461
|
+
const transaction = new Transaction(shim.agent)
|
|
610
462
|
transaction.type = spec.type
|
|
611
463
|
return shim.applySegment(fn, transaction.trace.root, false, this, arguments)
|
|
612
464
|
}
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
const genericRecorder = require('../metrics/recorders/generic')
|
|
9
|
+
const logger = require('../logger.js').child({ component: 'WebFrameworkShim' })
|
|
10
|
+
const metrics = require('../metrics/names')
|
|
11
|
+
const TransactionShim = require('./transaction-shim')
|
|
12
|
+
const Shim = require('./shim')
|
|
13
|
+
const specs = require('./specs')
|
|
14
|
+
const urltils = require('../util/urltils')
|
|
15
|
+
const util = require('util')
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* An enumeration of well-known web frameworks so that new instrumentations can
|
|
@@ -25,7 +25,7 @@ var util = require('util')
|
|
|
25
25
|
* @memberof WebFrameworkShim
|
|
26
26
|
* @enum {string}
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
const FRAMEWORK_NAMES = {
|
|
29
29
|
CONNECT: 'Connect',
|
|
30
30
|
DIRECTOR: 'Director',
|
|
31
31
|
EXPRESS: 'Expressjs',
|
|
@@ -35,7 +35,7 @@ var FRAMEWORK_NAMES = {
|
|
|
35
35
|
FASTIFY: 'Fastify'
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
const MIDDLEWARE_TYPE_DETAILS = {
|
|
39
39
|
APPLICATION: { name: 'Mounted App: ', path: true, record: false },
|
|
40
40
|
ERRORWARE: { name: '', path: false, record: true },
|
|
41
41
|
MIDDLEWARE: { name: '', path: false, record: true },
|
|
@@ -44,7 +44,7 @@ var MIDDLEWARE_TYPE_DETAILS = {
|
|
|
44
44
|
ROUTER: { name: 'Router: ', path: true, record: false }
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
const MIDDLEWARE_TYPE_NAMES = {
|
|
48
48
|
APPLICATION: 'APPLICATION',
|
|
49
49
|
ERRORWARE: 'ERRORWARE',
|
|
50
50
|
MIDDLEWARE: 'MIDDLEWARE',
|
|
@@ -58,7 +58,7 @@ var MIDDLEWARE_TYPE_NAMES = {
|
|
|
58
58
|
*
|
|
59
59
|
* @private
|
|
60
60
|
*/
|
|
61
|
-
|
|
61
|
+
const TRANSACTION_INFO_KEY = '__NR_transactionInfo'
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* Constructs a shim associated with the given agent instance, specialized for
|
|
@@ -336,7 +336,7 @@ function setFramework(framework) {
|
|
|
336
336
|
* @param {string} uri - The URI path to use for the transaction.
|
|
337
337
|
*/
|
|
338
338
|
function setTransactionUri(uri) {
|
|
339
|
-
|
|
339
|
+
const tx = this.tracer.getTransaction()
|
|
340
340
|
if (!tx) {
|
|
341
341
|
return
|
|
342
342
|
}
|
|
@@ -379,7 +379,7 @@ function recordRender(nodule, properties, spec) {
|
|
|
379
379
|
})
|
|
380
380
|
|
|
381
381
|
return this.record(nodule, properties, function renderRecorder(shim, fn, name, args) {
|
|
382
|
-
|
|
382
|
+
const viewIdx = shim.normalizeIndex(args.length, spec.view)
|
|
383
383
|
if (viewIdx === null) {
|
|
384
384
|
shim.logger.debug('Invalid spec.view (%d vs %d), not recording.', spec.view, args.length)
|
|
385
385
|
return null
|
|
@@ -439,18 +439,18 @@ function wrapMiddlewareMounter(nodule, properties, spec) {
|
|
|
439
439
|
endpoint: null
|
|
440
440
|
})
|
|
441
441
|
|
|
442
|
-
|
|
442
|
+
const wrapSpec = {
|
|
443
443
|
wrapper: function wrapMounter(shim, fn, fnName) {
|
|
444
444
|
if (!shim.isFunction(fn)) {
|
|
445
445
|
return fn
|
|
446
446
|
}
|
|
447
447
|
|
|
448
448
|
return function wrappedMounter() {
|
|
449
|
-
|
|
449
|
+
const args = shim.argsToArray.apply(shim, arguments)
|
|
450
450
|
|
|
451
451
|
// Normalize the route index and pull out the route argument if provided.
|
|
452
|
-
|
|
453
|
-
|
|
452
|
+
let routeIdx = null
|
|
453
|
+
let route = null
|
|
454
454
|
if (shim.isNumber(spec.route)) {
|
|
455
455
|
routeIdx = shim.normalizeIndex(args.length, spec.route)
|
|
456
456
|
route = routeIdx === null ? null : args[routeIdx]
|
|
@@ -479,7 +479,7 @@ function wrapMiddlewareMounter(nodule, properties, spec) {
|
|
|
479
479
|
|
|
480
480
|
// Some platforms accept an arbitrarily nested array of middlewares,
|
|
481
481
|
// so if this argument is an array we must recurse into it.
|
|
482
|
-
|
|
482
|
+
const middleware = middlewares[i]
|
|
483
483
|
if (middleware instanceof Array) {
|
|
484
484
|
_wrapMiddlewares(null, middleware)
|
|
485
485
|
continue
|
|
@@ -536,8 +536,8 @@ function recordMiddleware(nodule, properties, spec) {
|
|
|
536
536
|
}
|
|
537
537
|
spec = spec || Object.create(null)
|
|
538
538
|
|
|
539
|
-
|
|
540
|
-
|
|
539
|
+
const mwSpec = new specs.MiddlewareSpec(spec)
|
|
540
|
+
const wrapSpec = new specs.WrapSpec(function wrapMiddleware(shim, middleware) {
|
|
541
541
|
return _recordMiddleware(shim, middleware, mwSpec)
|
|
542
542
|
})
|
|
543
543
|
|
|
@@ -582,7 +582,7 @@ function recordParamware(nodule, properties, spec) {
|
|
|
582
582
|
}
|
|
583
583
|
spec = spec || Object.create(null)
|
|
584
584
|
|
|
585
|
-
|
|
585
|
+
const mwSpec = new specs.MiddlewareSpec(spec)
|
|
586
586
|
if (spec && this.isString(spec.name)) {
|
|
587
587
|
mwSpec.route = '[param handler :' + spec.name + ']'
|
|
588
588
|
} else {
|
|
@@ -590,7 +590,7 @@ function recordParamware(nodule, properties, spec) {
|
|
|
590
590
|
}
|
|
591
591
|
mwSpec.type = MIDDLEWARE_TYPE_NAMES.PARAMWARE
|
|
592
592
|
|
|
593
|
-
|
|
593
|
+
const wrapSpec = new specs.WrapSpec(function wrapParamware(shim, middleware, name) {
|
|
594
594
|
mwSpec.name = name
|
|
595
595
|
return _recordMiddleware(shim, middleware, mwSpec)
|
|
596
596
|
})
|
|
@@ -618,7 +618,7 @@ function recordParamware(nodule, properties, spec) {
|
|
|
618
618
|
* @see WebFrameworkShim#setErrorPredicate
|
|
619
619
|
*/
|
|
620
620
|
function noticeError(req, err) {
|
|
621
|
-
|
|
621
|
+
const txInfo = _getTransactionInfo(this, req)
|
|
622
622
|
if (txInfo && _isError(this, err)) {
|
|
623
623
|
_noticeError(this, txInfo, err)
|
|
624
624
|
}
|
|
@@ -636,7 +636,7 @@ function noticeError(req, err) {
|
|
|
636
636
|
* @see WebFrameworkShim#setErrorPredicate
|
|
637
637
|
*/
|
|
638
638
|
function errorHandled(req, err) {
|
|
639
|
-
|
|
639
|
+
const txInfo = _getTransactionInfo(this, req)
|
|
640
640
|
if (txInfo && txInfo.error === err) {
|
|
641
641
|
txInfo.errorHandled = true
|
|
642
642
|
}
|
|
@@ -667,7 +667,7 @@ function setErrorPredicate(pred) {
|
|
|
667
667
|
* @param {Request} req - The request which caused the error.
|
|
668
668
|
*/
|
|
669
669
|
function savePossibleTransactionName(req) {
|
|
670
|
-
|
|
670
|
+
const txInfo = _getTransactionInfo(this, req)
|
|
671
671
|
if (txInfo && txInfo.transaction) {
|
|
672
672
|
txInfo.transaction.nameState.markPath()
|
|
673
673
|
}
|
|
@@ -696,7 +696,7 @@ function setResponsePredicate(pred) {
|
|
|
696
696
|
* An object with key-value pairs.
|
|
697
697
|
*/
|
|
698
698
|
function captureUrlParams(params) {
|
|
699
|
-
|
|
699
|
+
const segment = this.getSegment()
|
|
700
700
|
if (segment && !this.agent.config.high_security) {
|
|
701
701
|
urltils.copyParameters(params, segment.parameters)
|
|
702
702
|
}
|
|
@@ -808,8 +808,8 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
808
808
|
return segmentName
|
|
809
809
|
}
|
|
810
810
|
|
|
811
|
-
|
|
812
|
-
|
|
811
|
+
const isErrorWare = spec.type === MIDDLEWARE_TYPE_NAMES.ERRORWARE
|
|
812
|
+
const getReq = shim.isFunction(spec.req) ? spec.req : _makeGetReq(shim, spec.req)
|
|
813
813
|
|
|
814
814
|
return shim.record(
|
|
815
815
|
middleware,
|
|
@@ -821,10 +821,10 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
821
821
|
const route = getRoute()
|
|
822
822
|
|
|
823
823
|
// Pull out the request object.
|
|
824
|
-
|
|
824
|
+
const req = getReq.call(this, shim, fn, fnName, args)
|
|
825
825
|
|
|
826
826
|
// Fetch the transaction information from that request.
|
|
827
|
-
|
|
827
|
+
const txInfo = _getTransactionInfo(shim, req)
|
|
828
828
|
if (!txInfo || !txInfo.transaction) {
|
|
829
829
|
shim.logger.debug(
|
|
830
830
|
{ txInfo: txInfo },
|
|
@@ -838,14 +838,14 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
838
838
|
txInfo.errorHandled |= isErrorWare
|
|
839
839
|
|
|
840
840
|
// Copy over route parameters onto the transaction root.
|
|
841
|
-
|
|
841
|
+
const params = shim.agent.config.high_security
|
|
842
842
|
? null
|
|
843
843
|
: spec.params.call(this, shim, fn, fnName, args, req)
|
|
844
844
|
|
|
845
845
|
// Wrap up `next` and push on our name state if we find it. We only want to
|
|
846
846
|
// push the name state if there is a next so that we can safely remove it
|
|
847
847
|
// if context leaves this middleware.
|
|
848
|
-
|
|
848
|
+
let nextWrapper = null
|
|
849
849
|
if (shim.isFunction(spec.next)) {
|
|
850
850
|
const nextDetails = {
|
|
851
851
|
route,
|
|
@@ -857,7 +857,7 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
857
857
|
|
|
858
858
|
nextWrapper = _makeNextBinder(nextDetails, txInfo)
|
|
859
859
|
} else {
|
|
860
|
-
|
|
860
|
+
const nextIdx = shim.normalizeIndex(args.length, spec.next)
|
|
861
861
|
if (nextIdx !== null && args[nextIdx] instanceof Function) {
|
|
862
862
|
const nextDetails = {
|
|
863
863
|
route,
|
|
@@ -880,9 +880,9 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
880
880
|
}
|
|
881
881
|
|
|
882
882
|
// ...and possibly construct a recorder
|
|
883
|
-
|
|
883
|
+
let recorder = null
|
|
884
884
|
if (typeDetails.record) {
|
|
885
|
-
|
|
885
|
+
const stackPath = txInfo.transaction.nameState.getPath() || ''
|
|
886
886
|
recorder = _makeMiddlewareRecorder(shim, metricName + '/' + stackPath)
|
|
887
887
|
}
|
|
888
888
|
|
|
@@ -896,7 +896,7 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
896
896
|
recorder: recorder,
|
|
897
897
|
parameters: params,
|
|
898
898
|
after: function afterExec(shim, _fn, _name, err) {
|
|
899
|
-
|
|
899
|
+
const errIsError = _isError(shim, err)
|
|
900
900
|
if (errIsError) {
|
|
901
901
|
_noticeError(shim, txInfo, err)
|
|
902
902
|
} else if (!nextWrapper && !isErrorWare && spec.appendPath) {
|
|
@@ -913,10 +913,10 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
913
913
|
const route = getRoute()
|
|
914
914
|
|
|
915
915
|
// Pull out the request object.
|
|
916
|
-
|
|
916
|
+
const req = getReq.call(this, shim, fn, fnName, args)
|
|
917
917
|
|
|
918
918
|
// Fetch the transaction information from that request.
|
|
919
|
-
|
|
919
|
+
const txInfo = _getTransactionInfo(shim, req)
|
|
920
920
|
if (!txInfo || !txInfo.transaction) {
|
|
921
921
|
shim.logger.debug(
|
|
922
922
|
{ txInfo: txInfo },
|
|
@@ -930,7 +930,7 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
930
930
|
txInfo.errorHandled |= isErrorWare
|
|
931
931
|
|
|
932
932
|
// Copy over route parameters onto the transaction root.
|
|
933
|
-
|
|
933
|
+
const params = shim.agent.config.high_security
|
|
934
934
|
? null
|
|
935
935
|
: spec.params.call(this, shim, fn, fnName, args, req)
|
|
936
936
|
|
|
@@ -938,9 +938,9 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
938
938
|
if (spec.appendPath) {
|
|
939
939
|
txInfo.transaction.nameState.appendPath(route, params)
|
|
940
940
|
}
|
|
941
|
-
|
|
941
|
+
let recorder = null
|
|
942
942
|
if (typeDetails.record) {
|
|
943
|
-
|
|
943
|
+
const stackPath = txInfo.transaction.nameState.getPath() || ''
|
|
944
944
|
recorder = _makeMiddlewareRecorder(shim, metricName + '/' + stackPath)
|
|
945
945
|
}
|
|
946
946
|
|
|
@@ -949,7 +949,7 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
949
949
|
// path for the current executing middleware, then readd it once the
|
|
950
950
|
// next callback is done (either asynchronously or after the
|
|
951
951
|
// returned promise is resolved).
|
|
952
|
-
|
|
952
|
+
let nextWrapper = function pushSegment(shim, _fn, _name, segment) {
|
|
953
953
|
txInfo.segmentStack.push(segment)
|
|
954
954
|
}
|
|
955
955
|
if (shim.isFunction(spec.next)) {
|
|
@@ -962,7 +962,7 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
962
962
|
}
|
|
963
963
|
nextWrapper = _makeNextBinder(nextDetails, txInfo)
|
|
964
964
|
} else {
|
|
965
|
-
|
|
965
|
+
const nextIdx = shim.normalizeIndex(args.length, spec.next)
|
|
966
966
|
if (nextIdx !== null && args[nextIdx] instanceof Function) {
|
|
967
967
|
const nextDetails = {
|
|
968
968
|
route,
|
|
@@ -1009,7 +1009,7 @@ function _recordMiddleware(shim, middleware, spec) {
|
|
|
1009
1009
|
|
|
1010
1010
|
function _makeGetReq(shim, req) {
|
|
1011
1011
|
return function getReqFromArgs(shim, fn, name, args) {
|
|
1012
|
-
|
|
1012
|
+
const reqIdx = shim.normalizeIndex(args.length, req)
|
|
1013
1013
|
if (reqIdx === null || !args[reqIdx]) {
|
|
1014
1014
|
shim.logger.debug('Can not find request parameter, not recording.')
|
|
1015
1015
|
return null
|
|
@@ -1048,7 +1048,7 @@ function _makeNextBinder(nextDetails, txInfo) {
|
|
|
1048
1048
|
txInfo.segmentStack.pop()
|
|
1049
1049
|
segment.end()
|
|
1050
1050
|
}
|
|
1051
|
-
|
|
1051
|
+
const ret = original.apply(this, arguments)
|
|
1052
1052
|
|
|
1053
1053
|
if (nextDetails.isPromise && shim.isPromise(ret)) {
|
|
1054
1054
|
// After the next call has resolved, we should reinstate the
|
|
@@ -1104,9 +1104,9 @@ function _getTransactionInfo(shim, req) {
|
|
|
1104
1104
|
*/
|
|
1105
1105
|
function _makeMiddlewareRecorder(shim, metricName) {
|
|
1106
1106
|
return function middlewareMetricRecorder(segment, scope) {
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1107
|
+
const duration = segment.getDurationInMillis()
|
|
1108
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
1109
|
+
const transaction = segment.transaction
|
|
1110
1110
|
|
|
1111
1111
|
if (scope) {
|
|
1112
1112
|
transaction.measure(metricName, scope, duration, exclusive)
|
|
@@ -1163,10 +1163,10 @@ function _isError(shim, err) {
|
|
|
1163
1163
|
* The spec object the values are coming from
|
|
1164
1164
|
*/
|
|
1165
1165
|
function _copyExpectedSpecParameters(destination, source) {
|
|
1166
|
-
|
|
1166
|
+
const keys = ['matchArity']
|
|
1167
1167
|
|
|
1168
|
-
for (
|
|
1169
|
-
|
|
1168
|
+
for (let i = 0; i < keys.length; ++i) {
|
|
1169
|
+
const key = keys[i]
|
|
1170
1170
|
if (source[key] != null) {
|
|
1171
1171
|
destination[key] = source[key]
|
|
1172
1172
|
}
|