newrelic 9.6.0 → 9.7.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 +4 -0
- package/api.js +2 -0
- package/bin/test-naming-rules.js +1 -1
- package/esm-loader.mjs +1 -3
- package/lib/adaptive-sampler.js +1 -2
- package/lib/agent.js +2 -0
- package/lib/aggregators/event-aggregator.js +2 -2
- package/lib/attributes.js +2 -4
- package/lib/collector/api.js +20 -12
- package/lib/collector/facts.js +1 -3
- package/lib/collector/parse-response.js +3 -1
- package/lib/collector/remote-method.js +8 -9
- package/lib/config/attribute-filter.js +14 -16
- package/lib/config/default.js +17 -0
- package/lib/config/harvest-config-validator.js +3 -5
- package/lib/config/index.js +7 -4
- package/lib/environment.js +6 -5
- package/lib/errors/error-collector.js +6 -3
- package/lib/errors/helper.js +10 -18
- package/lib/errors/index.js +12 -6
- package/lib/grpc/connection.js +12 -5
- package/lib/header-attributes.js +4 -2
- package/lib/header-processing.js +2 -2
- package/lib/instrumentation/@hapi/hapi.js +2 -0
- package/lib/instrumentation/@node-redis/client.js +2 -0
- package/lib/instrumentation/amqplib.js +2 -0
- package/lib/instrumentation/core/async_hooks.js +2 -0
- package/lib/instrumentation/core/globals.js +11 -8
- package/lib/instrumentation/core/http-outbound.js +14 -12
- package/lib/instrumentation/core/http.js +10 -8
- package/lib/instrumentation/core/timers.js +2 -0
- package/lib/instrumentation/fastify.js +1 -3
- package/lib/instrumentation/grpc-js/grpc.js +14 -3
- package/lib/instrumentation/memcached.js +5 -0
- package/lib/instrumentation/mongodb/common.js +3 -0
- package/lib/instrumentation/mongodb/v2-mongo.js +6 -3
- package/lib/instrumentation/mongodb.js +1 -1
- package/lib/instrumentation/nr-winston-transport.js +3 -4
- package/lib/instrumentation/promise.js +7 -4
- package/lib/instrumentation/redis.js +2 -0
- package/lib/instrumentation/undici.js +2 -0
- package/lib/metrics/mapper.js +2 -3
- package/lib/metrics/metric-aggregator.js +1 -3
- package/lib/metrics/names.js +19 -15
- package/lib/metrics/normalizer/rule.js +6 -7
- package/lib/metrics/normalizer/tx_segment.js +3 -2
- package/lib/metrics/normalizer.js +5 -3
- package/lib/parse-proc-cpuinfo.js +11 -6
- package/lib/serverless/api-gateway.js +3 -4
- package/lib/serverless/aws-lambda.js +3 -3
- package/lib/shim/conglomerate-shim.js +2 -3
- package/lib/shim/datastore-shim.js +22 -104
- package/lib/shim/index.js +7 -0
- package/lib/shim/message-shim.js +2 -0
- package/lib/shim/promise-shim.js +48 -42
- package/lib/shim/shim.js +7 -7
- package/lib/shim/webframework-shim.js +2 -0
- package/lib/spans/map-to-streaming-type.js +0 -2
- package/lib/spans/span-context.js +2 -0
- package/lib/spans/span-event-aggregator.js +2 -2
- package/lib/spans/span-event.js +2 -2
- package/lib/spans/span-streamer.js +4 -0
- package/lib/spans/streaming-span-event-aggregator.js +2 -4
- package/lib/spans/streaming-span-event.js +3 -2
- package/lib/system-info.js +3 -5
- package/lib/timer.js +8 -6
- package/lib/transaction/dt-payload.js +4 -3
- package/lib/transaction/handle.js +12 -2
- package/lib/transaction/index.js +19 -18
- package/lib/transaction/name-state.js +17 -2
- package/lib/transaction/trace/aggregator.js +4 -12
- package/lib/transaction/trace/index.js +7 -5
- package/lib/transaction/trace/segment.js +6 -11
- package/lib/transaction/tracecontext.js +10 -6
- package/lib/transaction/tracer/index.js +23 -25
- package/lib/transaction/transaction-event-aggregator.js +1 -3
- package/lib/util/attribute-types.js +1 -2
- package/lib/util/byte-limit.js +1 -3
- package/lib/util/cat.js +16 -13
- package/lib/util/codec.js +0 -2
- package/lib/util/copy.js +1 -2
- package/lib/util/deep-equal.js +7 -0
- package/lib/util/flatten.js +4 -6
- package/lib/util/hashes.js +1 -3
- package/lib/util/process-version.js +2 -3
- package/lib/util/properties.js +2 -5
- package/lib/util/stream-sink.js +2 -0
- package/lib/util/urltils.js +4 -10
- package/newrelic.js +1 -1
- package/package.json +2 -1
package/lib/transaction/index.js
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
+
/* eslint sonarjs/cognitive-complexity: ["error", 29] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
|
+
|
|
8
10
|
const errorHelper = require('../errors/helper')
|
|
9
11
|
const hashes = require('../util/hashes')
|
|
10
12
|
const logger = require('../logger').child({ component: 'transaction' })
|
|
@@ -18,6 +20,9 @@ const url = require('url')
|
|
|
18
20
|
const urltils = require('../util/urltils')
|
|
19
21
|
const TraceContext = require('./tracecontext').TraceContext
|
|
20
22
|
const Logs = require('./logs')
|
|
23
|
+
const DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC = 'DistributedTrace/AcceptPayload/Exception'
|
|
24
|
+
const DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC = 'DistributedTrace/AcceptPayload/ParseException'
|
|
25
|
+
const REQUEST_PARAMS_PATH = 'request.parameters.'
|
|
21
26
|
|
|
22
27
|
/*
|
|
23
28
|
*
|
|
@@ -425,7 +430,7 @@ function finalizeNameFromUri(requestURL, statusCode) {
|
|
|
425
430
|
this.nameState.forEachParams(function forEachRouteParams(params) {
|
|
426
431
|
for (const key in params) {
|
|
427
432
|
if (props.hasOwn(params, key)) {
|
|
428
|
-
this.trace.attributes.addAttribute(DESTS.NONE,
|
|
433
|
+
this.trace.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
|
|
429
434
|
|
|
430
435
|
const segment = this.agent.tracer.getSegment()
|
|
431
436
|
|
|
@@ -435,7 +440,7 @@ function finalizeNameFromUri(requestURL, statusCode) {
|
|
|
435
440
|
key
|
|
436
441
|
)
|
|
437
442
|
} else {
|
|
438
|
-
segment.attributes.addAttribute(DESTS.NONE,
|
|
443
|
+
segment.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
|
|
439
444
|
}
|
|
440
445
|
}
|
|
441
446
|
}
|
|
@@ -484,7 +489,7 @@ Transaction.prototype._markAsWeb = function _markAsWeb(rawURL) {
|
|
|
484
489
|
const params = urltils.parseParameters(rawURL)
|
|
485
490
|
for (const key in params) {
|
|
486
491
|
if (props.hasOwn(params, key)) {
|
|
487
|
-
this.trace.attributes.addAttribute(DESTS.NONE,
|
|
492
|
+
this.trace.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
|
|
488
493
|
|
|
489
494
|
const segment = this.agent.tracer.getSegment()
|
|
490
495
|
|
|
@@ -494,7 +499,7 @@ Transaction.prototype._markAsWeb = function _markAsWeb(rawURL) {
|
|
|
494
499
|
key
|
|
495
500
|
)
|
|
496
501
|
} else {
|
|
497
|
-
segment.attributes.addAttribute(DESTS.NONE,
|
|
502
|
+
segment.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, params[key])
|
|
498
503
|
}
|
|
499
504
|
}
|
|
500
505
|
}
|
|
@@ -1058,7 +1063,7 @@ function _acceptDistributedTracePayload(payload, transport) {
|
|
|
1058
1063
|
trustedAccount
|
|
1059
1064
|
)
|
|
1060
1065
|
|
|
1061
|
-
this.agent.recordSupportability(
|
|
1066
|
+
this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC)
|
|
1062
1067
|
return
|
|
1063
1068
|
}
|
|
1064
1069
|
|
|
@@ -1075,14 +1080,14 @@ function _acceptDistributedTracePayload(payload, transport) {
|
|
|
1075
1080
|
if (!parsed.d) {
|
|
1076
1081
|
logger.warn('Received a distributed trace payload with no data field', this.id)
|
|
1077
1082
|
}
|
|
1078
|
-
this.agent.recordSupportability(
|
|
1083
|
+
this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
|
|
1079
1084
|
return
|
|
1080
1085
|
}
|
|
1081
1086
|
|
|
1082
1087
|
const majorVersion = parsed.v && typeof parsed.v[0] === 'number' && parsed.v[0]
|
|
1083
1088
|
if (majorVersion == null) {
|
|
1084
1089
|
logger.warn('Invalid distributed trace payload, not accepting')
|
|
1085
|
-
this.agent.recordSupportability(
|
|
1090
|
+
this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC)
|
|
1086
1091
|
}
|
|
1087
1092
|
if (majorVersion > 0) {
|
|
1088
1093
|
// TODO: Add DistributedTracePayload class?
|
|
@@ -1094,7 +1099,7 @@ function _acceptDistributedTracePayload(payload, transport) {
|
|
|
1094
1099
|
|
|
1095
1100
|
if (!data) {
|
|
1096
1101
|
logger.warn('No distributed trace data received, not accepting payload')
|
|
1097
|
-
this.agent.recordSupportability(
|
|
1102
|
+
this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_EXCEPTION_METRIC)
|
|
1098
1103
|
return
|
|
1099
1104
|
}
|
|
1100
1105
|
|
|
@@ -1103,7 +1108,7 @@ function _acceptDistributedTracePayload(payload, transport) {
|
|
|
1103
1108
|
})
|
|
1104
1109
|
// Either parentSpanId or parentId are required.
|
|
1105
1110
|
if (!requiredKeysExist || (data.tx == null && data.id == null)) {
|
|
1106
|
-
this.agent.recordSupportability(
|
|
1111
|
+
this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
|
|
1107
1112
|
return
|
|
1108
1113
|
}
|
|
1109
1114
|
|
|
@@ -1157,7 +1162,7 @@ Transaction.prototype._getParsedPayload = function _getParsedPayload(payload) {
|
|
|
1157
1162
|
payload = Buffer.from(payload, 'base64').toString('utf-8')
|
|
1158
1163
|
} catch (err) {
|
|
1159
1164
|
logger.warn(err, 'Got unparseable distributed trace payload in transaction %s', this.id)
|
|
1160
|
-
this.agent.recordSupportability(
|
|
1165
|
+
this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
|
|
1161
1166
|
return null
|
|
1162
1167
|
}
|
|
1163
1168
|
}
|
|
@@ -1165,7 +1170,7 @@ Transaction.prototype._getParsedPayload = function _getParsedPayload(payload) {
|
|
|
1165
1170
|
parsed = JSON.parse(payload)
|
|
1166
1171
|
} catch (err) {
|
|
1167
1172
|
logger.warn(err, 'Failed to parse distributed trace payload in transaction %s', this.id)
|
|
1168
|
-
this.agent.recordSupportability(
|
|
1173
|
+
this.agent.recordSupportability(DT_ACCEPT_PAYLOAD_PARSE_EXCEPTION_METRIC)
|
|
1169
1174
|
return null
|
|
1170
1175
|
}
|
|
1171
1176
|
}
|
|
@@ -1300,24 +1305,20 @@ Transaction.prototype.addRequestParameters = addRequestParameters
|
|
|
1300
1305
|
* 'request.parameters.{key}'. These attributes will only be created
|
|
1301
1306
|
* when 'request.parameters.*' is included in the attribute config.
|
|
1302
1307
|
*
|
|
1303
|
-
* @param {
|
|
1308
|
+
* @param {Object<string, string>} requestParameters
|
|
1304
1309
|
*/
|
|
1305
1310
|
function addRequestParameters(requestParameters) {
|
|
1306
1311
|
for (const key in requestParameters) {
|
|
1307
1312
|
if (props.hasOwn(requestParameters, key)) {
|
|
1308
1313
|
this.trace.attributes.addAttribute(
|
|
1309
1314
|
DESTS.NONE,
|
|
1310
|
-
|
|
1315
|
+
REQUEST_PARAMS_PATH + key,
|
|
1311
1316
|
requestParameters[key]
|
|
1312
1317
|
)
|
|
1313
1318
|
|
|
1314
1319
|
const segment = this.baseSegment
|
|
1315
1320
|
|
|
1316
|
-
segment.attributes.addAttribute(
|
|
1317
|
-
DESTS.NONE,
|
|
1318
|
-
'request.parameters.' + key,
|
|
1319
|
-
requestParameters[key]
|
|
1320
|
-
)
|
|
1321
|
+
segment.attributes.addAttribute(DESTS.NONE, REQUEST_PARAMS_PATH + key, requestParameters[key])
|
|
1321
1322
|
}
|
|
1322
1323
|
}
|
|
1323
1324
|
}
|
|
@@ -29,7 +29,11 @@ const STATUS_CODE_NAMES = {
|
|
|
29
29
|
/**
|
|
30
30
|
* Manages transaction names using a stack of paths.
|
|
31
31
|
*
|
|
32
|
-
* @
|
|
32
|
+
* @param prefix
|
|
33
|
+
* @param verb
|
|
34
|
+
* @param delimiter
|
|
35
|
+
* @param path
|
|
36
|
+
* @class
|
|
33
37
|
*/
|
|
34
38
|
function NameState(prefix, verb, delimiter, path) {
|
|
35
39
|
this.reset()
|
|
@@ -67,6 +71,8 @@ NameState.prototype.markPath = function markPath() {
|
|
|
67
71
|
|
|
68
72
|
/**
|
|
69
73
|
* Sets the metric prefix (i.e. Expressjs).
|
|
74
|
+
*
|
|
75
|
+
* @param prefix
|
|
70
76
|
*/
|
|
71
77
|
NameState.prototype.setPrefix = function setPrefix(prefix) {
|
|
72
78
|
if (this._frozen) {
|
|
@@ -82,6 +88,8 @@ NameState.prototype.setPrefix = function setPrefix(prefix) {
|
|
|
82
88
|
|
|
83
89
|
/**
|
|
84
90
|
* Sets the HTTP verb (i.e. GET/POST/PUT)
|
|
91
|
+
*
|
|
92
|
+
* @param verb
|
|
85
93
|
*/
|
|
86
94
|
NameState.prototype.setVerb = function setVerb(verb) {
|
|
87
95
|
if (!this._frozen) {
|
|
@@ -91,6 +99,8 @@ NameState.prototype.setVerb = function setVerb(verb) {
|
|
|
91
99
|
|
|
92
100
|
/**
|
|
93
101
|
* Sets the delimiter character used to separate the http verb from the path.
|
|
102
|
+
*
|
|
103
|
+
* @param delimiter
|
|
94
104
|
*/
|
|
95
105
|
NameState.prototype.setDelimiter = function setDelimiter(delimiter) {
|
|
96
106
|
if (!this._frozen) {
|
|
@@ -104,6 +114,9 @@ NameState.prototype.isEmpty = function isEmpty() {
|
|
|
104
114
|
|
|
105
115
|
/**
|
|
106
116
|
* Pushes a new path element onto the naming stack.
|
|
117
|
+
*
|
|
118
|
+
* @param path
|
|
119
|
+
* @param params
|
|
107
120
|
*/
|
|
108
121
|
NameState.prototype.appendPath = function appendPath(path, params) {
|
|
109
122
|
if (!this._frozen && path != null) {
|
|
@@ -120,6 +133,9 @@ NameState.prototype.appendPath = function appendPath(path, params) {
|
|
|
120
133
|
/**
|
|
121
134
|
* Pushes a new path element onto the naming stack if the stack is
|
|
122
135
|
* empty.
|
|
136
|
+
*
|
|
137
|
+
* @param path
|
|
138
|
+
* @param params
|
|
123
139
|
*/
|
|
124
140
|
NameState.prototype.appendPathIfEmpty = function appendPathIfEmpty(path, params) {
|
|
125
141
|
if (!this._frozen && this.isEmpty()) {
|
|
@@ -244,7 +260,6 @@ function _getName(nameState, path) {
|
|
|
244
260
|
* @param {Array} arr - Array to search.
|
|
245
261
|
* @param {Function} pred - Predicate function that returns `true` on matches.
|
|
246
262
|
* @param {*} ctx - The `this` arg for `pred`.
|
|
247
|
-
*
|
|
248
263
|
* @returns {number} - This index of the last matching item, or `-1`.
|
|
249
264
|
*/
|
|
250
265
|
function _findLastIndex(arr, pred, ctx) {
|
|
@@ -272,10 +272,8 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
272
272
|
* is less than the response time in the map, it is skipped.
|
|
273
273
|
*/
|
|
274
274
|
let slowerThanCaptured = true
|
|
275
|
-
if (hasMetGuarantee) {
|
|
276
|
-
|
|
277
|
-
slowerThanCaptured = this.requestTimes[name] < duration
|
|
278
|
-
}
|
|
275
|
+
if (hasMetGuarantee && this.requestTimes[name]) {
|
|
276
|
+
slowerThanCaptured = this.requestTimes[name] < duration
|
|
279
277
|
}
|
|
280
278
|
if (!slowerThanCaptured) {
|
|
281
279
|
return false
|
|
@@ -285,17 +283,11 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
285
283
|
* Ensure this name is either already in the request time map
|
|
286
284
|
* or that the map still hasn't hit capacity.
|
|
287
285
|
*/
|
|
288
|
-
|
|
286
|
+
return !(
|
|
289
287
|
hasMetGuarantee &&
|
|
290
288
|
!this.requestTimes[name] &&
|
|
291
289
|
Object.keys(this.requestTimes).length >= this.capacity
|
|
292
|
-
)
|
|
293
|
-
return false
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/* 4. The transaction is held as the slowest transaction.
|
|
297
|
-
*/
|
|
298
|
-
return true
|
|
290
|
+
)
|
|
299
291
|
}
|
|
300
292
|
}
|
|
301
293
|
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
+
/* eslint sonarjs/cognitive-complexity: ["error", 19] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
|
+
|
|
8
10
|
const codec = require('../../util/codec')
|
|
9
11
|
const Segment = require('./segment')
|
|
10
12
|
const { Attributes, MAXIMUM_CUSTOM_ATTRIBUTES } = require('../../attributes')
|
|
@@ -139,6 +141,7 @@ function DTTraceNode(segment, parentId, isRoot = false) {
|
|
|
139
141
|
* Add a child to the list of segments.
|
|
140
142
|
*
|
|
141
143
|
* @param {string} childName Name for the new segment.
|
|
144
|
+
* @param callback
|
|
142
145
|
* @returns {Segment} Newly-created Segment.
|
|
143
146
|
*/
|
|
144
147
|
Trace.prototype.add = function add(childName, callback) {
|
|
@@ -159,7 +162,7 @@ function setDurationInMillis(duration, startTimeInMillis) {
|
|
|
159
162
|
}
|
|
160
163
|
|
|
161
164
|
/**
|
|
162
|
-
* @
|
|
165
|
+
* @returns {integer} The amount of time the trace took, in milliseconds.
|
|
163
166
|
*/
|
|
164
167
|
Trace.prototype.getDurationInMillis = function getDurationInMillis() {
|
|
165
168
|
return this.root.getDurationInMillis()
|
|
@@ -188,7 +191,7 @@ Trace.prototype.addCustomAttribute = function addCustomAttribute(key, value) {
|
|
|
188
191
|
* The duration of the transaction trace tree that only this level accounts
|
|
189
192
|
* for.
|
|
190
193
|
*
|
|
191
|
-
* @
|
|
194
|
+
* @returns {integer} The amount of time the trace took, minus any child
|
|
192
195
|
* traces, in milliseconds.
|
|
193
196
|
*/
|
|
194
197
|
Trace.prototype.getExclusiveDurationInMillis = function getExclusiveDurationInMillis() {
|
|
@@ -199,7 +202,7 @@ Trace.prototype.getExclusiveDurationInMillis = function getExclusiveDurationInMi
|
|
|
199
202
|
* The duration of all segments in a transaction trace. The root is not
|
|
200
203
|
* accounted for, since it doesn't represent a unit of work.
|
|
201
204
|
*
|
|
202
|
-
* @
|
|
205
|
+
* @returns {integer} The sum of durations for all segments in a trace in
|
|
203
206
|
* milliseconds
|
|
204
207
|
*/
|
|
205
208
|
Trace.prototype.getTotalTimeDurationInMillis = function getTotalTimeDurationInMillis() {
|
|
@@ -287,8 +290,8 @@ Trace.prototype.generateJSONSync = function generateJSONSync() {
|
|
|
287
290
|
/**
|
|
288
291
|
* Generates the payload used in a trace harvest.
|
|
289
292
|
*
|
|
293
|
+
* @param data
|
|
290
294
|
* @private
|
|
291
|
-
*
|
|
292
295
|
* @returns {Array} The formatted payload.
|
|
293
296
|
*/
|
|
294
297
|
Trace.prototype._generatePayload = function _generatePayload(data) {
|
|
@@ -336,7 +339,6 @@ Trace.prototype._getRequestUri = function _getRequestUri() {
|
|
|
336
339
|
* Serializes the trace into the expected JSON format to be sent.
|
|
337
340
|
*
|
|
338
341
|
* @private
|
|
339
|
-
*
|
|
340
342
|
* @returns {Array} Serialized trace data.
|
|
341
343
|
*/
|
|
342
344
|
Trace.prototype._serializeTrace = function _serializeTrace() {
|
|
@@ -26,21 +26,18 @@ const ATTRIBUTE_SCOPE = 'segment'
|
|
|
26
26
|
/**
|
|
27
27
|
* Initializes the segment and binds the recorder to itself, if provided.
|
|
28
28
|
*
|
|
29
|
-
* @
|
|
29
|
+
* @class
|
|
30
30
|
* @classdesc
|
|
31
31
|
* TraceSegments are inserted to track instrumented function calls. Each one is
|
|
32
32
|
* bound to a transaction, given a name (used only internally to the framework
|
|
33
33
|
* for now), and has one or more children (that are also part of the same
|
|
34
34
|
* transaction), as well as an associated timer.
|
|
35
|
-
*
|
|
36
35
|
* @param {Transaction} transaction
|
|
37
36
|
* The transaction to which this segment will be bound.
|
|
38
|
-
*
|
|
39
37
|
* @param {string} name
|
|
40
38
|
* Human-readable name for this segment (e.g. 'http', 'net', 'express',
|
|
41
39
|
* 'mysql', etc).
|
|
42
|
-
*
|
|
43
|
-
* @param {?function} recorder
|
|
40
|
+
* @param {?Function} recorder
|
|
44
41
|
* Callback that takes a segment and a scope name as attributes (intended to be
|
|
45
42
|
* used to record metrics related to the segment).
|
|
46
43
|
*/
|
|
@@ -126,10 +123,8 @@ TraceSegment.prototype.getSpanId = function getSpanId() {
|
|
|
126
123
|
* @param {string} host
|
|
127
124
|
* The name of the host of the database. This will be normalized if the string
|
|
128
125
|
* represents localhost.
|
|
129
|
-
*
|
|
130
126
|
* @param {string|number} port
|
|
131
127
|
* The database's port, path to unix socket, or id.
|
|
132
|
-
*
|
|
133
128
|
* @param {string|number|bool} database
|
|
134
129
|
* The name or ID of the database that was connected to. Or `false` if there is
|
|
135
130
|
* no database name (i.e. Redis has no databases, only hosts).
|
|
@@ -282,6 +277,7 @@ TraceSegment.prototype._isEnded = function _isEnded() {
|
|
|
282
277
|
* Add a new segment to a scope implicitly bounded by this segment.
|
|
283
278
|
*
|
|
284
279
|
* @param {string} childName New human-readable name for the segment.
|
|
280
|
+
* @param recorder
|
|
285
281
|
* @returns {TraceSegment} New nested TraceSegment.
|
|
286
282
|
*/
|
|
287
283
|
TraceSegment.prototype.add = function add(childName, recorder) {
|
|
@@ -308,7 +304,7 @@ TraceSegment.prototype.add = function add(childName, recorder) {
|
|
|
308
304
|
/**
|
|
309
305
|
* Set the duration of the segment explicitly.
|
|
310
306
|
*
|
|
311
|
-
* @param {
|
|
307
|
+
* @param {number} duration Duration in milliseconds.
|
|
312
308
|
*/
|
|
313
309
|
TraceSegment.prototype.setDurationInMillis = setDurationInMillis
|
|
314
310
|
|
|
@@ -335,7 +331,7 @@ function _setExclusiveDurationInMillis(duration) {
|
|
|
335
331
|
* The duration of the transaction trace tree that only this level accounts
|
|
336
332
|
* for.
|
|
337
333
|
*
|
|
338
|
-
* @
|
|
334
|
+
* @returns {integer} The amount of time the trace took, minus any child
|
|
339
335
|
* segments, in milliseconds.
|
|
340
336
|
*/
|
|
341
337
|
TraceSegment.prototype.getExclusiveDurationInMillis = getExclusiveDurationInMillis
|
|
@@ -372,10 +368,9 @@ TraceSegment.prototype.getCollectedChildren = function getCollectedChildren() {
|
|
|
372
368
|
/**
|
|
373
369
|
* Enumerate the timings of this segment's descendants.
|
|
374
370
|
*
|
|
375
|
-
* @param {
|
|
371
|
+
* @param {number} end The end of this segment, to keep the calculated
|
|
376
372
|
* duration from exceeding the duration of the
|
|
377
373
|
* parent. Defaults to Infinity.
|
|
378
|
-
*
|
|
379
374
|
* @returns {Array} Unsorted list of [start, end] pairs, with no pair
|
|
380
375
|
* having an end greater than the passed in end time.
|
|
381
376
|
*/
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
+
/* eslint sonarjs/cognitive-complexity: ["error", 20] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
|
+
|
|
8
10
|
const logger = require('../logger').child({ component: 'TraceContext' })
|
|
9
11
|
const hashes = require('../util/hashes')
|
|
10
12
|
|
|
@@ -32,6 +34,7 @@ const FLAGS = {
|
|
|
32
34
|
class TraceContext {
|
|
33
35
|
/**
|
|
34
36
|
* Create a TraceContext object
|
|
37
|
+
*
|
|
35
38
|
* @param {Transaction} transaction - a transaction object to attach to.
|
|
36
39
|
*/
|
|
37
40
|
constructor(transaction) {
|
|
@@ -135,6 +138,7 @@ class TraceContext {
|
|
|
135
138
|
|
|
136
139
|
/**
|
|
137
140
|
* Takes a headers object and modifies it in place by adding Trace Context headers
|
|
141
|
+
*
|
|
138
142
|
* @param {object} headers - Headers for an HTTP request
|
|
139
143
|
*/
|
|
140
144
|
addTraceContextHeaders(headers) {
|
|
@@ -175,7 +179,7 @@ class TraceContext {
|
|
|
175
179
|
*
|
|
176
180
|
* @param {string} traceparent - W3C traceparent header from an HTTP request
|
|
177
181
|
* @param {string} tracestate - W3C tracestate header from an HTTP request
|
|
178
|
-
* @returns {
|
|
182
|
+
* @returns {object} returns an Object with the traceparent data and validation info
|
|
179
183
|
*/
|
|
180
184
|
acceptTraceContextPayload(traceparent, tracestate) {
|
|
181
185
|
const traceContextData = {
|
|
@@ -294,7 +298,7 @@ class TraceContext {
|
|
|
294
298
|
* parsed out if valid.
|
|
295
299
|
*
|
|
296
300
|
* @param {string} traceparent - a W3C traceparent header string
|
|
297
|
-
* @returns {
|
|
301
|
+
* @returns {object} returns an Object with the traceparent data and validation info
|
|
298
302
|
*/
|
|
299
303
|
_validateAndParseTraceParentHeader(traceparent) {
|
|
300
304
|
const traceParentInfo = {
|
|
@@ -363,7 +367,7 @@ class TraceContext {
|
|
|
363
367
|
* @property {Intrinsics} intrinsics - All the parts of the New Relic tracestate string
|
|
364
368
|
* parsed and split out into an object
|
|
365
369
|
* @property {string} newTraceState - The raw tracestate without the New Relic entry
|
|
366
|
-
* @property {
|
|
370
|
+
* @property {Array} vendors - All the vendor strings found in the tracestate
|
|
367
371
|
*/
|
|
368
372
|
|
|
369
373
|
/**
|
|
@@ -535,6 +539,8 @@ class TraceContext {
|
|
|
535
539
|
|
|
536
540
|
/**
|
|
537
541
|
* Parses intrinsics of a New Relic tracestate entry's value
|
|
542
|
+
*
|
|
543
|
+
* @param nrTracestateValue
|
|
538
544
|
*/
|
|
539
545
|
_parseIntrinsics(nrTracestateValue) {
|
|
540
546
|
const intrinsics = this._extractTraceStateIntrinsics(nrTracestateValue)
|
|
@@ -570,7 +576,7 @@ class TraceContext {
|
|
|
570
576
|
}
|
|
571
577
|
})
|
|
572
578
|
|
|
573
|
-
|
|
579
|
+
return {
|
|
574
580
|
version: splitValues[0],
|
|
575
581
|
parentType: splitValues[1],
|
|
576
582
|
accountId: splitValues[2],
|
|
@@ -581,8 +587,6 @@ class TraceContext {
|
|
|
581
587
|
priority: splitValues[7],
|
|
582
588
|
timestamp: splitValues[8]
|
|
583
589
|
}
|
|
584
|
-
|
|
585
|
-
return intrinsics
|
|
586
590
|
}
|
|
587
591
|
}
|
|
588
592
|
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
const Transaction = require('../index.js')
|
|
9
9
|
const logger = require('../../logger').child({ component: 'tracer' })
|
|
10
10
|
const symbols = require('../../symbols')
|
|
11
|
+
const INACTIVE_TRANSACTION_MESSAGE = 'Not creating segment "%s" because no transaction was active'
|
|
12
|
+
const SKIP_WRAPPING_FUNCTION_MESSAGE = 'Not wrapping "%s" because it was not a function'
|
|
13
|
+
const CREATE_SEGMENT_MESSAGE = 'Creating "%s" segment for transaction %s.'
|
|
11
14
|
|
|
12
15
|
module.exports = Tracer
|
|
13
16
|
|
|
@@ -311,7 +314,7 @@ function wrapFunctionFirstNoSegment(original, name) {
|
|
|
311
314
|
|
|
312
315
|
function wrapFunctionLast(name, recorder, original) {
|
|
313
316
|
if (typeof original !== 'function') {
|
|
314
|
-
logger.trace(
|
|
317
|
+
logger.trace(SKIP_WRAPPING_FUNCTION_MESSAGE, name)
|
|
315
318
|
return original
|
|
316
319
|
}
|
|
317
320
|
|
|
@@ -323,11 +326,11 @@ function wrapFunctionLast(name, recorder, original) {
|
|
|
323
326
|
function wrappedFunction() {
|
|
324
327
|
const transaction = tracer.getTransaction()
|
|
325
328
|
if (!transaction) {
|
|
326
|
-
logger.trace(
|
|
329
|
+
logger.trace(INACTIVE_TRANSACTION_MESSAGE, name)
|
|
327
330
|
return original.apply(this, arguments)
|
|
328
331
|
}
|
|
329
332
|
|
|
330
|
-
logger.trace(
|
|
333
|
+
logger.trace(CREATE_SEGMENT_MESSAGE, name, transaction.id)
|
|
331
334
|
const args = tracer.slice(arguments)
|
|
332
335
|
const last = args.length - 1
|
|
333
336
|
const cb = args[last]
|
|
@@ -335,21 +338,19 @@ function wrapFunctionLast(name, recorder, original) {
|
|
|
335
338
|
return original.apply(this, arguments)
|
|
336
339
|
}
|
|
337
340
|
const child = tracer.createSegment(name, recorder)
|
|
338
|
-
args[last] = tracer.wrapCallback(cb, child, wrappedCallback)
|
|
339
|
-
child.start()
|
|
340
|
-
return tracer.bindFunction(original, child).apply(this, args)
|
|
341
|
-
|
|
342
|
-
function wrappedCallback() {
|
|
341
|
+
args[last] = tracer.wrapCallback(cb, child, function wrappedCallback() {
|
|
343
342
|
logger.trace('Ending "%s" segment for transaction %s.', name, transaction.id)
|
|
344
343
|
child.touch()
|
|
345
344
|
return cb.apply(this, arguments)
|
|
346
|
-
}
|
|
345
|
+
})
|
|
346
|
+
child.start()
|
|
347
|
+
return tracer.bindFunction(original, child).apply(this, args)
|
|
347
348
|
}
|
|
348
349
|
}
|
|
349
350
|
|
|
350
351
|
function wrapFunctionFirst(name, recorder, original) {
|
|
351
352
|
if (typeof original !== 'function') {
|
|
352
|
-
logger.trace(
|
|
353
|
+
logger.trace(SKIP_WRAPPING_FUNCTION_MESSAGE, name)
|
|
353
354
|
return original
|
|
354
355
|
}
|
|
355
356
|
|
|
@@ -361,33 +362,30 @@ function wrapFunctionFirst(name, recorder, original) {
|
|
|
361
362
|
function wrappedFunction() {
|
|
362
363
|
const transaction = tracer.getTransaction()
|
|
363
364
|
if (!transaction) {
|
|
364
|
-
logger.trace(
|
|
365
|
+
logger.trace(INACTIVE_TRANSACTION_MESSAGE, name)
|
|
365
366
|
return original.apply(this, arguments)
|
|
366
367
|
}
|
|
367
368
|
|
|
368
|
-
logger.trace(
|
|
369
|
+
logger.trace(CREATE_SEGMENT_MESSAGE, name, transaction.id)
|
|
369
370
|
const args = tracer.slice(arguments)
|
|
370
371
|
const cb = args[0]
|
|
371
372
|
if (typeof cb !== 'function') {
|
|
372
373
|
return original.apply(this, arguments)
|
|
373
374
|
}
|
|
374
375
|
const child = tracer.createSegment(name, recorder)
|
|
375
|
-
args[0] = tracer.wrapCallback(cb, child, wrappedCallback)
|
|
376
|
-
child.start()
|
|
377
|
-
return tracer.bindFunction(original, child).apply(this, args)
|
|
378
|
-
|
|
379
|
-
function wrappedCallback() {
|
|
376
|
+
args[0] = tracer.wrapCallback(cb, child, function wrappedCallback() {
|
|
380
377
|
logger.trace('Ending "%s" segment for transaction %s.', name, transaction.id)
|
|
381
378
|
child.touch()
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
379
|
+
return cb.apply(this, arguments)
|
|
380
|
+
})
|
|
381
|
+
child.start()
|
|
382
|
+
return tracer.bindFunction(original, child).apply(this, args)
|
|
385
383
|
}
|
|
386
384
|
}
|
|
387
385
|
|
|
388
386
|
function wrapFunction(name, recorder, original, wrapper, resp) {
|
|
389
387
|
if (typeof original !== 'function' || !wrapper) {
|
|
390
|
-
logger.trace(
|
|
388
|
+
logger.trace(SKIP_WRAPPING_FUNCTION_MESSAGE, name)
|
|
391
389
|
return original
|
|
392
390
|
}
|
|
393
391
|
|
|
@@ -400,11 +398,11 @@ function wrapFunction(name, recorder, original, wrapper, resp) {
|
|
|
400
398
|
function wrappedFunction() {
|
|
401
399
|
const transaction = tracer.getTransaction()
|
|
402
400
|
if (!transaction) {
|
|
403
|
-
logger.trace(
|
|
401
|
+
logger.trace(INACTIVE_TRANSACTION_MESSAGE, name)
|
|
404
402
|
return original.apply(this, arguments)
|
|
405
403
|
}
|
|
406
404
|
|
|
407
|
-
logger.trace(
|
|
405
|
+
logger.trace(CREATE_SEGMENT_MESSAGE, name, transaction.id)
|
|
408
406
|
|
|
409
407
|
const child = tracer.createSegment(name, recorder)
|
|
410
408
|
const args = wrapper.call(this, child, tracer.slice(arguments), bind)
|
|
@@ -430,7 +428,7 @@ function wrapFunction(name, recorder, original, wrapper, resp) {
|
|
|
430
428
|
|
|
431
429
|
function wrapSyncFunction(name, recorder, original) {
|
|
432
430
|
if (typeof original !== 'function') {
|
|
433
|
-
logger.trace(
|
|
431
|
+
logger.trace(SKIP_WRAPPING_FUNCTION_MESSAGE, name)
|
|
434
432
|
return original
|
|
435
433
|
}
|
|
436
434
|
|
|
@@ -443,7 +441,7 @@ function wrapSyncFunction(name, recorder, original) {
|
|
|
443
441
|
function wrappedFunction() {
|
|
444
442
|
const transaction = tracer.getTransaction()
|
|
445
443
|
if (!transaction) {
|
|
446
|
-
logger.trace(
|
|
444
|
+
logger.trace(INACTIVE_TRANSACTION_MESSAGE, name)
|
|
447
445
|
return original.apply(this, arguments)
|
|
448
446
|
}
|
|
449
447
|
logger.trace('Creating "%s" sync segment for transaction %s.', name, transaction.id)
|
|
@@ -87,12 +87,10 @@ class TransactionEventAggregator extends EventAggregator {
|
|
|
87
87
|
const secondHalfEventData = secondHalfRawEvents.map(this._rawEventsToValues)
|
|
88
88
|
const secondPayload = [this.runId, secondMetrics, secondHalfEventData]
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
return [
|
|
91
91
|
{ rawData: firstHalfRawEvents, payload: firstPayload },
|
|
92
92
|
{ rawData: secondHalfRawEvents, payload: secondPayload }
|
|
93
93
|
]
|
|
94
|
-
|
|
95
|
-
return eventPayloadPairs
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
_rawEventsToValues(rawEvent) {
|
package/lib/util/byte-limit.js
CHANGED
|
@@ -32,11 +32,9 @@ function compareLength(str, limit) {
|
|
|
32
32
|
* Trims a string value to given byte limit, if necessary.
|
|
33
33
|
*
|
|
34
34
|
* @private
|
|
35
|
-
*
|
|
36
35
|
* @param {string} val - The value to truncate to given byte limit.
|
|
37
36
|
* @param {number} limit - The byte limit
|
|
38
|
-
*
|
|
39
|
-
* @return {string} The truncated value.
|
|
37
|
+
* @returns {string} The truncated value.
|
|
40
38
|
*/
|
|
41
39
|
function truncate(val, limit) {
|
|
42
40
|
// First truncation handles the simple case of only one-byte characters.
|