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,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const logger = require('../logger.js').child({ component: 'name-state' })
|
|
9
|
+
const NAMES = require('../metrics/names')
|
|
10
10
|
|
|
11
11
|
// TODO: Figure out a way to phase out legacy transaction names.
|
|
12
|
-
|
|
12
|
+
const LEGACY_NAMING = {
|
|
13
13
|
Custom: true,
|
|
14
14
|
|
|
15
15
|
Connect: true,
|
|
@@ -45,7 +45,7 @@ NameState.prototype.setName = function setName(prefix, verb, delimiter, path) {
|
|
|
45
45
|
this.setPrefix(prefix)
|
|
46
46
|
this.verb = verb && verb.toUpperCase()
|
|
47
47
|
this.delimiter = delimiter
|
|
48
|
-
this.pathStack = path ? [{path: path, params: null}] : []
|
|
48
|
+
this.pathStack = path ? [{ path: path, params: null }] : []
|
|
49
49
|
this._pathCache = null
|
|
50
50
|
this.markedPath = []
|
|
51
51
|
logger.trace('setName called on name state, path stack now %j', this.pathStack)
|
|
@@ -77,8 +77,7 @@ NameState.prototype.setPrefix = function setPrefix(prefix) {
|
|
|
77
77
|
this.prefix = null
|
|
78
78
|
return
|
|
79
79
|
}
|
|
80
|
-
this.prefix =
|
|
81
|
-
prefix.substring(0, prefix.length - 1) : prefix
|
|
80
|
+
this.prefix = prefix[prefix.length - 1] === '/' ? prefix.substring(0, prefix.length - 1) : prefix
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
/**
|
|
@@ -108,8 +107,8 @@ NameState.prototype.isEmpty = function isEmpty() {
|
|
|
108
107
|
*/
|
|
109
108
|
NameState.prototype.appendPath = function appendPath(path, params) {
|
|
110
109
|
if (!this._frozen && path != null) {
|
|
111
|
-
|
|
112
|
-
this.pathStack.push({path: strPath, params: params || null})
|
|
110
|
+
const strPath = path instanceof RegExp ? path.source : String(path)
|
|
111
|
+
this.pathStack.push({ path: strPath, params: params || null })
|
|
113
112
|
|
|
114
113
|
if (path !== '') {
|
|
115
114
|
this._pathCache = null
|
|
@@ -142,7 +141,7 @@ NameState.prototype.popPath = function popPath(path) {
|
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
this._pathCache = null
|
|
145
|
-
|
|
144
|
+
let pops = 0
|
|
146
145
|
if (path != null) {
|
|
147
146
|
const idx = _findLastIndex(this.pathStack, (a) => a.path === path)
|
|
148
147
|
if (idx !== -1) {
|
|
@@ -157,17 +156,17 @@ NameState.prototype.popPath = function popPath(path) {
|
|
|
157
156
|
}
|
|
158
157
|
|
|
159
158
|
NameState.prototype.getPath = function getPath() {
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
const ps = !this.pathStack.length ? this.markedPath : this.pathStack
|
|
160
|
+
const psLength = ps.length
|
|
162
161
|
if (this._pathCache) {
|
|
163
162
|
return this._pathCache
|
|
164
163
|
} else if (psLength === 0) {
|
|
165
164
|
return null // nameState initialized but never set
|
|
166
165
|
}
|
|
167
166
|
|
|
168
|
-
|
|
169
|
-
for (
|
|
170
|
-
|
|
167
|
+
let path = '/'
|
|
168
|
+
for (let i = 0; i < psLength; ++i) {
|
|
169
|
+
let a = ps[i].path
|
|
171
170
|
if (a && a !== '/') {
|
|
172
171
|
if (a[0] !== '/' && path[path.length - 1] !== '/') {
|
|
173
172
|
path += '/'
|
|
@@ -178,11 +177,11 @@ NameState.prototype.getPath = function getPath() {
|
|
|
178
177
|
}
|
|
179
178
|
}
|
|
180
179
|
|
|
181
|
-
return this._pathCache = path
|
|
180
|
+
return (this._pathCache = path)
|
|
182
181
|
}
|
|
183
182
|
|
|
184
183
|
NameState.prototype.getNameNotFound = function getNameNotFound() {
|
|
185
|
-
|
|
184
|
+
const name = _getName(this, '(not found)')
|
|
186
185
|
if (LEGACY_NAMING.hasOwnProperty(this.prefix)) {
|
|
187
186
|
return name
|
|
188
187
|
}
|
|
@@ -190,7 +189,7 @@ NameState.prototype.getNameNotFound = function getNameNotFound() {
|
|
|
190
189
|
}
|
|
191
190
|
|
|
192
191
|
NameState.prototype.getName = function getName() {
|
|
193
|
-
|
|
192
|
+
const path = this.getPath()
|
|
194
193
|
if (path === null) {
|
|
195
194
|
return null
|
|
196
195
|
}
|
|
@@ -199,7 +198,7 @@ NameState.prototype.getName = function getName() {
|
|
|
199
198
|
}
|
|
200
199
|
|
|
201
200
|
NameState.prototype.getFullName = function getFullName() {
|
|
202
|
-
|
|
201
|
+
const name = this.getName()
|
|
203
202
|
if (LEGACY_NAMING.hasOwnProperty(this.prefix)) {
|
|
204
203
|
return name
|
|
205
204
|
}
|
|
@@ -235,7 +234,7 @@ NameState.prototype.reset = function reset() {
|
|
|
235
234
|
}
|
|
236
235
|
|
|
237
236
|
function _getName(nameState, path) {
|
|
238
|
-
|
|
237
|
+
const verb = nameState.verb ? '/' + nameState.verb : ''
|
|
239
238
|
return (nameState.prefix || '') + verb + (nameState.delimiter || '') + path
|
|
240
239
|
}
|
|
241
240
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
const a = require('async')
|
|
8
|
-
const logger = require('../../logger').child({component: 'Transaction Trace Aggregator'})
|
|
8
|
+
const logger = require('../../logger').child({ component: 'Transaction Trace Aggregator' })
|
|
9
9
|
|
|
10
10
|
/*
|
|
11
11
|
*
|
|
@@ -32,23 +32,22 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
32
32
|
|
|
33
33
|
super(opts, collector)
|
|
34
34
|
/*
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
* From
|
|
36
|
+
*
|
|
37
|
+
* https://newrelic.atlassian.net/wiki/display/eng/Transaction+Trace+Collection+Improvements
|
|
38
|
+
*
|
|
39
|
+
* 5 Transaction Trace Guarantee
|
|
40
|
+
*
|
|
41
|
+
* For the initial experience problem, the Agent will sample up to 1
|
|
42
|
+
* transaction per minute until it has sampled 5 transactions. This
|
|
43
|
+
* guarantees that the agent will always report some transaction traces.
|
|
44
|
+
* There is no time out for this sampling period - the agent always
|
|
45
|
+
* samples until it has collected 5 transactions. The agent doesn't
|
|
46
|
+
* simply report the first 5 transactions that it sees because it's
|
|
47
|
+
* likely (particularly for a local dev test) that all 5 transactions
|
|
48
|
+
* would be associated with one request (a single web page and its
|
|
49
|
+
* resources).
|
|
50
|
+
*/
|
|
52
51
|
|
|
53
52
|
const config = opts.config
|
|
54
53
|
this.reported = 0
|
|
@@ -56,8 +55,7 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
56
55
|
|
|
57
56
|
// Setting up top n capacity.
|
|
58
57
|
this.capacity = 1
|
|
59
|
-
if (config.transaction_tracer &&
|
|
60
|
-
config.transaction_tracer.top_n) {
|
|
58
|
+
if (config.transaction_tracer && config.transaction_tracer.top_n) {
|
|
61
59
|
this.capacity = config.transaction_tracer.top_n
|
|
62
60
|
}
|
|
63
61
|
|
|
@@ -69,22 +67,22 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
* For every five harvest cycles (or "minutes"), if no new slow transactions
|
|
71
|
+
* have been added, reset the requestTime match and allow a new set of five
|
|
72
|
+
* to start populating the Top N Slow Trace list.
|
|
73
|
+
*/
|
|
76
74
|
resetTimingTracker() {
|
|
77
75
|
this.requestTimes = Object.create(null)
|
|
78
76
|
this.noTraceSubmitted = 0
|
|
79
77
|
}
|
|
80
78
|
|
|
81
79
|
/**
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
* Add a trace to the slow trace list, if and only if it fulfills the necessary
|
|
81
|
+
* criteria.
|
|
82
|
+
*
|
|
83
|
+
* @param {Transaction} transaction The transaction, which we need to check
|
|
84
|
+
* apdexT, as well as getting the trace.
|
|
85
|
+
*/
|
|
88
86
|
add(transaction) {
|
|
89
87
|
if (!transaction) {
|
|
90
88
|
return
|
|
@@ -124,8 +122,8 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
124
122
|
}
|
|
125
123
|
|
|
126
124
|
/**
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
* Reset the trace diversity settings.
|
|
126
|
+
*/
|
|
129
127
|
clear() {
|
|
130
128
|
this.trace = null
|
|
131
129
|
this.syntheticsTraces = []
|
|
@@ -184,10 +182,7 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
184
182
|
return null
|
|
185
183
|
}
|
|
186
184
|
|
|
187
|
-
return [
|
|
188
|
-
this.runId,
|
|
189
|
-
traces.map((trace) => trace.generateJSONSync())
|
|
190
|
-
]
|
|
185
|
+
return [this.runId, traces.map((trace) => trace.generateJSONSync())]
|
|
191
186
|
}
|
|
192
187
|
|
|
193
188
|
_toPayload(callback) {
|
|
@@ -209,75 +204,85 @@ class TransactionTraceAggregator extends TraceAggregator {
|
|
|
209
204
|
}
|
|
210
205
|
|
|
211
206
|
/**
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
207
|
+
* Determine whether a new trace is more worth keeping than an old one.
|
|
208
|
+
* This gets called on every single transactionFinished event, so return as
|
|
209
|
+
* quickly as possible and call as few external functions as possible. On the
|
|
210
|
+
* converse, there's some complicated logic here, so spell things out.
|
|
211
|
+
*
|
|
212
|
+
* All specifications are from
|
|
213
|
+
* https://newrelic.atlassian.net/wiki/display/eng/Transaction+Trace+Collection+Improvements
|
|
214
|
+
*
|
|
215
|
+
* @param {string} name Name of this transaction's key metric.
|
|
216
|
+
* @param {number} duration Time the transaction took, in milliseconds.
|
|
217
|
+
* @param {number} apdexT Apdex tolerating threshold, in seconds.
|
|
218
|
+
*/
|
|
224
219
|
isBetter(name, duration, apdexT) {
|
|
225
220
|
/* 1. If the transaction duration is below the tracing threshold, the
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
221
|
+
* transaction is skipped.
|
|
222
|
+
*
|
|
223
|
+
* The threshold for slow traces defaults to apdex_f, which is 4 * apdex_t.
|
|
224
|
+
*/
|
|
230
225
|
const config = this.config.transaction_tracer
|
|
231
226
|
let isOverThreshold
|
|
232
227
|
|
|
233
|
-
if (
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
228
|
+
if (
|
|
229
|
+
config &&
|
|
230
|
+
config.transaction_threshold != null &&
|
|
231
|
+
config.transaction_threshold !== 'apdex_f' &&
|
|
232
|
+
typeof config.transaction_threshold === 'number'
|
|
233
|
+
) {
|
|
237
234
|
isOverThreshold = duration >= config.transaction_threshold * TO_MILLIS
|
|
238
235
|
} else {
|
|
239
236
|
isOverThreshold = duration >= 4 * TO_MILLIS * apdexT
|
|
240
237
|
}
|
|
241
|
-
if (!isOverThreshold)
|
|
238
|
+
if (!isOverThreshold) {
|
|
239
|
+
return false
|
|
240
|
+
}
|
|
242
241
|
|
|
243
242
|
/* 2. If the transaction duration is less than the duration of the current
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
* slow transaction, the transaction is skipped.
|
|
244
|
+
*/
|
|
246
245
|
let slowerThanExisting = true
|
|
247
246
|
if (this.trace) {
|
|
248
247
|
slowerThanExisting = this.trace.getDurationInMillis() < duration
|
|
249
248
|
}
|
|
250
|
-
if (!slowerThanExisting)
|
|
249
|
+
if (!slowerThanExisting) {
|
|
250
|
+
return false
|
|
251
|
+
}
|
|
251
252
|
|
|
252
253
|
/* We always gather some slow transactions at the start, regardless of
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
* the size of Top N. This changes the behavior of the rest of the
|
|
255
|
+
* decision-making process in some subtle ways.
|
|
256
|
+
*/
|
|
256
257
|
const hasMetGuarantee = this.reported >= 5
|
|
257
258
|
|
|
258
259
|
/* 3. If the transaction's name is in the transaction map and its duration
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
* is less than the response time in the map, it is skipped.
|
|
261
|
+
*/
|
|
261
262
|
let slowerThanCaptured = true
|
|
262
263
|
if (hasMetGuarantee) {
|
|
263
264
|
if (this.requestTimes[name]) {
|
|
264
265
|
slowerThanCaptured = this.requestTimes[name] < duration
|
|
265
266
|
}
|
|
266
267
|
}
|
|
267
|
-
if (!slowerThanCaptured)
|
|
268
|
+
if (!slowerThanCaptured) {
|
|
269
|
+
return false
|
|
270
|
+
}
|
|
268
271
|
|
|
269
272
|
/* Not part of enumerated rules, but necessary for Top N support:
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if (
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
* Ensure this name is either already in the request time map
|
|
274
|
+
* or that the map still hasn't hit capacity.
|
|
275
|
+
*/
|
|
276
|
+
if (
|
|
277
|
+
hasMetGuarantee &&
|
|
278
|
+
!this.requestTimes[name] &&
|
|
279
|
+
Object.keys(this.requestTimes).length >= this.capacity
|
|
280
|
+
) {
|
|
276
281
|
return false
|
|
277
282
|
}
|
|
278
283
|
|
|
279
284
|
/* 4. The transaction is held as the slowest transaction.
|
|
280
|
-
|
|
285
|
+
*/
|
|
281
286
|
return true
|
|
282
287
|
}
|
|
283
288
|
}
|
|
@@ -36,7 +36,7 @@ class ExclusiveCalculator {
|
|
|
36
36
|
segment: segment,
|
|
37
37
|
childPairs: []
|
|
38
38
|
})
|
|
39
|
-
for (
|
|
39
|
+
for (let i = children.length - 1; i >= 0; --i) {
|
|
40
40
|
this.toProcess.push(children[i])
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -60,7 +60,7 @@ class ExclusiveCalculator {
|
|
|
60
60
|
// of children left to process is 0).
|
|
61
61
|
while (--parent.childrenLeft === 0) {
|
|
62
62
|
// pull off the finished parent and assign the exclusive duration
|
|
63
|
-
const {segment: finishedParent, childPairs} = this.parentStack.pop()
|
|
63
|
+
const { segment: finishedParent, childPairs } = this.parentStack.pop()
|
|
64
64
|
const timer = finishedParent.timer
|
|
65
65
|
const finishedEnd = timer.getDurationInMillis() + timer.start
|
|
66
66
|
let duration = finishedParent.getDurationInMillis()
|
|
@@ -103,20 +103,17 @@ function merge(first, second) {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
const res = []
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
let resIdx = 0
|
|
107
|
+
let firstIdx = 0
|
|
108
|
+
let secondIdx = 0
|
|
109
109
|
// N.B. this is destructive, it will be updating the end times for range arrays in
|
|
110
110
|
// the input arrays. If we need to reuse these arrays for anything, this behavior
|
|
111
111
|
// must be changed.
|
|
112
|
-
|
|
113
|
-
? first[firstIdx++]
|
|
114
|
-
: second[secondIdx++]
|
|
112
|
+
let currInterval =
|
|
113
|
+
first[firstIdx][0] < second[secondIdx][0] ? first[firstIdx++] : second[secondIdx++]
|
|
115
114
|
|
|
116
115
|
while (firstIdx < first.length && secondIdx < second.length) {
|
|
117
|
-
|
|
118
|
-
? first[firstIdx++]
|
|
119
|
-
: second[secondIdx++]
|
|
116
|
+
const next = first[firstIdx][0] < second[secondIdx][0] ? first[firstIdx++] : second[secondIdx++]
|
|
120
117
|
if (next[0] <= currInterval[1]) {
|
|
121
118
|
// if the segment overlaps, update the end of the current merged segment
|
|
122
119
|
currInterval[1] = Math.max(next[1], currInterval[1])
|
|
@@ -127,7 +124,6 @@ function merge(first, second) {
|
|
|
127
124
|
}
|
|
128
125
|
}
|
|
129
126
|
|
|
130
|
-
|
|
131
127
|
const firstIsRemainder = firstIdx !== first.length
|
|
132
128
|
const remainder = firstIsRemainder ? first : second
|
|
133
129
|
let remainderIdx = firstIsRemainder ? firstIdx : secondIdx
|
|
@@ -140,7 +136,7 @@ function merge(first, second) {
|
|
|
140
136
|
res[resIdx++] = currInterval
|
|
141
137
|
|
|
142
138
|
// append the remaining non-overlapping ranges
|
|
143
|
-
for (;remainderIdx < remainder.length; ++remainderIdx) {
|
|
139
|
+
for (; remainderIdx < remainder.length; ++remainderIdx) {
|
|
144
140
|
res[resIdx++] = remainder[remainderIdx]
|
|
145
141
|
}
|
|
146
142
|
|
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
const codec = require('../../util/codec')
|
|
9
|
+
const Segment = require('./segment')
|
|
10
|
+
const { Attributes, MAXIMUM_CUSTOM_ATTRIBUTES } = require('../../attributes')
|
|
11
|
+
const logger = require('../../logger').child({ component: 'trace' })
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
var FROM_MILLIS = 1e-3
|
|
13
|
+
const { DESTINATIONS } = require('../../config/attribute-filter')
|
|
14
|
+
const FROM_MILLIS = 1e-3
|
|
16
15
|
const ATTRIBUTE_SCOPE = 'transaction'
|
|
17
16
|
|
|
18
17
|
const REQUEST_URI_KEY = 'request.uri'
|
|
@@ -25,7 +24,9 @@ const UNKNOWN_URI_PLACEHOLDER = '/Unknown'
|
|
|
25
24
|
* @param {Transaction} transaction The transaction bound to the trace.
|
|
26
25
|
*/
|
|
27
26
|
function Trace(transaction) {
|
|
28
|
-
if (!transaction)
|
|
27
|
+
if (!transaction) {
|
|
28
|
+
throw new Error('All traces must be associated with a transaction.')
|
|
29
|
+
}
|
|
29
30
|
|
|
30
31
|
this.transaction = transaction
|
|
31
32
|
|
|
@@ -40,14 +41,10 @@ function Trace(transaction) {
|
|
|
40
41
|
this.attributes = new Attributes(ATTRIBUTE_SCOPE)
|
|
41
42
|
|
|
42
43
|
// sending displayName if set by user
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
const displayName = transaction.agent.config.getDisplayHost()
|
|
45
|
+
const hostName = transaction.agent.config.getHostnameSafe()
|
|
45
46
|
if (displayName !== hostName) {
|
|
46
|
-
this.attributes.addAttribute(
|
|
47
|
-
DESTINATIONS.TRANS_COMMON,
|
|
48
|
-
'host.displayName',
|
|
49
|
-
displayName
|
|
50
|
-
)
|
|
47
|
+
this.attributes.addAttribute(DESTINATIONS.TRANS_COMMON, 'host.displayName', displayName)
|
|
51
48
|
|
|
52
49
|
this.displayName = displayName
|
|
53
50
|
}
|
|
@@ -85,7 +82,7 @@ Trace.prototype.generateSpanEvents = function generateSpanEvents() {
|
|
|
85
82
|
config.span_events.enabled &&
|
|
86
83
|
config.distributed_tracing.enabled
|
|
87
84
|
) {
|
|
88
|
-
|
|
85
|
+
const toProcess = []
|
|
89
86
|
|
|
90
87
|
// Root segment does not become a span, so we need to process it separately.
|
|
91
88
|
const spanAggregator = this.transaction.agent.spanEventAggregator
|
|
@@ -116,8 +113,8 @@ Trace.prototype.generateSpanEvents = function generateSpanEvents() {
|
|
|
116
113
|
}
|
|
117
114
|
|
|
118
115
|
while (toProcess.length) {
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
const segmentInfo = toProcess.pop()
|
|
117
|
+
const segment = segmentInfo.segment
|
|
121
118
|
|
|
122
119
|
// Even though at some point we might want to stop adding events because all the priorities
|
|
123
120
|
// should be the same, we need to count the spans as seen.
|
|
@@ -198,7 +195,6 @@ Trace.prototype.getExclusiveDurationInMillis = function getExclusiveDurationInMi
|
|
|
198
195
|
return this.root.getExclusiveDurationInMillis()
|
|
199
196
|
}
|
|
200
197
|
|
|
201
|
-
|
|
202
198
|
/**
|
|
203
199
|
* The duration of all segments in a transaction trace. The root is not
|
|
204
200
|
* accounted for, since it doesn't represent a unit of work.
|
|
@@ -207,18 +203,24 @@ Trace.prototype.getExclusiveDurationInMillis = function getExclusiveDurationInMi
|
|
|
207
203
|
* milliseconds
|
|
208
204
|
*/
|
|
209
205
|
Trace.prototype.getTotalTimeDurationInMillis = function getTotalTimeDurationInMillis() {
|
|
210
|
-
if (this.totalTimeCache !== null)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
206
|
+
if (this.totalTimeCache !== null) {
|
|
207
|
+
return this.totalTimeCache
|
|
208
|
+
}
|
|
209
|
+
if (this.root.children.length === 0) {
|
|
210
|
+
return 0
|
|
211
|
+
}
|
|
212
|
+
let segments = this.root.getChildren()
|
|
213
|
+
let totalTimeInMillis = 0
|
|
214
214
|
|
|
215
215
|
while (segments.length !== 0) {
|
|
216
|
-
|
|
216
|
+
const segment = segments.pop()
|
|
217
217
|
totalTimeInMillis += segment.getExclusiveDurationInMillis()
|
|
218
218
|
segments = segments.concat(segment.getChildren())
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
if (!this.transaction.isActive())
|
|
221
|
+
if (!this.transaction.isActive()) {
|
|
222
|
+
this.totalTimeCache = totalTimeInMillis
|
|
223
|
+
}
|
|
222
224
|
return totalTimeInMillis
|
|
223
225
|
}
|
|
224
226
|
|
|
@@ -299,15 +301,15 @@ Trace.prototype._generatePayload = function _generatePayload(data) {
|
|
|
299
301
|
|
|
300
302
|
return [
|
|
301
303
|
this.root.timer.start, // start
|
|
302
|
-
this.transaction.getResponseTimeInMillis(),
|
|
303
|
-
this.transaction.getFullName(),
|
|
304
|
-
requestUri,
|
|
305
|
-
data,
|
|
306
|
-
this.transaction.id,
|
|
307
|
-
null,
|
|
308
|
-
false,
|
|
309
|
-
null,
|
|
310
|
-
syntheticsResourceId
|
|
304
|
+
this.transaction.getResponseTimeInMillis(), // response time
|
|
305
|
+
this.transaction.getFullName(), // path
|
|
306
|
+
requestUri, // request.uri
|
|
307
|
+
data, // encodedCompressedData
|
|
308
|
+
this.transaction.id, // guid
|
|
309
|
+
null, // reserved for future use
|
|
310
|
+
false, // forcePersist
|
|
311
|
+
null, // xraySessionId
|
|
312
|
+
syntheticsResourceId // synthetics resource id
|
|
311
313
|
]
|
|
312
314
|
}
|
|
313
315
|
|
|
@@ -353,7 +355,7 @@ Trace.prototype._serializeTrace = function _serializeTrace() {
|
|
|
353
355
|
}, // moved to userAttributes
|
|
354
356
|
this.root.toJSON(),
|
|
355
357
|
attributes,
|
|
356
|
-
[]
|
|
358
|
+
[] // FIXME: parameter groups
|
|
357
359
|
]
|
|
358
360
|
}
|
|
359
361
|
|