newrelic 7.5.2 → 8.3.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 +4989 -4886
- package/THIRD_PARTY_NOTICES.md +625 -216
- package/api.js +105 -174
- package/bin/test-naming-rules.js +38 -32
- package/bin/tracetractor +0 -1
- package/index.js +12 -18
- package/lib/agent.js +108 -111
- package/lib/aggregators/base-aggregator.js +1 -1
- package/lib/aggregators/event-aggregator.js +6 -6
- package/lib/attributes.js +12 -13
- package/lib/collector/api.js +32 -42
- package/lib/collector/facts.js +67 -65
- package/lib/collector/http-agents.js +30 -27
- package/lib/collector/parse-response.js +1 -2
- package/lib/collector/remote-method.js +43 -36
- package/lib/collector/serverless.js +13 -18
- package/lib/collector/ssl/certificates.js +1056 -1056
- package/lib/config/attribute-filter.js +90 -82
- package/lib/config/default.js +30 -18
- package/lib/config/env.js +17 -12
- package/lib/config/harvest-config-validator.js +1 -1
- package/lib/config/index.js +160 -177
- package/lib/config/merge-server-config.js +7 -5
- package/lib/custom-events/custom-event-aggregator.js +1 -1
- package/lib/db/parse-sql.js +6 -9
- package/lib/db/parsed-statement.js +6 -13
- package/lib/db/query-parsers/sql.js +6 -9
- package/lib/db/query-sample.js +7 -3
- package/lib/db/query-trace-aggregator.js +12 -12
- package/lib/db/utils.js +1 -1
- package/lib/environment.js +173 -138
- package/lib/errors/error-collector.js +18 -31
- package/lib/errors/error-event-aggregator.js +1 -1
- package/lib/errors/error-trace-aggregator.js +2 -3
- package/lib/errors/helper.js +21 -30
- package/lib/errors/index.js +16 -28
- package/lib/feature_flags.js +5 -8
- package/lib/grpc/connection/states.js +6 -6
- package/lib/grpc/connection.js +35 -46
- package/lib/header-attributes.js +49 -53
- package/lib/instrumentation/amqplib.js +8 -17
- package/lib/instrumentation/bluebird.js +61 -20
- package/lib/instrumentation/cassandra-driver.js +2 -2
- package/lib/instrumentation/connect.js +4 -3
- package/lib/instrumentation/core/async_hooks.js +11 -4
- package/lib/instrumentation/core/child_process.js +20 -28
- package/lib/instrumentation/core/crypto.js +1 -7
- package/lib/instrumentation/core/dns.js +3 -7
- package/lib/instrumentation/core/domain.js +2 -8
- package/lib/instrumentation/core/fs.js +22 -37
- package/lib/instrumentation/core/globals.js +3 -7
- package/lib/instrumentation/core/http-outbound.js +15 -40
- package/lib/instrumentation/core/http.js +29 -63
- package/lib/instrumentation/core/inspector.js +6 -10
- package/lib/instrumentation/core/net.js +3 -1
- package/lib/instrumentation/core/timers.js +17 -24
- package/lib/instrumentation/core/zlib.js +2 -10
- package/lib/instrumentation/express.js +4 -2
- package/lib/instrumentation/fastify/spec-builders.js +5 -0
- package/lib/instrumentation/fastify.js +37 -10
- package/lib/instrumentation/hapi/hapi-17.js +9 -10
- package/lib/instrumentation/hapi.js +15 -15
- package/lib/instrumentation/ioredis.js +1 -2
- package/lib/instrumentation/memcached.js +39 -43
- package/lib/instrumentation/mongodb/common.js +218 -0
- package/lib/instrumentation/mongodb/constants.js +87 -0
- package/lib/instrumentation/mongodb/v2-mongo.js +110 -0
- package/lib/instrumentation/mongodb/v3-mongo.js +80 -0
- package/lib/instrumentation/mongodb/v4-mongo.js +90 -0
- package/lib/instrumentation/mongodb.js +20 -312
- package/lib/instrumentation/mysql.js +33 -26
- package/lib/instrumentation/oracle.js +10 -14
- package/lib/instrumentation/pg.js +30 -21
- package/lib/instrumentation/promise.js +20 -17
- package/lib/instrumentation/redis.js +30 -30
- package/lib/instrumentation/when.js +9 -1
- package/lib/instrumentations.js +24 -24
- package/lib/logger.js +1 -1
- package/lib/metrics/index.js +37 -17
- package/lib/metrics/mapper.js +9 -9
- package/lib/metrics/metric-aggregator.js +5 -10
- package/lib/metrics/names.js +8 -7
- package/lib/metrics/normalizer/rule.js +6 -7
- package/lib/metrics/normalizer/tx_segment.js +17 -13
- package/lib/metrics/normalizer.js +30 -33
- package/lib/metrics/recorders/custom.js +3 -1
- package/lib/metrics/recorders/distributed-trace.js +3 -18
- package/lib/metrics/recorders/generic.js +3 -2
- package/lib/metrics/recorders/http.js +4 -6
- package/lib/metrics/recorders/http_external.js +1 -3
- package/lib/metrics/recorders/message-transaction.js +2 -12
- package/lib/metrics/recorders/other.js +2 -12
- package/lib/parse-proc-cpuinfo.js +11 -16
- package/lib/parse-proc-meminfo.js +5 -3
- package/lib/prioritized-attributes.js +12 -17
- package/lib/priority-queue.js +1 -1
- package/lib/proxy/grpc.js +1 -1
- package/lib/reservoir.js +9 -3
- package/lib/sampler.js +12 -13
- package/lib/serverless/api-gateway.js +3 -3
- package/lib/serverless/aws-lambda.js +28 -37
- package/lib/shim/conglomerate-shim.js +4 -4
- package/lib/shim/datastore-shim.js +29 -38
- package/lib/shim/index.js +8 -9
- package/lib/shim/message-shim.js +111 -113
- package/lib/shim/promise-shim.js +18 -13
- package/lib/shim/shim.js +72 -66
- package/lib/shim/specs/index.js +18 -19
- package/lib/shim/transaction-shim.js +26 -36
- package/lib/shim/webframework-shim.js +25 -35
- package/lib/shimmer.js +184 -166
- package/lib/spans/create-span-event-aggregator.js +24 -44
- package/lib/spans/span-context.js +4 -10
- package/lib/spans/span-event-aggregator.js +68 -13
- package/lib/spans/span-event.js +5 -7
- package/lib/spans/span-streamer.js +10 -18
- package/lib/spans/streaming-span-event-aggregator.js +1 -1
- package/lib/spans/streaming-span-event.js +4 -4
- package/lib/stats/apdex.js +5 -11
- package/lib/stats/index.js +12 -17
- package/lib/system-info.js +7 -3
- package/lib/timer.js +30 -16
- package/lib/transaction/dt-payload.js +1 -1
- package/lib/transaction/handle.js +19 -19
- package/lib/transaction/index.js +94 -112
- package/lib/transaction/name-state.js +5 -6
- package/lib/transaction/trace/aggregator.js +78 -73
- package/lib/transaction/trace/exclusive-time-calculator.js +5 -9
- package/lib/transaction/trace/index.js +26 -24
- package/lib/transaction/trace/segment.js +39 -56
- package/lib/transaction/tracecontext.js +37 -45
- package/lib/transaction/tracer/index.js +79 -44
- package/lib/transaction/transaction-event-aggregator.js +29 -31
- package/lib/uninstrumented.js +4 -5
- package/lib/util/attribute-types.js +1 -5
- package/lib/util/byte-limit.js +0 -1
- package/lib/util/cat.js +5 -13
- package/lib/util/codec.js +8 -4
- package/lib/util/deep-equal.js +48 -18
- package/lib/util/flatten.js +5 -2
- package/lib/util/hashes.js +2 -2
- package/lib/util/label-parser.js +7 -13
- package/lib/util/logger.js +31 -13
- package/lib/util/process-version.js +1 -1
- package/lib/util/properties.js +1 -1
- package/lib/util/sql/obfuscate.js +7 -17
- package/lib/util/stream-sink.js +2 -3
- package/lib/util/urltils.js +9 -13
- package/lib/utilization/aws-info.js +2 -3
- package/lib/utilization/azure-info.js +32 -30
- package/lib/utilization/common.js +5 -4
- package/lib/utilization/docker-info.js +4 -6
- package/lib/utilization/gcp-info.js +36 -35
- package/lib/utilization/index.js +1 -1
- package/lib/utilization/kubernetes-info.js +2 -2
- package/lib/utilization/pcf-info.js +4 -4
- package/package.json +32 -18
- package/stub_api.js +8 -6
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
const logger = require('../logger').child({component: 'TraceContext'})
|
|
8
|
+
const logger = require('../logger').child({ component: 'TraceContext' })
|
|
9
9
|
const hashes = require('../util/hashes')
|
|
10
10
|
|
|
11
11
|
const TRACE_CONTEXT_PARENT_HEADER = 'traceparent'
|
|
@@ -89,8 +89,8 @@ class TraceContext {
|
|
|
89
89
|
if (!accountId || !appId || !trustedAccountKey) {
|
|
90
90
|
logger.debug(
|
|
91
91
|
'Unable to create tracestate header due to missing required fields ' +
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
'(account_id: %s, primary_application_id: %s, trusted_account_key: %s) in transaction %s' +
|
|
93
|
+
'This may occur if a trace is created prior to the agent fully starting.',
|
|
94
94
|
accountId,
|
|
95
95
|
appId,
|
|
96
96
|
trustedAccountKey,
|
|
@@ -122,7 +122,8 @@ class TraceContext {
|
|
|
122
122
|
const priority = this.transaction.priority ? this.transaction.priority.toFixed(6) : ''
|
|
123
123
|
const timestamp = Date.now()
|
|
124
124
|
|
|
125
|
-
const nrTraceState =
|
|
125
|
+
const nrTraceState =
|
|
126
|
+
`${trustedAccountKey}@nr=${version}-${parentType}-${accountId}` +
|
|
126
127
|
`-${appId}-${spanId}-${transactionId}-${sampled}-${priority}-${timestamp}`
|
|
127
128
|
|
|
128
129
|
if (this._traceStateRaw) {
|
|
@@ -220,15 +221,9 @@ class TraceContext {
|
|
|
220
221
|
traceContextData.traceId = parsedParent.traceId
|
|
221
222
|
traceContextData.parentSpanId = parsedParent.parentId
|
|
222
223
|
} else {
|
|
223
|
-
logger.trace(
|
|
224
|
-
'Invalid traceparent for transaction %s: %s',
|
|
225
|
-
this.transaction.id,
|
|
226
|
-
traceparent
|
|
227
|
-
)
|
|
224
|
+
logger.trace('Invalid traceparent for transaction %s: %s', this.transaction.id, traceparent)
|
|
228
225
|
|
|
229
|
-
this.transaction.agent.recordSupportability(
|
|
230
|
-
'TraceContext/TraceParent/Parse/Exception'
|
|
231
|
-
)
|
|
226
|
+
this.transaction.agent.recordSupportability('TraceContext/TraceParent/Parse/Exception')
|
|
232
227
|
// From the W3C spec: If the vendor failed to parse traceparent, it MUST NOT
|
|
233
228
|
// attempt to parse tracestate
|
|
234
229
|
return traceContextData
|
|
@@ -246,10 +241,7 @@ class TraceContext {
|
|
|
246
241
|
const parsedState = this._validateAndParseTraceStateHeader(tracestate)
|
|
247
242
|
|
|
248
243
|
if (!parsedState.traceStateValid) {
|
|
249
|
-
logger.trace('Invalid tracestate for transaction %s: %s',
|
|
250
|
-
this.transaction.id,
|
|
251
|
-
tracestate
|
|
252
|
-
)
|
|
244
|
+
logger.trace('Invalid tracestate for transaction %s: %s', this.transaction.id, tracestate)
|
|
253
245
|
|
|
254
246
|
this.transaction.agent.recordSupportability('TraceContext/TraceState/Parse/Exception')
|
|
255
247
|
return traceContextData
|
|
@@ -261,10 +253,7 @@ class TraceContext {
|
|
|
261
253
|
// These need to be kept to be added to root span events as an attribute
|
|
262
254
|
this.tracingVendors = parsedState.vendors
|
|
263
255
|
|
|
264
|
-
if (
|
|
265
|
-
parsedState.intrinsics &&
|
|
266
|
-
parsedState.intrinsics.version !== NR_TRACESTATE_VERSION
|
|
267
|
-
) {
|
|
256
|
+
if (parsedState.intrinsics && parsedState.intrinsics.version !== NR_TRACESTATE_VERSION) {
|
|
268
257
|
logger.trace(
|
|
269
258
|
'Incoming tracestate version: %s, agent tracestate version: %s',
|
|
270
259
|
parsedState.intrinsics.version,
|
|
@@ -282,20 +271,19 @@ class TraceContext {
|
|
|
282
271
|
traceContextData.transactionId = parsedState.intrinsics.transactionId
|
|
283
272
|
traceContextData.sampled = parsedState.intrinsics.sampled
|
|
284
273
|
traceContextData.priority = parsedState.intrinsics.priority
|
|
285
|
-
traceContextData.transportDuration =
|
|
286
|
-
|
|
274
|
+
traceContextData.transportDuration = Math.max(
|
|
275
|
+
0,
|
|
276
|
+
(Date.now() - parsedState.intrinsics.timestamp) / 1000
|
|
277
|
+
)
|
|
287
278
|
|
|
288
279
|
this.trustedParentId = parsedState.intrinsics.spanId
|
|
289
280
|
this._traceStateRaw = parsedState.newTraceState
|
|
290
281
|
|
|
291
282
|
this.transaction.agent.recordSupportability('TraceContext/Accept/Success')
|
|
292
283
|
} else if (parsedState.entryFound) {
|
|
293
|
-
logger.error('Invalid tracestate for transaction %s: %s',
|
|
294
|
-
this.transaction.id, tracestate)
|
|
284
|
+
logger.error('Invalid tracestate for transaction %s: %s', this.transaction.id, tracestate)
|
|
295
285
|
|
|
296
|
-
this.transaction.agent.recordSupportability(
|
|
297
|
-
'TraceContext/TraceState/InvalidNrEntry'
|
|
298
|
-
)
|
|
286
|
+
this.transaction.agent.recordSupportability('TraceContext/TraceState/InvalidNrEntry')
|
|
299
287
|
}
|
|
300
288
|
|
|
301
289
|
return traceContextData
|
|
@@ -405,8 +393,8 @@ class TraceContext {
|
|
|
405
393
|
if (!hasTrustKey) {
|
|
406
394
|
logger.debug(
|
|
407
395
|
'Unable to accept any New Relic tracestate list members. ' +
|
|
408
|
-
|
|
409
|
-
|
|
396
|
+
'Missing trusted_account_key. ' +
|
|
397
|
+
'This may occur if a trace is received prior to the agent fully starting.'
|
|
410
398
|
)
|
|
411
399
|
|
|
412
400
|
this.transaction.agent.recordSupportability('TraceContext/TraceState/Accept/Exception')
|
|
@@ -429,14 +417,15 @@ class TraceContext {
|
|
|
429
417
|
if (listMemberParts.length !== 2) {
|
|
430
418
|
tsd.traceStateValid = false
|
|
431
419
|
logger.debug('Unable to parse tracestate list members.')
|
|
432
|
-
this.transaction.agent
|
|
433
|
-
|
|
420
|
+
this.transaction.agent.recordSupportability(
|
|
421
|
+
'TraceContext/TraceState/Parse/Exception/ListMember'
|
|
422
|
+
)
|
|
434
423
|
|
|
435
424
|
return tsd
|
|
436
425
|
}
|
|
437
426
|
|
|
438
427
|
const [vendorKey, vendorValue] = listMemberParts
|
|
439
|
-
if (hasTrustKey &&
|
|
428
|
+
if (hasTrustKey && vendorKey === expectedNrKey) {
|
|
440
429
|
// Matching members do not get added to vendors.
|
|
441
430
|
// We'll replace the first valid entry and drop the rest
|
|
442
431
|
// (which would be invalid members if they exist).
|
|
@@ -510,18 +499,17 @@ class TraceContext {
|
|
|
510
499
|
const intrinsics = this._parseIntrinsics(nrTracestateValue)
|
|
511
500
|
|
|
512
501
|
// Functions that return true when the field is invalid
|
|
513
|
-
const isNull = v => v == null
|
|
502
|
+
const isNull = (v) => v == null
|
|
514
503
|
const intrinsicInvalidations = {
|
|
515
|
-
version: isNaN,
|
|
504
|
+
version: isNaN, // required, int
|
|
516
505
|
parentType: isNull, // required, str
|
|
517
|
-
accountId: isNull,
|
|
518
|
-
appId: isNull,
|
|
519
|
-
sampled:
|
|
520
|
-
priority: v => v == null ? false : isNaN(v), // not required, float
|
|
521
|
-
timestamp: isNaN
|
|
506
|
+
accountId: isNull, // required, str
|
|
507
|
+
appId: isNull, // required, str
|
|
508
|
+
sampled: (v) => (v == null ? false : isNaN(v)), // not required, int
|
|
509
|
+
priority: (v) => (v == null ? false : isNaN(v)), // not required, float
|
|
510
|
+
timestamp: isNaN // required, int
|
|
522
511
|
}
|
|
523
512
|
|
|
524
|
-
|
|
525
513
|
// If a field is found invalid, flag the entry as not valid
|
|
526
514
|
intrinsics.entryValid = true
|
|
527
515
|
for (const key of Object.keys(intrinsicInvalidations)) {
|
|
@@ -538,7 +526,9 @@ class TraceContext {
|
|
|
538
526
|
}
|
|
539
527
|
|
|
540
528
|
intrinsics.parentType = PARENT_TYPES[intrinsics.parentType]
|
|
541
|
-
if (!intrinsics.parentType)
|
|
529
|
+
if (!intrinsics.parentType) {
|
|
530
|
+
intrinsics.entryValid = false
|
|
531
|
+
}
|
|
542
532
|
|
|
543
533
|
return intrinsics
|
|
544
534
|
}
|
|
@@ -554,10 +544,10 @@ class TraceContext {
|
|
|
554
544
|
parentType: parseInt,
|
|
555
545
|
|
|
556
546
|
// these two can be null, don't try to parse a null
|
|
557
|
-
sampled: v => v == null ? v : parseInt(v, 10),
|
|
558
|
-
priority: v => v == null ? v : parseFloat(v),
|
|
547
|
+
sampled: (v) => (v == null ? v : parseInt(v, 10)),
|
|
548
|
+
priority: (v) => (v == null ? v : parseFloat(v)),
|
|
559
549
|
|
|
560
|
-
timestamp: parseInt
|
|
550
|
+
timestamp: parseInt
|
|
561
551
|
}
|
|
562
552
|
|
|
563
553
|
for (const key of Object.keys(intrinsicConversions)) {
|
|
@@ -575,7 +565,9 @@ class TraceContext {
|
|
|
575
565
|
|
|
576
566
|
// convert empty strings to null
|
|
577
567
|
splitValues.forEach((value, i) => {
|
|
578
|
-
if (value === '')
|
|
568
|
+
if (value === '') {
|
|
569
|
+
splitValues[i] = null
|
|
570
|
+
}
|
|
579
571
|
})
|
|
580
572
|
|
|
581
573
|
const intrinsics = {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
var Transaction = require('../index.js')
|
|
9
|
-
var logger = require('../../logger').child({component: 'tracer'})
|
|
9
|
+
var logger = require('../../logger').child({ component: 'tracer' })
|
|
10
10
|
|
|
11
11
|
/*
|
|
12
12
|
* CONSTANTS
|
|
@@ -14,11 +14,12 @@ var logger = require('../../logger').child({component: 'tracer'})
|
|
|
14
14
|
var ORIGINAL = '__NR_original'
|
|
15
15
|
var SEGMENT = '__NR_segment'
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
module.exports = Tracer
|
|
19
18
|
|
|
20
19
|
function Tracer(agent) {
|
|
21
|
-
if (!agent)
|
|
20
|
+
if (!agent) {
|
|
21
|
+
throw new Error('Must be initialized with an agent.')
|
|
22
|
+
}
|
|
22
23
|
|
|
23
24
|
this.agent = agent
|
|
24
25
|
this._segment = null
|
|
@@ -51,7 +52,7 @@ Object.defineProperty(Tracer.prototype, 'segment', {
|
|
|
51
52
|
set: function segmentSetter(segment) {
|
|
52
53
|
this._segment && this._segment.probe('Segment removed from tracer')
|
|
53
54
|
segment && segment.probe('Set tracer.segment')
|
|
54
|
-
return this._segment = segment
|
|
55
|
+
return (this._segment = segment)
|
|
55
56
|
}
|
|
56
57
|
})
|
|
57
58
|
|
|
@@ -74,10 +75,14 @@ function getSpanContext() {
|
|
|
74
75
|
function createSegment(name, recorder, _parent) {
|
|
75
76
|
var parent = _parent || this.segment
|
|
76
77
|
if (!parent || !parent.transaction.isActive()) {
|
|
77
|
-
logger.trace(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
logger.trace(
|
|
79
|
+
{
|
|
80
|
+
hasParent: !!parent,
|
|
81
|
+
transactionActive: parent && parent.transaction.isActive()
|
|
82
|
+
},
|
|
83
|
+
'Not creating segment %s, no parent or active transaction available.',
|
|
84
|
+
name
|
|
85
|
+
)
|
|
81
86
|
return null
|
|
82
87
|
}
|
|
83
88
|
return parent.add(name, recorder)
|
|
@@ -95,7 +100,9 @@ function addSegment(name, recorder, parent, full, task) {
|
|
|
95
100
|
|
|
96
101
|
function transactionProxy(handler) {
|
|
97
102
|
// if there's no handler, there's nothing to proxy.
|
|
98
|
-
if (typeof handler !== 'function')
|
|
103
|
+
if (typeof handler !== 'function') {
|
|
104
|
+
return handler
|
|
105
|
+
}
|
|
99
106
|
|
|
100
107
|
var tracer = this
|
|
101
108
|
var wrapped = function wrapTransactionInvocation() {
|
|
@@ -110,16 +117,18 @@ function transactionProxy(handler) {
|
|
|
110
117
|
segment.probe('!!! Nested transaction creation !!!')
|
|
111
118
|
segment.transaction.traceFlag = true // Will log the stacks when it ends.
|
|
112
119
|
}
|
|
113
|
-
logger.warn(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
logger.warn(
|
|
121
|
+
{
|
|
122
|
+
transaction: { id: segment.transaction.id, name: segment.transaction.getName() },
|
|
123
|
+
segment: segment.name
|
|
124
|
+
},
|
|
125
|
+
'Active transaction when creating non-nested transaction'
|
|
126
|
+
)
|
|
117
127
|
tracer.agent.recordSupportability('Nodejs/Transactions/Nested')
|
|
118
128
|
return handler.apply(this, arguments)
|
|
119
129
|
}
|
|
120
130
|
var transaction = new Transaction(tracer.agent)
|
|
121
|
-
return tracer.bindFunction(handler, transaction.trace.root, true)
|
|
122
|
-
.apply(this, arguments)
|
|
131
|
+
return tracer.bindFunction(handler, transaction.trace.root, true).apply(this, arguments)
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
wrapped[ORIGINAL] = handler
|
|
@@ -127,7 +136,6 @@ function transactionProxy(handler) {
|
|
|
127
136
|
return wrapped
|
|
128
137
|
}
|
|
129
138
|
|
|
130
|
-
|
|
131
139
|
/**
|
|
132
140
|
* Use transactionNestProxy to wrap a closure that is a top-level handler that
|
|
133
141
|
* is meant to start transactions. This wraps the first half of asynchronous
|
|
@@ -145,7 +153,9 @@ function transactionNestProxy(type, handler) {
|
|
|
145
153
|
type = undefined
|
|
146
154
|
}
|
|
147
155
|
// if there's no handler, there's nothing to proxy.
|
|
148
|
-
if (typeof handler !== 'function')
|
|
156
|
+
if (typeof handler !== 'function') {
|
|
157
|
+
return handler
|
|
158
|
+
}
|
|
149
159
|
|
|
150
160
|
var tracer = this
|
|
151
161
|
var wrapped = function wrapTransactionInvocation() {
|
|
@@ -193,11 +203,13 @@ function _makeWrapped(tracer, handler, active, full) {
|
|
|
193
203
|
function wrapped() {
|
|
194
204
|
var prev = tracer.segment
|
|
195
205
|
tracer.segment = active
|
|
196
|
-
if (active && full)
|
|
206
|
+
if (active && full) {
|
|
207
|
+
active.start()
|
|
208
|
+
}
|
|
197
209
|
try {
|
|
198
210
|
return handler.apply(this, arguments)
|
|
199
211
|
} catch (err) {
|
|
200
|
-
logger.trace(err,
|
|
212
|
+
logger.trace(err, 'Error from wrapped function:')
|
|
201
213
|
|
|
202
214
|
if (prev === null && process.domain != null) {
|
|
203
215
|
process.domain.__NR_transactionSegment = tracer.segment
|
|
@@ -205,7 +217,9 @@ function _makeWrapped(tracer, handler, active, full) {
|
|
|
205
217
|
|
|
206
218
|
throw err // Re-throwing application error, this is not an agent error.
|
|
207
219
|
} finally {
|
|
208
|
-
if (active && full)
|
|
220
|
+
if (active && full) {
|
|
221
|
+
active.touch()
|
|
222
|
+
}
|
|
209
223
|
tracer.segment = prev
|
|
210
224
|
}
|
|
211
225
|
}
|
|
@@ -257,7 +271,9 @@ function argSlice(args) {
|
|
|
257
271
|
}
|
|
258
272
|
|
|
259
273
|
function wrapFunctionNoSegment(original, name, wrapper) {
|
|
260
|
-
if (typeof original !== 'function')
|
|
274
|
+
if (typeof original !== 'function') {
|
|
275
|
+
return original
|
|
276
|
+
}
|
|
261
277
|
|
|
262
278
|
logger.trace('Wrapping function %s (no segment)', name || original.name || 'anonymous')
|
|
263
279
|
var tracer = this
|
|
@@ -265,7 +281,9 @@ function wrapFunctionNoSegment(original, name, wrapper) {
|
|
|
265
281
|
return wrappedFunction
|
|
266
282
|
|
|
267
283
|
function wrappedFunction() {
|
|
268
|
-
if (!tracer.getTransaction())
|
|
284
|
+
if (!tracer.getTransaction()) {
|
|
285
|
+
return original.apply(this, arguments)
|
|
286
|
+
}
|
|
269
287
|
var args = tracer.slice(arguments)
|
|
270
288
|
|
|
271
289
|
if (wrapper === undefined) {
|
|
@@ -282,7 +300,9 @@ function wrapFunctionNoSegment(original, name, wrapper) {
|
|
|
282
300
|
}
|
|
283
301
|
|
|
284
302
|
function wrapFunctionFirstNoSegment(original, name) {
|
|
285
|
-
if (typeof original !== 'function')
|
|
303
|
+
if (typeof original !== 'function') {
|
|
304
|
+
return original
|
|
305
|
+
}
|
|
286
306
|
|
|
287
307
|
logger.trace('Wrapping function %s (no segment)', name || original.name || 'anonymous')
|
|
288
308
|
var tracer = this
|
|
@@ -290,7 +310,9 @@ function wrapFunctionFirstNoSegment(original, name) {
|
|
|
290
310
|
return wrappedFunction
|
|
291
311
|
|
|
292
312
|
function wrappedFunction() {
|
|
293
|
-
if (!tracer.getTransaction())
|
|
313
|
+
if (!tracer.getTransaction()) {
|
|
314
|
+
return original.apply(this, arguments)
|
|
315
|
+
}
|
|
294
316
|
var args = tracer.slice(arguments)
|
|
295
317
|
var cb = args[0]
|
|
296
318
|
if (typeof cb === 'function') {
|
|
@@ -322,7 +344,9 @@ function wrapFunctionLast(name, recorder, original) {
|
|
|
322
344
|
var args = tracer.slice(arguments)
|
|
323
345
|
var last = args.length - 1
|
|
324
346
|
var cb = args[last]
|
|
325
|
-
if (typeof cb !== 'function')
|
|
347
|
+
if (typeof cb !== 'function') {
|
|
348
|
+
return original.apply(this, arguments)
|
|
349
|
+
}
|
|
326
350
|
var child = tracer.createSegment(name, recorder)
|
|
327
351
|
args[last] = tracer.wrapCallback(cb, child, wrappedCallback)
|
|
328
352
|
child.start()
|
|
@@ -357,7 +381,9 @@ function wrapFunctionFirst(name, recorder, original) {
|
|
|
357
381
|
logger.trace('Creating "%s" segment for transaction %s.', name, transaction.id)
|
|
358
382
|
var args = tracer.slice(arguments)
|
|
359
383
|
var cb = args[0]
|
|
360
|
-
if (typeof cb !== 'function')
|
|
384
|
+
if (typeof cb !== 'function') {
|
|
385
|
+
return original.apply(this, arguments)
|
|
386
|
+
}
|
|
361
387
|
var child = tracer.createSegment(name, recorder)
|
|
362
388
|
args[0] = tracer.wrapCallback(cb, child, wrappedCallback)
|
|
363
389
|
child.start()
|
|
@@ -397,11 +423,15 @@ function wrapFunction(name, recorder, original, wrapper, resp) {
|
|
|
397
423
|
var args = wrapper.call(this, child, tracer.slice(arguments), bind)
|
|
398
424
|
child.start()
|
|
399
425
|
var result = tracer.bindFunction(original, child).apply(this, args)
|
|
400
|
-
if (resp)
|
|
426
|
+
if (resp) {
|
|
427
|
+
result = resp.call(this, child, result, bind)
|
|
428
|
+
}
|
|
401
429
|
return result
|
|
402
430
|
|
|
403
431
|
function bind(fn) {
|
|
404
|
-
if (!fn)
|
|
432
|
+
if (!fn) {
|
|
433
|
+
return fn
|
|
434
|
+
}
|
|
405
435
|
return tracer.wrapCallback(fn, child, function nrWrappedHandler() {
|
|
406
436
|
logger.trace('Touching "%s" segment for transaction %s.', name, transaction.id)
|
|
407
437
|
child.touch()
|
|
@@ -431,7 +461,9 @@ function wrapSyncFunction(name, recorder, original) {
|
|
|
431
461
|
}
|
|
432
462
|
logger.trace('Creating "%s" sync segment for transaction %s.', name, transaction.id)
|
|
433
463
|
var child = tracer.createSegment(name, recorder)
|
|
434
|
-
if (child)
|
|
464
|
+
if (child) {
|
|
465
|
+
child.async = false
|
|
466
|
+
}
|
|
435
467
|
return tracer.bindFunction(original, child, true).apply(this, arguments)
|
|
436
468
|
}
|
|
437
469
|
}
|
|
@@ -439,24 +471,27 @@ function wrapSyncFunction(name, recorder, original) {
|
|
|
439
471
|
function wrapCallback(original, segment, wrapped) {
|
|
440
472
|
var tracer = this
|
|
441
473
|
|
|
442
|
-
if (typeof original !== 'function')
|
|
474
|
+
if (typeof original !== 'function') {
|
|
475
|
+
return original
|
|
476
|
+
}
|
|
443
477
|
|
|
444
|
-
logger.trace(
|
|
445
|
-
'Wrapping callback for "%s" segment',
|
|
446
|
-
segment ? segment.name : 'unknown'
|
|
447
|
-
)
|
|
478
|
+
logger.trace('Wrapping callback for "%s" segment', segment ? segment.name : 'unknown')
|
|
448
479
|
|
|
449
|
-
return tracer.bindFunction(
|
|
450
|
-
|
|
480
|
+
return tracer.bindFunction(
|
|
481
|
+
function wrappedCallback() {
|
|
482
|
+
if (wrapped) {
|
|
483
|
+
wrapped[ORIGINAL] = original
|
|
484
|
+
}
|
|
451
485
|
|
|
452
|
-
|
|
453
|
-
'Callback: ' + (original.name || 'anonymous'),
|
|
454
|
-
null,
|
|
455
|
-
segment
|
|
456
|
-
)
|
|
486
|
+
var child = tracer.createSegment('Callback: ' + (original.name || 'anonymous'), null, segment)
|
|
457
487
|
|
|
458
|
-
|
|
488
|
+
if (child) {
|
|
489
|
+
child.async = false
|
|
490
|
+
}
|
|
459
491
|
|
|
460
|
-
|
|
461
|
-
|
|
492
|
+
return tracer.bindFunction(wrapped || original, child, true).apply(this, arguments)
|
|
493
|
+
},
|
|
494
|
+
segment,
|
|
495
|
+
false
|
|
496
|
+
)
|
|
462
497
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const async = require('async')
|
|
9
|
-
const logger = require('../logger').child({component: 'transaction-event-aggregator'})
|
|
9
|
+
const logger = require('../logger').child({ component: 'transaction-event-aggregator' })
|
|
10
10
|
const EventAggregator = require('../aggregators/event-aggregator')
|
|
11
11
|
|
|
12
12
|
const NAMES = require('../metrics/names')
|
|
@@ -80,7 +80,6 @@ class TransactionEventAggregator extends EventAggregator {
|
|
|
80
80
|
const firstHalfEventData = firstHalfRawEvents.map(this._rawEventsToValues)
|
|
81
81
|
const firstPayload = [this.runId, firstMetrics, firstHalfEventData]
|
|
82
82
|
|
|
83
|
-
|
|
84
83
|
const secondHalfRawEvents = events
|
|
85
84
|
const secondMetrics = {
|
|
86
85
|
reservoir_size: data.limit - limit,
|
|
@@ -89,10 +88,9 @@ class TransactionEventAggregator extends EventAggregator {
|
|
|
89
88
|
const secondHalfEventData = secondHalfRawEvents.map(this._rawEventsToValues)
|
|
90
89
|
const secondPayload = [this.runId, secondMetrics, secondHalfEventData]
|
|
91
90
|
|
|
92
|
-
|
|
93
91
|
const eventPayloadPairs = [
|
|
94
92
|
{ rawData: firstHalfRawEvents, payload: firstPayload },
|
|
95
|
-
{ rawData: secondHalfRawEvents, payload: secondPayload}
|
|
93
|
+
{ rawData: secondHalfRawEvents, payload: secondPayload }
|
|
96
94
|
]
|
|
97
95
|
|
|
98
96
|
return eventPayloadPairs
|
|
@@ -106,38 +104,38 @@ class TransactionEventAggregator extends EventAggregator {
|
|
|
106
104
|
const self = this
|
|
107
105
|
|
|
108
106
|
// Send payloads one at a time
|
|
109
|
-
async.eachOfSeries(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
self.method
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
self._sendSplitPayload(payloadPair.rawData, payloadPair.payload, (error) => {
|
|
118
|
-
if (error) {
|
|
119
|
-
logger.warn(error, 'An error occurred sending payload')
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
logger.trace(
|
|
123
|
-
'Finished sending payload %d of %d to %s',
|
|
107
|
+
async.eachOfSeries(
|
|
108
|
+
eventPayloadPairs,
|
|
109
|
+
(payloadPair, index, asyncCallback) => {
|
|
110
|
+
logger.debug(
|
|
111
|
+
'Sending payload %d of %d to %s',
|
|
124
112
|
index + 1,
|
|
125
113
|
eventPayloadPairs.length,
|
|
126
114
|
self.method
|
|
127
115
|
)
|
|
128
116
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
117
|
+
self._sendSplitPayload(payloadPair.rawData, payloadPair.payload, (error) => {
|
|
118
|
+
if (error) {
|
|
119
|
+
logger.warn(error, 'An error occurred sending payload')
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
logger.trace(
|
|
123
|
+
'Finished sending payload %d of %d to %s',
|
|
124
|
+
index + 1,
|
|
125
|
+
eventPayloadPairs.length,
|
|
126
|
+
self.method
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
// don't pass on error, allow next payload to attempt to send
|
|
130
|
+
asyncCallback()
|
|
131
|
+
})
|
|
132
|
+
},
|
|
133
|
+
function afterAllPayloadsSent() {
|
|
134
|
+
logger.debug('Finished sending %d payloads to %s', eventPayloadPairs.length, self.method)
|
|
135
|
+
|
|
136
|
+
sendCallback()
|
|
137
|
+
}
|
|
138
|
+
)
|
|
141
139
|
}
|
|
142
140
|
|
|
143
141
|
_sendSplitPayload(rawData, payload, callback) {
|
package/lib/uninstrumented.js
CHANGED
|
@@ -24,8 +24,7 @@ function logUninstrumented() {
|
|
|
24
24
|
'instrumented:'
|
|
25
25
|
|
|
26
26
|
modules.forEach(function buildMessage(module) {
|
|
27
|
-
message += '\n\t' + uninstrumented[module].name
|
|
28
|
-
+ ': ' + uninstrumented[module].filename
|
|
27
|
+
message += '\n\t' + uninstrumented[module].name + ': ' + uninstrumented[module].filename
|
|
29
28
|
})
|
|
30
29
|
|
|
31
30
|
logger.warn(message)
|
|
@@ -42,9 +41,9 @@ function createMetrics(metrics) {
|
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
modules.forEach(function addMetrics(module) {
|
|
45
|
-
metrics
|
|
46
|
-
NAMES.SUPPORTABILITY.UNINSTRUMENTED + '/' + uninstrumented[module].name
|
|
47
|
-
|
|
44
|
+
metrics
|
|
45
|
+
.getOrCreateMetric(NAMES.SUPPORTABILITY.UNINSTRUMENTED + '/' + uninstrumented[module].name)
|
|
46
|
+
.incrementCallCount()
|
|
48
47
|
})
|
|
49
48
|
}
|
|
50
49
|
|
package/lib/util/byte-limit.js
CHANGED
|
@@ -45,7 +45,6 @@ function truncate(val, limit) {
|
|
|
45
45
|
return val
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
49
48
|
// Our limitation is on byte length, and the string could contain multi-byte
|
|
50
49
|
// characters. Doing a byte-substring could chop a character in half. Instead
|
|
51
50
|
// we do a binary search over the byte length of the substrings.
|
package/lib/util/cat.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const hashes = require('./hashes')
|
|
9
|
-
const logger = require('../logger').child({component: 'cat'})
|
|
9
|
+
const logger = require('../logger').child({ component: 'cat' })
|
|
10
10
|
|
|
11
11
|
module.exports.handleCatHeaders = handleCatHeaders
|
|
12
12
|
module.exports.parsedHeadersToTrans = parsedHeadersToTrans
|
|
@@ -14,23 +14,15 @@ module.exports.parsedHeadersToTrans = parsedHeadersToTrans
|
|
|
14
14
|
function handleCatHeaders(incomingCatId, obfTransaction, encKey, transaction) {
|
|
15
15
|
var parsedCatId = null
|
|
16
16
|
if (incomingCatId) {
|
|
17
|
-
parsedCatId = hashes.deobfuscateNameUsingKey(
|
|
18
|
-
incomingCatId,
|
|
19
|
-
encKey
|
|
20
|
-
)
|
|
17
|
+
parsedCatId = hashes.deobfuscateNameUsingKey(incomingCatId, encKey)
|
|
21
18
|
}
|
|
22
19
|
|
|
23
20
|
var externalTrans = null
|
|
24
21
|
if (obfTransaction) {
|
|
25
22
|
try {
|
|
26
|
-
externalTrans = JSON.parse(
|
|
27
|
-
hashes.deobfuscateNameUsingKey(obfTransaction, encKey)
|
|
28
|
-
)
|
|
23
|
+
externalTrans = JSON.parse(hashes.deobfuscateNameUsingKey(obfTransaction, encKey))
|
|
29
24
|
} catch (e) {
|
|
30
|
-
logger.trace(
|
|
31
|
-
'Got an unparsable CAT header x-newrelic-transaction: %s',
|
|
32
|
-
obfTransaction
|
|
33
|
-
)
|
|
25
|
+
logger.trace('Got an unparsable CAT header x-newrelic-transaction: %s', obfTransaction)
|
|
34
26
|
}
|
|
35
27
|
}
|
|
36
28
|
|
|
@@ -59,5 +51,5 @@ function parsedHeadersToTrans(parsedCatId, externalTrans, transaction) {
|
|
|
59
51
|
}
|
|
60
52
|
|
|
61
53
|
function _isValidReferringHash(hash) {
|
|
62
|
-
return
|
|
54
|
+
return typeof hash === 'string'
|
|
63
55
|
}
|
package/lib/util/codec.js
CHANGED
|
@@ -23,8 +23,10 @@ module.exports = {
|
|
|
23
23
|
*/
|
|
24
24
|
encode: function encode(data, callback) {
|
|
25
25
|
try {
|
|
26
|
-
zlib.deflate(stringify(data), function
|
|
27
|
-
if (err)
|
|
26
|
+
zlib.deflate(stringify(data), function cbDeflate(err, raw) {
|
|
27
|
+
if (err) {
|
|
28
|
+
return callback(err)
|
|
29
|
+
}
|
|
28
30
|
|
|
29
31
|
return callback(null, raw.toString('base64'))
|
|
30
32
|
})
|
|
@@ -47,8 +49,10 @@ module.exports = {
|
|
|
47
49
|
* decoding, and the second parameter is the decoded data object.
|
|
48
50
|
*/
|
|
49
51
|
decode: function decode(encoded, callback) {
|
|
50
|
-
zlib.inflate(Buffer.from(encoded, 'base64'), function
|
|
51
|
-
if (err)
|
|
52
|
+
zlib.inflate(Buffer.from(encoded, 'base64'), function cbInflate(err, raw) {
|
|
53
|
+
if (err) {
|
|
54
|
+
return callback(err)
|
|
55
|
+
}
|
|
52
56
|
|
|
53
57
|
let json
|
|
54
58
|
try {
|