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,12 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
const logger = require('../logger')
|
|
9
|
-
let spanLogger = null
|
|
8
|
+
const logger = require('../logger').child({ component: 'span_aggregator' })
|
|
10
9
|
const EventAggregator = require('../aggregators/event-aggregator')
|
|
11
10
|
const SpanEvent = require('./span-event')
|
|
12
11
|
const NAMES = require('../metrics/names')
|
|
13
|
-
|
|
12
|
+
|
|
13
|
+
const DEFAULT_SPAN_EVENT_LIMIT = 2000
|
|
14
|
+
// Used only when server value missing
|
|
15
|
+
const SPAN_EVENT_FALLBACK_MAX_LIMIT = 10000
|
|
14
16
|
|
|
15
17
|
class SpanEventAggregator extends EventAggregator {
|
|
16
18
|
constructor(opts, collector, metrics) {
|
|
@@ -18,8 +20,6 @@ class SpanEventAggregator extends EventAggregator {
|
|
|
18
20
|
opts.method = opts.method || 'span_event_data'
|
|
19
21
|
opts.metricNames = opts.metricNames || NAMES.SPAN_EVENTS
|
|
20
22
|
|
|
21
|
-
spanLogger = logger.child({component: 'span_aggregator'})
|
|
22
|
-
|
|
23
23
|
super(opts, collector, metrics)
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -27,7 +27,7 @@ class SpanEventAggregator extends EventAggregator {
|
|
|
27
27
|
const events = this.events
|
|
28
28
|
|
|
29
29
|
if (events.length === 0) {
|
|
30
|
-
|
|
30
|
+
logger.debug('No span events to send.')
|
|
31
31
|
return
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -46,11 +46,14 @@ class SpanEventAggregator extends EventAggregator {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
send() {
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
if (logger.traceEnabled()) {
|
|
50
|
+
logger.trace(
|
|
51
|
+
{
|
|
52
|
+
spansCollected: this.length,
|
|
53
|
+
spansSeen: this.seen
|
|
54
|
+
},
|
|
55
|
+
'Entity stats on span harvest'
|
|
56
|
+
)
|
|
54
57
|
}
|
|
55
58
|
super.send()
|
|
56
59
|
}
|
|
@@ -61,7 +64,7 @@ class SpanEventAggregator extends EventAggregator {
|
|
|
61
64
|
* @param {TraceSegment} segment - The segment to add.
|
|
62
65
|
* @param {string} [parentId=null] - The GUID of the parent span.
|
|
63
66
|
*
|
|
64
|
-
* @return {
|
|
67
|
+
* @return {boolean} True if the segment was added, or false if it was discarded.
|
|
65
68
|
*/
|
|
66
69
|
addSegment(segment, parentId, isRoot) {
|
|
67
70
|
// Check if the priority would be accepted before creating the event object.
|
|
@@ -76,7 +79,59 @@ class SpanEventAggregator extends EventAggregator {
|
|
|
76
79
|
const span = SpanEvent.fromSegment(segment, parentId || null, isRoot)
|
|
77
80
|
return this.add(span, tx.priority)
|
|
78
81
|
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Reconfigure the `SpanEventAggregator` based on values from server
|
|
85
|
+
*
|
|
86
|
+
* @param {Config} config
|
|
87
|
+
*/
|
|
88
|
+
reconfigure(config) {
|
|
89
|
+
super.reconfigure(config)
|
|
90
|
+
|
|
91
|
+
const { periodMs, limit } = this._getValidSpanConfiguration(config)
|
|
92
|
+
|
|
93
|
+
this.periodMs = periodMs
|
|
94
|
+
this.limit = limit
|
|
95
|
+
this._metrics.getOrCreateMetric(this._metricNames.LIMIT).recordValue(this.limit)
|
|
96
|
+
this._items.setLimit(this.limit)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Retrieves report period and harvest limits defined in `span_event_harvest_config`.
|
|
101
|
+
* When no `span_event_harvest_config` has been received from the server, applies an
|
|
102
|
+
* agent-defined fallback maximum to protect against collecting and sending too many spans.
|
|
103
|
+
*
|
|
104
|
+
* @param {Config} config
|
|
105
|
+
*/
|
|
106
|
+
_getValidSpanConfiguration(config) {
|
|
107
|
+
const spanHarvestConfig = config.span_event_harvest_config
|
|
108
|
+
if (spanHarvestConfig) {
|
|
109
|
+
logger.trace('Using span_event_harvest_config values.')
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
periodMs: spanHarvestConfig.report_period_ms,
|
|
113
|
+
limit: spanHarvestConfig.harvest_limit
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const configuredLimit = config.span_events.max_samples_stored || DEFAULT_SPAN_EVENT_LIMIT
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
periodMs: this.defaultPeriod,
|
|
121
|
+
limit: _enforceMaxLimit(configuredLimit, SPAN_EVENT_FALLBACK_MAX_LIMIT)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function _enforceMaxLimit(currentLimit, maxLimit) {
|
|
127
|
+
let spanLimit = currentLimit
|
|
128
|
+
if (spanLimit > maxLimit) {
|
|
129
|
+
spanLimit = maxLimit
|
|
130
|
+
|
|
131
|
+
logger.debug('Using maximum allowed span event limit of %s', maxLimit)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return spanLimit
|
|
79
135
|
}
|
|
80
136
|
|
|
81
137
|
module.exports = SpanEventAggregator
|
|
82
|
-
module.exports.LIMIT = LIMIT
|
package/lib/spans/span-event.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const Config = require('../config')
|
|
9
|
-
const {truncate} = require('../util/byte-limit')
|
|
9
|
+
const { truncate } = require('../util/byte-limit')
|
|
10
10
|
|
|
11
|
-
const {DESTINATIONS} = require('../config/attribute-filter')
|
|
11
|
+
const { DESTINATIONS } = require('../config/attribute-filter')
|
|
12
12
|
|
|
13
13
|
const HTTP_LIBRARY = 'http'
|
|
14
14
|
const CLIENT_KIND = 'client'
|
|
@@ -149,15 +149,13 @@ class SpanEvent {
|
|
|
149
149
|
toJSON() {
|
|
150
150
|
return [
|
|
151
151
|
_filterNulls(this.intrinsics),
|
|
152
|
-
this.customAttributes ?
|
|
153
|
-
_filterNulls(this.customAttributes) :
|
|
154
|
-
EMPTY_USER_ATTRS,
|
|
152
|
+
this.customAttributes ? _filterNulls(this.customAttributes) : EMPTY_USER_ATTRS,
|
|
155
153
|
_filterNulls(this.attributes)
|
|
156
154
|
]
|
|
157
155
|
}
|
|
158
156
|
|
|
159
157
|
addCustomAttribute(key, value, truncateExempt = false) {
|
|
160
|
-
const {attributeFilter} = Config.getInstance()
|
|
158
|
+
const { attributeFilter } = Config.getInstance()
|
|
161
159
|
const dest = attributeFilter.filterSegment(DESTINATIONS.SPAN_EVENT, key)
|
|
162
160
|
if (dest & DESTINATIONS.SPAN_EVENT) {
|
|
163
161
|
this.customAttributes[key] = truncateExempt ? value : _truncate(value)
|
|
@@ -165,7 +163,7 @@ class SpanEvent {
|
|
|
165
163
|
}
|
|
166
164
|
|
|
167
165
|
addAttribute(key, value, truncateExempt = false) {
|
|
168
|
-
const {attributeFilter} = Config.getInstance()
|
|
166
|
+
const { attributeFilter } = Config.getInstance()
|
|
169
167
|
const dest = attributeFilter.filterSegment(DESTINATIONS.SPAN_EVENT, key)
|
|
170
168
|
if (dest & DESTINATIONS.SPAN_EVENT) {
|
|
171
169
|
this.attributes[key] = truncateExempt ? value : _truncate(value)
|
|
@@ -276,7 +274,7 @@ function _truncate(val) {
|
|
|
276
274
|
|
|
277
275
|
function _filterNulls(obj) {
|
|
278
276
|
const out = Object.create(null)
|
|
279
|
-
for (
|
|
277
|
+
for (const key in obj) {
|
|
280
278
|
if (obj[key] != null) {
|
|
281
279
|
out[key] = obj[key]
|
|
282
280
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
const logger = require('../logger').child({component: 'span-streamer'})
|
|
8
|
+
const logger = require('../logger').child({ component: 'span-streamer' })
|
|
9
9
|
const NAMES = require('../metrics/names').INFINITE_TRACING
|
|
10
10
|
|
|
11
11
|
const SPAN_DROP_MSG_INTERVAL_MS = 30000
|
|
@@ -14,25 +14,25 @@ const SPAN_DROP_MSG =
|
|
|
14
14
|
`Will not warn again for ${SPAN_DROP_MSG_INTERVAL_MS / 1000} seconds.`
|
|
15
15
|
|
|
16
16
|
class SpanStreamer {
|
|
17
|
-
constructor(
|
|
17
|
+
constructor(licenseKey, connection, metrics, queueSize) {
|
|
18
18
|
this.stream = null
|
|
19
|
-
this.license_key =
|
|
19
|
+
this.license_key = licenseKey
|
|
20
20
|
this.connection = connection
|
|
21
|
-
this.queue_size =
|
|
21
|
+
this.queue_size = queueSize
|
|
22
22
|
this.spans = []
|
|
23
23
|
this._metrics = metrics
|
|
24
24
|
this._writable = false
|
|
25
25
|
|
|
26
26
|
// 'connected' indicates a safely writeable stream.
|
|
27
27
|
// May still be mid-connect to gRPC server.
|
|
28
|
-
this.connection.on('connected', (stream) =>{
|
|
28
|
+
this.connection.on('connected', (stream) => {
|
|
29
29
|
logger.info('Span streamer connected')
|
|
30
30
|
this.stream = stream
|
|
31
31
|
this._writable = true
|
|
32
32
|
this.sendQueue()
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
this.connection.on('disconnected', () =>{
|
|
35
|
+
this.connection.on('disconnected', () => {
|
|
36
36
|
logger.info('Span streamer disconnected')
|
|
37
37
|
this.stream = null
|
|
38
38
|
this._writable = false
|
|
@@ -110,8 +110,7 @@ class SpanStreamer {
|
|
|
110
110
|
// average time to drain from when we first notice.
|
|
111
111
|
const drainCompleted = Date.now()
|
|
112
112
|
const drainDurationMs = drainCompleted - waitDrainStart
|
|
113
|
-
this._metrics.getOrCreateMetric(NAMES.DRAIN_DURATION)
|
|
114
|
-
.recordValue(drainDurationMs / 1000)
|
|
113
|
+
this._metrics.getOrCreateMetric(NAMES.DRAIN_DURATION).recordValue(drainDurationMs / 1000)
|
|
115
114
|
|
|
116
115
|
// Once the 'drain' event fires we can begin writing to the stream again
|
|
117
116
|
this._writable = true
|
|
@@ -131,18 +130,11 @@ class SpanStreamer {
|
|
|
131
130
|
this.send(nextObject.toStreamingFormat())
|
|
132
131
|
}
|
|
133
132
|
|
|
134
|
-
logger.trace(
|
|
135
|
-
'Finished sending spans from queue. Items left in queue: %s',
|
|
136
|
-
this.spans.length
|
|
137
|
-
)
|
|
133
|
+
logger.trace('Finished sending spans from queue. Items left in queue: %s', this.spans.length)
|
|
138
134
|
}
|
|
139
135
|
|
|
140
|
-
connect(
|
|
141
|
-
this.connection.setConnectionDetails(
|
|
142
|
-
this.license_key,
|
|
143
|
-
agent_run_id,
|
|
144
|
-
requestHeadersMap
|
|
145
|
-
)
|
|
136
|
+
connect(agentRunId, requestHeadersMap) {
|
|
137
|
+
this.connection.setConnectionDetails(this.license_key, agentRunId, requestHeadersMap)
|
|
146
138
|
|
|
147
139
|
this.connection.connectSpans()
|
|
148
140
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const Aggregator = require('../aggregators/base-aggregator')
|
|
9
9
|
const StreamingSpanEvent = require('./streaming-span-event')
|
|
10
|
-
const logger = require('../logger').child({component: 'streaming-span-event-aggregator'})
|
|
10
|
+
const logger = require('../logger').child({ component: 'streaming-span-event-aggregator' })
|
|
11
11
|
|
|
12
12
|
const SEND_WARNING =
|
|
13
13
|
'send() is not currently supported on streaming span event aggregator. ' +
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const StreamingSpanAttributes = require('./streaming-span-attributes')
|
|
9
|
-
const {truncate} = require('../util/byte-limit')
|
|
9
|
+
const { truncate } = require('../util/byte-limit')
|
|
10
10
|
const Config = require('../config')
|
|
11
11
|
|
|
12
|
-
const {DESTINATIONS} = require('../config/attribute-filter')
|
|
12
|
+
const { DESTINATIONS } = require('../config/attribute-filter')
|
|
13
13
|
|
|
14
14
|
const HTTP_LIBRARY = 'http'
|
|
15
15
|
const CLIENT_KIND = 'client'
|
|
@@ -88,7 +88,7 @@ class StreamingSpanEvent {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
_checkFilter(key) {
|
|
91
|
-
const {attributeFilter} = Config.getInstance()
|
|
91
|
+
const { attributeFilter } = Config.getInstance()
|
|
92
92
|
const dest = attributeFilter.filterSegment(DESTINATIONS.SPAN_EVENT, key)
|
|
93
93
|
return dest & DESTINATIONS.SPAN_EVENT
|
|
94
94
|
}
|
|
@@ -128,7 +128,7 @@ class StreamingSpanEvent {
|
|
|
128
128
|
let span = null
|
|
129
129
|
if (StreamingHttpSpanEvent.isHttpSegment(segment)) {
|
|
130
130
|
span = new StreamingHttpSpanEvent(traceId, agentAttributes, customAttributes)
|
|
131
|
-
}
|
|
131
|
+
} else if (StreamingDatastoreSpanEvent.isDatastoreSegment(segment)) {
|
|
132
132
|
span = new StreamingDatastoreSpanEvent(traceId, agentAttributes, customAttributes)
|
|
133
133
|
} else {
|
|
134
134
|
span = new StreamingSpanEvent(traceId, agentAttributes, customAttributes)
|
package/lib/stats/apdex.js
CHANGED
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
* CONSTANTS
|
|
11
11
|
*
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const FROM_MILLIS = 1e-3
|
|
15
14
|
|
|
16
15
|
function ApdexStats(apdexT) {
|
|
17
16
|
if (!apdexT && apdexT !== 0) {
|
|
@@ -25,7 +24,7 @@ function ApdexStats(apdexT) {
|
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
ApdexStats.prototype.recordValue = function recordValue(time, overrideApdex) {
|
|
28
|
-
|
|
27
|
+
const apdexT = overrideApdex || this.apdexT
|
|
29
28
|
if (time <= apdexT) {
|
|
30
29
|
++this.satisfying
|
|
31
30
|
} else if (time <= 4 * apdexT) {
|
|
@@ -35,8 +34,10 @@ ApdexStats.prototype.recordValue = function recordValue(time, overrideApdex) {
|
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
ApdexStats.prototype.recordValueInMillis =
|
|
39
|
-
|
|
37
|
+
ApdexStats.prototype.recordValueInMillis = function recordValueInMillis(
|
|
38
|
+
timeInMillis,
|
|
39
|
+
overrideApdex
|
|
40
|
+
) {
|
|
40
41
|
this.recordValue(timeInMillis * FROM_MILLIS, overrideApdex * FROM_MILLIS)
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -71,14 +72,7 @@ ApdexStats.prototype.merge = function merge(other) {
|
|
|
71
72
|
* load times, respectively.
|
|
72
73
|
*/
|
|
73
74
|
ApdexStats.prototype.toJSON = function toJSON() {
|
|
74
|
-
return [
|
|
75
|
-
this.satisfying,
|
|
76
|
-
this.tolerating,
|
|
77
|
-
this.frustrating,
|
|
78
|
-
this.apdexT,
|
|
79
|
-
this.apdexT,
|
|
80
|
-
0
|
|
81
|
-
]
|
|
75
|
+
return [this.satisfying, this.tolerating, this.frustrating, this.apdexT, this.apdexT, 0]
|
|
82
76
|
}
|
|
83
77
|
|
|
84
78
|
module.exports = ApdexStats
|
package/lib/stats/index.js
CHANGED
|
@@ -10,9 +10,8 @@
|
|
|
10
10
|
* CONSTANTS
|
|
11
11
|
*
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const BYTES_PER_MB = 1024 * 1024
|
|
14
|
+
const FROM_MILLIS = 1e-3
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Simple container for tracking running statistics for a metric.
|
|
@@ -35,8 +34,12 @@ function Stats() {
|
|
|
35
34
|
*/
|
|
36
35
|
Stats.prototype.recordValue = function recordValue(totalTime, exclusiveTime) {
|
|
37
36
|
// even if a caller messes up, don't break everything else
|
|
38
|
-
if (totalTime !== 0 && !totalTime)
|
|
39
|
-
|
|
37
|
+
if (totalTime !== 0 && !totalTime) {
|
|
38
|
+
totalTime = 0
|
|
39
|
+
}
|
|
40
|
+
if (exclusiveTime !== 0 && !exclusiveTime) {
|
|
41
|
+
exclusiveTime = totalTime
|
|
42
|
+
}
|
|
40
43
|
|
|
41
44
|
if (this.callCount > 0) {
|
|
42
45
|
this.min = Math.min(totalTime, this.min)
|
|
@@ -45,7 +48,7 @@ Stats.prototype.recordValue = function recordValue(totalTime, exclusiveTime) {
|
|
|
45
48
|
}
|
|
46
49
|
this.max = Math.max(totalTime, this.max)
|
|
47
50
|
|
|
48
|
-
this.sumOfSquares +=
|
|
51
|
+
this.sumOfSquares += totalTime * totalTime
|
|
49
52
|
++this.callCount
|
|
50
53
|
this.total += totalTime
|
|
51
54
|
this.totalExclusive += exclusiveTime
|
|
@@ -57,10 +60,7 @@ Stats.prototype.recordValue = function recordValue(totalTime, exclusiveTime) {
|
|
|
57
60
|
*/
|
|
58
61
|
Stats.prototype.recordValueInMillis = recordValueInMillis
|
|
59
62
|
function recordValueInMillis(totalTime, exclusiveTime) {
|
|
60
|
-
this.recordValue(
|
|
61
|
-
totalTime * FROM_MILLIS,
|
|
62
|
-
exclusiveTime >= 0 ? exclusiveTime * FROM_MILLIS : null
|
|
63
|
-
)
|
|
63
|
+
this.recordValue(totalTime * FROM_MILLIS, exclusiveTime >= 0 ? exclusiveTime * FROM_MILLIS : null)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
Stats.prototype.recordValueInBytes = function recordValueInBytes(bytes, exclusiveBytes) {
|
|
@@ -69,7 +69,9 @@ Stats.prototype.recordValueInBytes = function recordValueInBytes(bytes, exclusiv
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
Stats.prototype.incrementCallCount = function incrementCallCount(count) {
|
|
72
|
-
if (typeof count === 'undefined')
|
|
72
|
+
if (typeof count === 'undefined') {
|
|
73
|
+
count = 1
|
|
74
|
+
}
|
|
73
75
|
this.callCount += count
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -113,14 +115,7 @@ Stats.prototype.merge = function merge(other) {
|
|
|
113
115
|
* running sum of squares.
|
|
114
116
|
*/
|
|
115
117
|
Stats.prototype.toJSON = function toJSON() {
|
|
116
|
-
return [
|
|
117
|
-
this.callCount,
|
|
118
|
-
this.total,
|
|
119
|
-
this.totalExclusive,
|
|
120
|
-
this.min,
|
|
121
|
-
this.max,
|
|
122
|
-
this.sumOfSquares
|
|
123
|
-
]
|
|
118
|
+
return [this.callCount, this.total, this.totalExclusive, this.min, this.max, this.sumOfSquares]
|
|
124
119
|
}
|
|
125
120
|
|
|
126
121
|
module.exports = Stats
|
package/lib/system-info.js
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
const exec = require('child_process').exec
|
|
9
|
+
const readProc = require('./utilization/common').readProc
|
|
10
|
+
const getBootId = require('./utilization/docker-info').getBootId
|
|
11
|
+
const utilization = require('./utilization')
|
|
12
|
+
const logger = require('./logger.js').child({ component: 'system-info' })
|
|
13
|
+
const os = require('os')
|
|
14
|
+
const parseCpuInfo = require('./parse-proc-cpuinfo')
|
|
15
|
+
const parseMemInfo = require('./parse-proc-meminfo')
|
|
16
|
+
const platform = os.platform()
|
|
17
17
|
|
|
18
18
|
module.exports = fetchSystemInfo
|
|
19
19
|
|
|
@@ -22,19 +22,19 @@ function isInteger(i) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function fetchSystemInfo(agent, callback) {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const config = agent.config
|
|
26
|
+
const systemInfo = {
|
|
27
27
|
processorArch: os.arch()
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
const utilizationConfig = Object.create(null)
|
|
31
31
|
if (config.utilization) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const configProcessors = config.utilization.logical_processors
|
|
33
|
+
const configRam = config.utilization.total_ram_mib
|
|
34
|
+
const configHostname = config.utilization.billing_hostname
|
|
35
35
|
|
|
36
36
|
if (configProcessors) {
|
|
37
|
-
|
|
37
|
+
const parsedConfigProcessors = parseFloat(configProcessors, 10)
|
|
38
38
|
if (!isNaN(parsedConfigProcessors) && isInteger(parsedConfigProcessors)) {
|
|
39
39
|
utilizationConfig.logical_processors = parsedConfigProcessors
|
|
40
40
|
} else {
|
|
@@ -46,7 +46,7 @@ function fetchSystemInfo(agent, callback) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
if (configRam) {
|
|
49
|
-
|
|
49
|
+
const parsedConfigRam = parseFloat(configRam, 10)
|
|
50
50
|
if (!isNaN(parsedConfigRam) && isInteger(parsedConfigRam)) {
|
|
51
51
|
utilizationConfig.total_ram_mib = parsedConfigRam
|
|
52
52
|
} else {
|
|
@@ -73,8 +73,8 @@ function fetchSystemInfo(agent, callback) {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
let tasksDone = 0
|
|
77
|
+
const numTasks = 5
|
|
78
78
|
function finishedResponse() {
|
|
79
79
|
if (++tasksDone === numTasks) {
|
|
80
80
|
callback(null, systemInfo)
|
|
@@ -111,7 +111,7 @@ function fetchSystemInfo(agent, callback) {
|
|
|
111
111
|
|
|
112
112
|
// placed on module for mocking purposes in tests
|
|
113
113
|
module.exports._getProcessorStats = function getProcessorStats(callback) {
|
|
114
|
-
|
|
114
|
+
const processorStats = {
|
|
115
115
|
logical: null,
|
|
116
116
|
cores: null,
|
|
117
117
|
packages: null
|
|
@@ -127,7 +127,7 @@ module.exports._getProcessorStats = function getProcessorStats(callback) {
|
|
|
127
127
|
processorStats.cores = parseFloat(cores, 10)
|
|
128
128
|
processorStats.packages = parseFloat(packages, 10)
|
|
129
129
|
|
|
130
|
-
for (
|
|
130
|
+
for (const key in processorStats) {
|
|
131
131
|
if (!processorStats[key] || !isInteger(processorStats[key])) {
|
|
132
132
|
processorStats[key] = null
|
|
133
133
|
}
|
|
@@ -193,14 +193,18 @@ function getKernelVersion(callback) {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
function getSysctlValue(names, callback) {
|
|
196
|
-
if (!names)
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
if (!names) {
|
|
197
|
+
return callback(null)
|
|
198
|
+
}
|
|
199
|
+
let returned = false
|
|
200
|
+
let ran = 0
|
|
199
201
|
names.forEach(function sysctlName(name) {
|
|
200
202
|
exec('sysctl -n ' + name, respond)
|
|
201
203
|
|
|
202
204
|
function respond(err, stdout, stderr) {
|
|
203
|
-
if (returned)
|
|
205
|
+
if (returned) {
|
|
206
|
+
return
|
|
207
|
+
}
|
|
204
208
|
if (err) {
|
|
205
209
|
logger.debug('Error when trying to run: sysctl -n %s: %s', name, err.message)
|
|
206
210
|
callback(null)
|
package/lib/timer.js
CHANGED
|
@@ -16,14 +16,13 @@
|
|
|
16
16
|
* are set, but the timer has not yet been harvested).
|
|
17
17
|
* DEAD timer has been harvested and can only have its duration read.
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const PENDING = 1
|
|
20
|
+
const RUNNING = 2
|
|
21
|
+
const STOPPED = 3
|
|
23
22
|
|
|
24
23
|
function hrToMillis(hr) {
|
|
25
24
|
// process.hrTime gives you [second, nanosecond] duration pairs
|
|
26
|
-
return
|
|
25
|
+
return hr[0] * 1e3 + hr[1] / 1e6
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
/**
|
|
@@ -45,7 +44,9 @@ function Timer() {
|
|
|
45
44
|
* Uses process.hrtime if available, Date.now() otherwise.
|
|
46
45
|
*/
|
|
47
46
|
Timer.prototype.begin = function begin() {
|
|
48
|
-
if (this.state > PENDING)
|
|
47
|
+
if (this.state > PENDING) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
49
50
|
|
|
50
51
|
this.start = Date.now()
|
|
51
52
|
this.hrstart = process.hrtime()
|
|
@@ -56,8 +57,12 @@ Timer.prototype.begin = function begin() {
|
|
|
56
57
|
* End measurement.
|
|
57
58
|
*/
|
|
58
59
|
Timer.prototype.end = function end() {
|
|
59
|
-
if (this.state > RUNNING)
|
|
60
|
-
|
|
60
|
+
if (this.state > RUNNING) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
if (this.state === PENDING) {
|
|
64
|
+
this.begin()
|
|
65
|
+
}
|
|
61
66
|
this.hrDuration = process.hrtime(this.hrstart)
|
|
62
67
|
this.touched = true
|
|
63
68
|
this.state = STOPPED
|
|
@@ -68,8 +73,12 @@ Timer.prototype.end = function end() {
|
|
|
68
73
|
*/
|
|
69
74
|
Timer.prototype.touch = function touch() {
|
|
70
75
|
this.touched = true
|
|
71
|
-
if (this.state > RUNNING)
|
|
72
|
-
|
|
76
|
+
if (this.state > RUNNING) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
if (this.state === PENDING) {
|
|
80
|
+
this.begin()
|
|
81
|
+
}
|
|
73
82
|
|
|
74
83
|
this.hrDuration = process.hrtime(this.hrstart)
|
|
75
84
|
}
|
|
@@ -79,12 +88,18 @@ Timer.prototype.touch = function touch() {
|
|
|
79
88
|
* "now". Returns a boolean indicating whether the end time changed.
|
|
80
89
|
*/
|
|
81
90
|
Timer.prototype.softEnd = function softEnd() {
|
|
82
|
-
if (this.state > RUNNING)
|
|
83
|
-
|
|
91
|
+
if (this.state > RUNNING) {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
if (this.state === PENDING) {
|
|
95
|
+
this.begin()
|
|
96
|
+
}
|
|
84
97
|
|
|
85
98
|
this.state = STOPPED
|
|
86
99
|
|
|
87
|
-
if (this.touched)
|
|
100
|
+
if (this.touched) {
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
88
103
|
this.hrDuration = process.hrtime(this.hrstart)
|
|
89
104
|
this.touched = true
|
|
90
105
|
return true
|
|
@@ -146,7 +161,7 @@ Timer.prototype.setDurationInMillis = function setDurationInMillis(duration, sta
|
|
|
146
161
|
// is the assumption being made here. since hrstart isn't used
|
|
147
162
|
// anywhere except to calculate duration, and we are setting duration
|
|
148
163
|
// this is fine.
|
|
149
|
-
this.hrstart = [Math.floor(start / 1e3), start % 1e3 * 1e6]
|
|
164
|
+
this.hrstart = [Math.floor(start / 1e3), (start % 1e3) * 1e6]
|
|
150
165
|
if (start != null) {
|
|
151
166
|
this.start = start
|
|
152
167
|
}
|
|
@@ -157,7 +172,9 @@ Timer.prototype.setDurationInMillis = function setDurationInMillis(duration, sta
|
|
|
157
172
|
* how long it ran (if it's been ended or touched).
|
|
158
173
|
*/
|
|
159
174
|
Timer.prototype.getDurationInMillis = function getDurationInMillis() {
|
|
160
|
-
if (this.state === PENDING)
|
|
175
|
+
if (this.state === PENDING) {
|
|
176
|
+
return 0
|
|
177
|
+
}
|
|
161
178
|
|
|
162
179
|
// only set by setDurationInMillis
|
|
163
180
|
if (this.durationInMillis !== null && this.durationInMillis >= 0) {
|
|
@@ -192,9 +209,8 @@ Timer.prototype.toRange = function toRange() {
|
|
|
192
209
|
*/
|
|
193
210
|
Timer.prototype.startedRelativeTo = function startedRelativeTo(other) {
|
|
194
211
|
if (this.hrstart && other.hrstart) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
212
|
+
const s = this.hrstart[0] - other.hrstart[0]
|
|
213
|
+
const ns = this.hrstart[1] - other.hrstart[1]
|
|
198
214
|
|
|
199
215
|
return hrToMillis([s, ns])
|
|
200
216
|
}
|
|
@@ -206,9 +222,7 @@ Timer.prototype.startedRelativeTo = function startedRelativeTo(other) {
|
|
|
206
222
|
* Returns true if this timer ends after the other.
|
|
207
223
|
*/
|
|
208
224
|
Timer.prototype.endsAfter = function compare(other) {
|
|
209
|
-
return
|
|
210
|
-
(other.getDurationInMillis() + other.start)
|
|
225
|
+
return this.getDurationInMillis() + this.start > other.getDurationInMillis() + other.start
|
|
211
226
|
}
|
|
212
227
|
|
|
213
|
-
|
|
214
228
|
module.exports = Timer
|