newrelic 8.0.0 → 8.4.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 +5023 -4922
- package/THIRD_PARTY_NOTICES.md +618 -209
- package/api.js +156 -219
- package/bin/test-naming-rules.js +57 -51
- package/bin/tracetractor +0 -1
- package/index.js +7 -14
- package/lib/agent.js +111 -114
- package/lib/aggregators/base-aggregator.js +1 -1
- package/lib/aggregators/event-aggregator.js +6 -6
- package/lib/attributes.js +13 -14
- package/lib/collector/api.js +44 -54
- package/lib/collector/facts.js +68 -66
- package/lib/collector/http-agents.js +36 -32
- package/lib/collector/key-parser.js +1 -1
- package/lib/collector/parse-response.js +1 -2
- package/lib/collector/remote-method.js +69 -61
- package/lib/collector/serverless.js +13 -18
- package/lib/collector/ssl/certificates.js +1056 -1056
- package/lib/config/attribute-filter.js +109 -101
- package/lib/config/default.js +35 -21
- package/lib/config/env.js +17 -12
- package/lib/config/harvest-config-validator.js +1 -1
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +240 -234
- package/lib/config/lasp.js +3 -3
- package/lib/config/merge-server-config.js +8 -6
- package/lib/custom-events/custom-event-aggregator.js +1 -1
- package/lib/db/parse-sql.js +13 -16
- package/lib/db/parsed-statement.js +13 -19
- package/lib/db/query-parsers/sql.js +12 -15
- package/lib/db/query-sample.js +16 -12
- package/lib/db/query-trace-aggregator.js +16 -16
- package/lib/db/statement-matcher.js +5 -5
- package/lib/db/utils.js +2 -2
- package/lib/environment.js +210 -175
- package/lib/errors/error-collector.js +20 -33
- package/lib/errors/error-event-aggregator.js +1 -1
- package/lib/errors/error-trace-aggregator.js +3 -4
- package/lib/errors/helper.js +23 -32
- package/lib/errors/index.js +31 -43
- package/lib/feature_flags.js +3 -4
- package/lib/grpc/connection/states.js +6 -6
- package/lib/grpc/connection.js +35 -46
- package/lib/header-attributes.js +55 -59
- package/lib/header-processing.js +1 -1
- package/lib/instrumentation/amqplib.js +34 -43
- package/lib/instrumentation/bluebird.js +63 -22
- package/lib/instrumentation/cassandra-driver.js +8 -4
- package/lib/instrumentation/connect.js +7 -6
- package/lib/instrumentation/core/async_hooks.js +16 -9
- 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 +4 -10
- package/lib/instrumentation/core/fs.js +22 -37
- package/lib/instrumentation/core/globals.js +4 -8
- package/lib/instrumentation/core/http-outbound.js +20 -114
- package/lib/instrumentation/core/http.js +61 -128
- package/lib/instrumentation/core/inspector.js +7 -11
- package/lib/instrumentation/core/net.js +3 -1
- package/lib/instrumentation/core/timers.js +21 -28
- package/lib/instrumentation/core/zlib.js +3 -11
- package/lib/instrumentation/director.js +4 -4
- package/lib/instrumentation/express.js +12 -10
- package/lib/instrumentation/fastify/spec-builders.js +5 -0
- package/lib/instrumentation/fastify.js +37 -10
- package/lib/instrumentation/generic-pool.js +1 -1
- package/lib/instrumentation/hapi/hapi-17.js +20 -21
- package/lib/instrumentation/hapi/shared.js +1 -1
- package/lib/instrumentation/hapi.js +37 -37
- package/lib/instrumentation/ioredis.js +8 -9
- package/lib/instrumentation/memcached.js +41 -45
- package/lib/instrumentation/mongodb/common.js +221 -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 +51 -44
- package/lib/instrumentation/oracle.js +24 -28
- package/lib/instrumentation/pg.js +34 -25
- package/lib/instrumentation/promise.js +65 -62
- package/lib/instrumentation/q.js +2 -2
- package/lib/instrumentation/redis.js +38 -38
- package/lib/instrumentation/restify.js +1 -1
- package/lib/instrumentation/vision.js +4 -4
- package/lib/instrumentation/when.js +12 -4
- package/lib/instrumentations.js +25 -25
- package/lib/logger.js +6 -6
- package/lib/metrics/index.js +50 -30
- package/lib/metrics/mapper.js +15 -15
- package/lib/metrics/metric-aggregator.js +5 -10
- package/lib/metrics/names.js +8 -7
- package/lib/metrics/normalizer/rule.js +14 -15
- package/lib/metrics/normalizer/tx_segment.js +33 -29
- package/lib/metrics/normalizer.js +51 -54
- package/lib/metrics/recorders/custom.js +8 -6
- package/lib/metrics/recorders/distributed-trace.js +3 -18
- package/lib/metrics/recorders/generic.js +6 -5
- package/lib/metrics/recorders/http.js +11 -13
- package/lib/metrics/recorders/http_external.js +8 -10
- package/lib/metrics/recorders/message-transaction.js +7 -18
- package/lib/metrics/recorders/other.js +7 -17
- package/lib/parse-proc-cpuinfo.js +26 -31
- package/lib/parse-proc-meminfo.js +5 -3
- package/lib/prioritized-attributes.js +14 -19
- package/lib/priority-queue.js +11 -11
- package/lib/proxy/grpc.js +1 -1
- package/lib/reservoir.js +12 -6
- package/lib/sampler.js +33 -34
- 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 +61 -67
- package/lib/shim/index.js +10 -11
- package/lib/shim/message-shim.js +149 -151
- package/lib/shim/promise-shim.js +19 -14
- package/lib/shim/shim.js +131 -125
- package/lib/shim/specs/index.js +21 -22
- package/lib/shim/transaction-shim.js +52 -210
- package/lib/shim/webframework-shim.js +75 -85
- package/lib/shimmer.js +184 -166
- package/lib/spans/create-span-event-aggregator.js +11 -8
- package/lib/spans/span-context.js +4 -10
- package/lib/spans/span-event-aggregator.js +68 -13
- package/lib/spans/span-event.js +6 -8
- package/lib/spans/span-streamer.js +10 -18
- package/lib/spans/streaming-span-attributes.js +1 -1
- package/lib/spans/streaming-span-event-aggregator.js +1 -1
- package/lib/spans/streaming-span-event.js +4 -4
- package/lib/stats/apdex.js +7 -13
- package/lib/stats/index.js +14 -19
- package/lib/system-info.js +29 -25
- package/lib/timer.js +35 -21
- package/lib/transaction/dt-payload.js +1 -1
- package/lib/transaction/handle.js +19 -19
- package/lib/transaction/index.js +133 -151
- package/lib/transaction/name-state.js +18 -19
- package/lib/transaction/trace/aggregator.js +78 -73
- package/lib/transaction/trace/exclusive-time-calculator.js +9 -13
- package/lib/transaction/trace/index.js +37 -35
- package/lib/transaction/trace/segment.js +56 -73
- package/lib/transaction/tracecontext.js +38 -46
- package/lib/transaction/tracer/index.js +130 -91
- package/lib/transaction/transaction-event-aggregator.js +29 -31
- package/lib/uninstrumented.js +11 -12
- package/lib/util/arity.js +2 -2
- package/lib/util/attribute-types.js +1 -5
- package/lib/util/byte-limit.js +4 -5
- package/lib/util/cat.js +270 -33
- package/lib/util/codec.js +10 -6
- package/lib/util/copy.js +2 -2
- package/lib/util/deep-equal.js +51 -21
- package/lib/util/flatten.js +9 -6
- package/lib/util/hashes.js +16 -16
- package/lib/util/label-parser.js +22 -28
- package/lib/util/logger.js +53 -35
- package/lib/util/process-version.js +3 -3
- package/lib/util/properties.js +5 -5
- package/lib/util/sql/obfuscate.js +21 -31
- package/lib/util/stream-sink.js +5 -6
- package/lib/util/unwrapped-core.js +2 -2
- package/lib/util/urltils.js +26 -30
- package/lib/utilization/aws-info.js +8 -9
- package/lib/utilization/azure-info.js +37 -35
- package/lib/utilization/common.js +17 -16
- package/lib/utilization/docker-info.js +14 -16
- package/lib/utilization/gcp-info.js +38 -37
- package/lib/utilization/index.js +5 -5
- package/lib/utilization/kubernetes-info.js +2 -2
- package/lib/utilization/pcf-info.js +12 -12
- package/package.json +23 -6
- package/stub_api.js +16 -14
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
const {DESTINATIONS} = require('../../config/attribute-filter')
|
|
9
|
-
const logger = require('../../logger').child({component: 'segment'})
|
|
8
|
+
const { DESTINATIONS } = require('../../config/attribute-filter')
|
|
9
|
+
const logger = require('../../logger').child({ component: 'segment' })
|
|
10
10
|
const Timer = require('../../timer')
|
|
11
11
|
const urltils = require('../../util/urltils')
|
|
12
12
|
const hashes = require('../../util/hashes')
|
|
13
13
|
|
|
14
|
-
const {Attributes} = require('../../attributes')
|
|
14
|
+
const { Attributes } = require('../../attributes')
|
|
15
15
|
const ExclusiveCalculator = require('./exclusive-time-calculator')
|
|
16
16
|
const SpanContext = require('../../spans/span-context')
|
|
17
17
|
|
|
@@ -23,7 +23,6 @@ const STATE = {
|
|
|
23
23
|
}
|
|
24
24
|
const ATTRIBUTE_SCOPE = 'segment'
|
|
25
25
|
|
|
26
|
-
|
|
27
26
|
/**
|
|
28
27
|
* Initializes the segment and binds the recorder to itself, if provided.
|
|
29
28
|
*
|
|
@@ -93,32 +92,20 @@ TraceSegment.prototype.getSpanContext = function getSpanContext() {
|
|
|
93
92
|
return this._spanContext
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
TraceSegment.prototype.addAttribute =
|
|
97
|
-
|
|
98
|
-
this.attributes.addAttribute(
|
|
99
|
-
DESTINATIONS.SEGMENT_SCOPE,
|
|
100
|
-
key,
|
|
101
|
-
value,
|
|
102
|
-
truncateExempt
|
|
103
|
-
)
|
|
95
|
+
TraceSegment.prototype.addAttribute = function addAttribute(key, value, truncateExempt = false) {
|
|
96
|
+
this.attributes.addAttribute(DESTINATIONS.SEGMENT_SCOPE, key, value, truncateExempt)
|
|
104
97
|
}
|
|
105
98
|
|
|
106
|
-
TraceSegment.prototype.addSpanAttribute =
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
truncateExempt
|
|
113
|
-
)
|
|
99
|
+
TraceSegment.prototype.addSpanAttribute = function addSpanAttribute(
|
|
100
|
+
key,
|
|
101
|
+
value,
|
|
102
|
+
truncateExempt = false
|
|
103
|
+
) {
|
|
104
|
+
this.attributes.addAttribute(DESTINATIONS.SPAN_EVENT, key, value, truncateExempt)
|
|
114
105
|
}
|
|
115
106
|
|
|
116
|
-
TraceSegment.prototype.addSpanAttributes =
|
|
117
|
-
|
|
118
|
-
this.attributes.addAttributes(
|
|
119
|
-
DESTINATIONS.SPAN_EVENT,
|
|
120
|
-
attributes
|
|
121
|
-
)
|
|
107
|
+
TraceSegment.prototype.addSpanAttributes = function addSpanAttributes(attributes) {
|
|
108
|
+
this.attributes.addAttributes(DESTINATIONS.SPAN_EVENT, attributes)
|
|
122
109
|
}
|
|
123
110
|
|
|
124
111
|
TraceSegment.prototype.getAttributes = function getAttributes() {
|
|
@@ -150,14 +137,14 @@ TraceSegment.prototype.getSpanId = function getSpanId() {
|
|
|
150
137
|
TraceSegment.prototype.captureDBInstanceAttributes = captureDBInstanceAttributes
|
|
151
138
|
|
|
152
139
|
function captureDBInstanceAttributes(host, port, database) {
|
|
153
|
-
|
|
154
|
-
|
|
140
|
+
const config = this.transaction.agent.config
|
|
141
|
+
const dsTracerConf = config.datastore_tracer
|
|
155
142
|
|
|
156
143
|
// Add database name if provided and enabled.
|
|
157
144
|
if (database !== false && dsTracerConf.database_name_reporting.enabled) {
|
|
158
145
|
this.addAttribute(
|
|
159
146
|
'database_name',
|
|
160
|
-
typeof database === 'number' ? database :
|
|
147
|
+
typeof database === 'number' ? database : database || INSTANCE_UNKNOWN
|
|
161
148
|
)
|
|
162
149
|
}
|
|
163
150
|
|
|
@@ -168,7 +155,8 @@ function captureDBInstanceAttributes(host, port, database) {
|
|
|
168
155
|
if (host && urltils.isLocalhost(host)) {
|
|
169
156
|
host = config.getHostnameSafe(host)
|
|
170
157
|
}
|
|
171
|
-
if (!host || host === 'UNKNOWN_BOX') {
|
|
158
|
+
if (!host || host === 'UNKNOWN_BOX') {
|
|
159
|
+
// Config's default name of a host.
|
|
172
160
|
host = INSTANCE_UNKNOWN
|
|
173
161
|
}
|
|
174
162
|
|
|
@@ -187,18 +175,17 @@ TraceSegment.prototype.isInCallbackState = function isInCallbackState() {
|
|
|
187
175
|
|
|
188
176
|
TraceSegment.prototype.probe = function probe(action) {
|
|
189
177
|
if (this.transaction.traceStacks) {
|
|
190
|
-
this.transaction.probe(action, {segment: this.name})
|
|
178
|
+
this.transaction.probe(action, { segment: this.name })
|
|
191
179
|
}
|
|
192
180
|
}
|
|
193
181
|
|
|
194
|
-
|
|
195
182
|
/**
|
|
196
183
|
* For use when a transaction is ending. The transaction segment should
|
|
197
184
|
* be named after the transaction it belongs to (which is only known by
|
|
198
185
|
* the end).
|
|
199
186
|
*/
|
|
200
187
|
TraceSegment.prototype.setNameFromTransaction = function setNameFromTransaction() {
|
|
201
|
-
|
|
188
|
+
const transaction = this.transaction
|
|
202
189
|
|
|
203
190
|
// transaction name and transaciton segment name must match
|
|
204
191
|
this.name = transaction.getFullName()
|
|
@@ -216,10 +203,10 @@ TraceSegment.prototype.setNameFromTransaction = function setNameFromTransaction(
|
|
|
216
203
|
* segment's parameters onto the transaction.
|
|
217
204
|
*/
|
|
218
205
|
TraceSegment.prototype.markAsWeb = function markAsWeb() {
|
|
219
|
-
|
|
206
|
+
const transaction = this.transaction
|
|
220
207
|
this.setNameFromTransaction()
|
|
221
208
|
|
|
222
|
-
|
|
209
|
+
const traceAttrs = transaction.trace.attributes.get(DESTINATIONS.TRANS_TRACE)
|
|
223
210
|
Object.keys(traceAttrs).forEach((key) => {
|
|
224
211
|
if (!this.attributes.has(key)) {
|
|
225
212
|
this.addAttribute(key, traceAttrs[key])
|
|
@@ -243,7 +230,6 @@ function overwriteDurationInMillis(duration, start) {
|
|
|
243
230
|
this.timer.overwriteDurationInMillis(duration, start)
|
|
244
231
|
}
|
|
245
232
|
|
|
246
|
-
|
|
247
233
|
TraceSegment.prototype.start = function start() {
|
|
248
234
|
this.timer.begin()
|
|
249
235
|
}
|
|
@@ -252,7 +238,9 @@ TraceSegment.prototype.start = function start() {
|
|
|
252
238
|
* Stop timing the related action.
|
|
253
239
|
*/
|
|
254
240
|
TraceSegment.prototype.end = function end() {
|
|
255
|
-
if (!this.timer.isActive())
|
|
241
|
+
if (!this.timer.isActive()) {
|
|
242
|
+
return
|
|
243
|
+
}
|
|
256
244
|
this.probe('Ended')
|
|
257
245
|
this.timer.end()
|
|
258
246
|
this._updateRootTimer()
|
|
@@ -266,10 +254,7 @@ TraceSegment.prototype.finalize = function finalize() {
|
|
|
266
254
|
this.name = NAMES.TRUNCATED.PREFIX + this.name
|
|
267
255
|
}
|
|
268
256
|
|
|
269
|
-
this.addAttribute(
|
|
270
|
-
'nr_exclusive_duration_millis',
|
|
271
|
-
this.getExclusiveDurationInMillis()
|
|
272
|
-
)
|
|
257
|
+
this.addAttribute('nr_exclusive_duration_millis', this.getExclusiveDurationInMillis())
|
|
273
258
|
}
|
|
274
259
|
|
|
275
260
|
/**
|
|
@@ -277,13 +262,9 @@ TraceSegment.prototype.finalize = function finalize() {
|
|
|
277
262
|
* in time.
|
|
278
263
|
*/
|
|
279
264
|
TraceSegment.prototype._updateRootTimer = function _updateRootTimer() {
|
|
280
|
-
|
|
265
|
+
const root = this.transaction.trace.root
|
|
281
266
|
if (this.timer.endsAfter(root.timer)) {
|
|
282
|
-
|
|
283
|
-
this.timer.start +
|
|
284
|
-
this.getDurationInMillis() -
|
|
285
|
-
root.timer.start
|
|
286
|
-
)
|
|
267
|
+
const newDuration = this.timer.start + this.getDurationInMillis() - root.timer.start
|
|
287
268
|
root.overwriteDurationInMillis(newDuration)
|
|
288
269
|
}
|
|
289
270
|
}
|
|
@@ -309,8 +290,8 @@ TraceSegment.prototype.add = function add(childName, recorder) {
|
|
|
309
290
|
return this
|
|
310
291
|
}
|
|
311
292
|
logger.trace('Adding segment %s to %s in %s', childName, this.name, this.transaction.id)
|
|
312
|
-
|
|
313
|
-
|
|
293
|
+
const segment = new TraceSegment(this.transaction, childName, recorder)
|
|
294
|
+
const config = this.transaction.agent.config
|
|
314
295
|
|
|
315
296
|
if (this.transaction.trace.segmentsSeen++ >= config.max_trace_segments) {
|
|
316
297
|
segment._collect = false
|
|
@@ -369,8 +350,8 @@ function getExclusiveDurationInMillis() {
|
|
|
369
350
|
}
|
|
370
351
|
|
|
371
352
|
TraceSegment.prototype.getChildren = function getChildren() {
|
|
372
|
-
|
|
373
|
-
for (
|
|
353
|
+
const children = []
|
|
354
|
+
for (let i = 0, len = this.children.length; i < len; ++i) {
|
|
374
355
|
if (!this.children[i].ignore) {
|
|
375
356
|
children.push(this.children[i])
|
|
376
357
|
}
|
|
@@ -379,8 +360,8 @@ TraceSegment.prototype.getChildren = function getChildren() {
|
|
|
379
360
|
}
|
|
380
361
|
|
|
381
362
|
TraceSegment.prototype.getCollectedChildren = function getCollectedChildren() {
|
|
382
|
-
|
|
383
|
-
for (
|
|
363
|
+
const children = []
|
|
364
|
+
for (let i = 0, len = this.children.length; i < len; ++i) {
|
|
384
365
|
if (this.children[i]._collect && !this.children[i].ignore) {
|
|
385
366
|
children.push(this.children[i])
|
|
386
367
|
}
|
|
@@ -400,16 +381,22 @@ TraceSegment.prototype.getCollectedChildren = function getCollectedChildren() {
|
|
|
400
381
|
*/
|
|
401
382
|
TraceSegment.prototype._getChildPairs = function _getChildPairs(end) {
|
|
402
383
|
// quick optimization
|
|
403
|
-
if (this.children.length < 1)
|
|
404
|
-
|
|
384
|
+
if (this.children.length < 1) {
|
|
385
|
+
return []
|
|
386
|
+
}
|
|
387
|
+
if (!end) {
|
|
388
|
+
end = Infinity
|
|
389
|
+
}
|
|
405
390
|
|
|
406
|
-
|
|
407
|
-
|
|
391
|
+
let children = this.getChildren()
|
|
392
|
+
const childPairs = []
|
|
408
393
|
while (children.length) {
|
|
409
|
-
|
|
410
|
-
|
|
394
|
+
const child = children.pop()
|
|
395
|
+
const pair = child.timer.toRange()
|
|
411
396
|
|
|
412
|
-
if (pair[0] >= end)
|
|
397
|
+
if (pair[0] >= end) {
|
|
398
|
+
continue
|
|
399
|
+
}
|
|
413
400
|
|
|
414
401
|
children = children.concat(child.getChildren())
|
|
415
402
|
|
|
@@ -450,13 +437,15 @@ TraceSegment.prototype.toJSON = function toJSON() {
|
|
|
450
437
|
const resultDest = []
|
|
451
438
|
// array of objects relating a segment and the destination for its
|
|
452
439
|
// serialized data.
|
|
453
|
-
const segmentsToProcess = [
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
440
|
+
const segmentsToProcess = [
|
|
441
|
+
{
|
|
442
|
+
segment: this,
|
|
443
|
+
destination: resultDest
|
|
444
|
+
}
|
|
445
|
+
]
|
|
457
446
|
|
|
458
447
|
while (segmentsToProcess.length !== 0) {
|
|
459
|
-
const {segment, destination} = segmentsToProcess.pop()
|
|
448
|
+
const { segment, destination } = segmentsToProcess.pop()
|
|
460
449
|
|
|
461
450
|
const start = segment.timer.startedRelativeTo(segment.transaction.trace.root.timer)
|
|
462
451
|
const duration = segment.getDurationInMillis()
|
|
@@ -465,19 +454,13 @@ TraceSegment.prototype.toJSON = function toJSON() {
|
|
|
465
454
|
const childArray = []
|
|
466
455
|
|
|
467
456
|
// push serialized data into the specified destination
|
|
468
|
-
destination.push([
|
|
469
|
-
start,
|
|
470
|
-
start + duration,
|
|
471
|
-
segment.name,
|
|
472
|
-
segment.getAttributes(),
|
|
473
|
-
childArray
|
|
474
|
-
])
|
|
457
|
+
destination.push([start, start + duration, segment.name, segment.getAttributes(), childArray])
|
|
475
458
|
|
|
476
459
|
if (segmentChildren.length) {
|
|
477
460
|
// push the children and the parent's children array into the stack.
|
|
478
461
|
// to preserve the chronological order of the children, push them
|
|
479
462
|
// onto the stack backwards (so the first one created is on top).
|
|
480
|
-
for (
|
|
463
|
+
for (let i = segmentChildren.length - 1; i >= 0; --i) {
|
|
481
464
|
segmentsToProcess.push({
|
|
482
465
|
segment: segmentChildren[i],
|
|
483
466
|
destination: childArray
|
|
@@ -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
|
|
@@ -387,7 +375,7 @@ class TraceContext {
|
|
|
387
375
|
* instrinsics on any relevant New Relic tracestate strings found
|
|
388
376
|
*/
|
|
389
377
|
_validateAndParseTraceStateHeader(tracestate) {
|
|
390
|
-
|
|
378
|
+
const tsd = {
|
|
391
379
|
entryFound: false,
|
|
392
380
|
entryValid: undefined,
|
|
393
381
|
entryInvalidReason: undefined,
|
|
@@ -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 = {
|