newrelic 8.3.0 → 8.5.2
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 +76 -0
- package/README.md +7 -6
- package/THIRD_PARTY_NOTICES.md +95 -35
- package/api.js +74 -68
- package/bin/test-naming-rules.js +22 -22
- package/lib/agent.js +4 -4
- package/lib/attributes.js +2 -2
- package/lib/collector/api.js +12 -12
- package/lib/collector/facts.js +1 -1
- package/lib/collector/http-agents.js +12 -11
- package/lib/collector/key-parser.js +1 -1
- package/lib/collector/remote-method.js +27 -26
- package/lib/config/attribute-filter.js +23 -23
- package/lib/config/default.js +12 -10
- package/lib/config/hsm.js +1 -1
- package/lib/config/index.js +82 -66
- package/lib/config/lasp.js +3 -3
- package/lib/config/merge-server-config.js +1 -1
- package/lib/db/parse-sql.js +8 -8
- package/lib/db/parsed-statement.js +9 -8
- package/lib/db/query-parsers/sql.js +7 -7
- package/lib/db/query-sample.js +9 -9
- package/lib/db/query-trace-aggregator.js +4 -4
- package/lib/db/statement-matcher.js +5 -5
- package/lib/db/utils.js +1 -1
- package/lib/environment.js +43 -43
- package/lib/errors/error-collector.js +2 -2
- package/lib/errors/error-trace-aggregator.js +1 -1
- package/lib/errors/helper.js +3 -3
- package/lib/errors/index.js +17 -17
- package/lib/feature_flags.js +7 -5
- package/lib/header-attributes.js +6 -6
- package/lib/header-processing.js +1 -1
- package/lib/instrumentation/amqplib.js +26 -26
- package/lib/instrumentation/bluebird.js +3 -3
- package/lib/instrumentation/cassandra-driver.js +7 -3
- package/lib/instrumentation/connect.js +4 -4
- package/lib/instrumentation/core/async_hooks.js +6 -6
- package/lib/instrumentation/core/domain.js +2 -2
- package/lib/instrumentation/core/globals.js +1 -1
- package/lib/instrumentation/core/http-outbound.js +15 -84
- package/lib/instrumentation/core/http.js +34 -67
- package/lib/instrumentation/core/inspector.js +2 -2
- package/lib/instrumentation/core/timers.js +7 -7
- package/lib/instrumentation/core/zlib.js +2 -2
- package/lib/instrumentation/director.js +4 -4
- package/lib/instrumentation/express.js +8 -8
- package/lib/instrumentation/fastify/spec-builders.js +57 -47
- package/lib/instrumentation/fastify.js +85 -24
- package/lib/instrumentation/generic-pool.js +1 -1
- package/lib/instrumentation/hapi/hapi-17.js +11 -11
- package/lib/instrumentation/hapi/shared.js +1 -1
- package/lib/instrumentation/hapi.js +22 -22
- package/lib/instrumentation/ioredis.js +7 -7
- package/lib/instrumentation/memcached.js +7 -7
- package/lib/instrumentation/mongodb/common.js +16 -5
- package/lib/instrumentation/mysql.js +19 -19
- package/lib/instrumentation/oracle.js +15 -15
- package/lib/instrumentation/pg.js +4 -4
- package/lib/instrumentation/promise.js +46 -46
- package/lib/instrumentation/q.js +2 -2
- package/lib/instrumentation/redis.js +11 -11
- package/lib/instrumentation/restify.js +1 -1
- package/lib/instrumentation/undici.js +242 -0
- package/lib/instrumentation/vision.js +4 -4
- package/lib/instrumentation/when.js +3 -3
- package/lib/instrumentations.js +2 -1
- package/lib/logger.js +5 -5
- package/lib/metrics/index.js +15 -15
- package/lib/metrics/mapper.js +7 -7
- package/lib/metrics/normalizer/rule.js +9 -9
- package/lib/metrics/normalizer/tx_segment.js +17 -17
- package/lib/metrics/normalizer.js +22 -22
- package/lib/metrics/recorders/custom.js +5 -5
- package/lib/metrics/recorders/generic.js +3 -3
- package/lib/metrics/recorders/http.js +7 -7
- package/lib/metrics/recorders/http_external.js +7 -7
- package/lib/metrics/recorders/message-transaction.js +5 -6
- package/lib/metrics/recorders/other.js +5 -5
- package/lib/parse-proc-cpuinfo.js +25 -19
- package/lib/parse-proc-meminfo.js +8 -2
- package/lib/prioritized-attributes.js +2 -2
- package/lib/priority-queue.js +10 -10
- package/lib/reservoir.js +3 -3
- package/lib/sampler.js +26 -26
- package/lib/serverless/aws-lambda.js +8 -2
- package/lib/shim/datastore-shim.js +35 -32
- package/lib/shim/index.js +2 -2
- package/lib/shim/message-shim.js +47 -47
- package/lib/shim/promise-shim.js +1 -1
- package/lib/shim/shim.js +61 -61
- package/lib/shim/specs/index.js +3 -3
- package/lib/shim/transaction-shim.js +44 -192
- package/lib/shim/webframework-shim.js +52 -52
- package/lib/spans/span-event.js +1 -1
- package/lib/spans/streaming-span-attributes.js +1 -1
- package/lib/stats/apdex.js +2 -2
- package/lib/stats/index.js +2 -2
- package/lib/system-info.js +23 -23
- package/lib/timer.js +5 -5
- package/lib/transaction/dt-payload.js +1 -1
- package/lib/transaction/index.js +40 -40
- package/lib/transaction/name-state.js +14 -14
- package/lib/transaction/trace/exclusive-time-calculator.js +6 -6
- package/lib/transaction/trace/index.js +14 -14
- package/lib/transaction/trace/segment.js +18 -18
- package/lib/transaction/tracecontext.js +1 -1
- package/lib/transaction/tracer/index.js +53 -49
- package/lib/uninstrumented.js +7 -7
- package/lib/util/arity.js +2 -2
- package/lib/util/byte-limit.js +4 -4
- package/lib/util/cat.js +269 -24
- package/lib/util/codec.js +2 -2
- package/lib/util/copy.js +2 -2
- package/lib/util/deep-equal.js +10 -10
- package/lib/util/flatten.js +4 -4
- package/lib/util/hashes.js +14 -14
- package/lib/util/label-parser.js +17 -17
- package/lib/util/logger.js +24 -24
- package/lib/util/process-version.js +2 -2
- package/lib/util/properties.js +4 -4
- package/lib/util/sql/obfuscate.js +15 -15
- package/lib/util/stream-sink.js +3 -3
- package/lib/util/unwrapped-core.js +2 -2
- package/lib/util/urltils.js +16 -16
- package/lib/utilization/aws-info.js +7 -7
- package/lib/utilization/azure-info.js +6 -6
- package/lib/utilization/common.js +13 -13
- package/lib/utilization/docker-info.js +11 -11
- package/lib/utilization/gcp-info.js +4 -4
- package/lib/utilization/index.js +5 -5
- package/lib/utilization/pcf-info.js +9 -9
- package/package.json +13 -6
- package/stub_api.js +8 -8
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const EventEmitter = require('events').EventEmitter
|
|
9
|
+
const util = require('util')
|
|
10
|
+
const logger = require('../logger').child({ component: 'metric_normalizer' })
|
|
11
|
+
const deepEqual = require('../util/deep-equal')
|
|
12
|
+
const NormalizerRule = require('./normalizer/rule')
|
|
13
|
+
const NAMES = require('../metrics/names.js')
|
|
14
14
|
|
|
15
15
|
function url(normalized, path, config) {
|
|
16
16
|
if (normalized) {
|
|
@@ -91,7 +91,7 @@ MetricNormalizer.prototype.load = function load(json) {
|
|
|
91
91
|
|
|
92
92
|
json.forEach((ruleJSON) => {
|
|
93
93
|
// no need to add the same rule twice
|
|
94
|
-
|
|
94
|
+
const rule = new NormalizerRule(ruleJSON)
|
|
95
95
|
if (!this.rules.find(deepEqual.bind(null, rule))) {
|
|
96
96
|
this.rules.push(rule)
|
|
97
97
|
logger.trace('Loaded %s normalization rule: %s', this.type, rule)
|
|
@@ -115,7 +115,7 @@ MetricNormalizer.prototype.load = function load(json) {
|
|
|
115
115
|
* Operates via side effects.
|
|
116
116
|
*/
|
|
117
117
|
MetricNormalizer.prototype.loadFromConfig = function loadFromConfig() {
|
|
118
|
-
|
|
118
|
+
const rules = this.config.rules
|
|
119
119
|
|
|
120
120
|
if (rules && rules.name && rules.name.length > 0) {
|
|
121
121
|
rules.name.forEach((rule) => {
|
|
@@ -126,9 +126,9 @@ MetricNormalizer.prototype.loadFromConfig = function loadFromConfig() {
|
|
|
126
126
|
return logger.error({ rule: rule }, 'Simple naming rules require a replacement name.')
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
const precedence = rule.precedence
|
|
130
|
+
const terminal = rule.terminate_chain
|
|
131
|
+
const json = {
|
|
132
132
|
match_expression: rule.pattern,
|
|
133
133
|
eval_order: typeof precedence === 'number' ? precedence : 500,
|
|
134
134
|
terminate_chain: typeof terminal === 'boolean' ? terminal : true,
|
|
@@ -138,8 +138,8 @@ MetricNormalizer.prototype.loadFromConfig = function loadFromConfig() {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// Find where the rule should be inserted and do so.
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
const reverse = this.config.feature_flag.reverse_naming_rules
|
|
142
|
+
const insert = this.rules.findIndex(function findRule(r) {
|
|
143
143
|
return reverse ? r.precedence >= json.eval_order : r.precedence > json.eval_order
|
|
144
144
|
})
|
|
145
145
|
if (insert === -1) {
|
|
@@ -174,7 +174,7 @@ MetricNormalizer.prototype.addSimple = function addSimple(pattern, name) {
|
|
|
174
174
|
return logger.error('Simple naming rules require a pattern.')
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
const json = {
|
|
178
178
|
match_expression: pattern,
|
|
179
179
|
eval_order: 0,
|
|
180
180
|
terminate_chain: true,
|
|
@@ -200,16 +200,16 @@ MetricNormalizer.prototype.addSimple = function addSimple(pattern, name) {
|
|
|
200
200
|
* @returns {NormalizationResults} - The results of normalization.
|
|
201
201
|
*/
|
|
202
202
|
MetricNormalizer.prototype.normalize = function normalize(path) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
203
|
+
let last = path
|
|
204
|
+
const length = this.rules.length
|
|
205
|
+
let normalized
|
|
206
|
+
let matched = false
|
|
207
|
+
let ignored = false
|
|
208
208
|
|
|
209
209
|
// Apply each of our rules in turn.
|
|
210
|
-
for (
|
|
211
|
-
|
|
212
|
-
|
|
210
|
+
for (let i = 0; i < length; i++) {
|
|
211
|
+
const rule = this.rules[i]
|
|
212
|
+
const applied = rule.apply(last)
|
|
213
213
|
if (!rule.matched) {
|
|
214
214
|
continue
|
|
215
215
|
}
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const NAMES = require('../names')
|
|
9
9
|
|
|
10
10
|
function record(segment, scope) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const duration = segment.getDurationInMillis()
|
|
12
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
13
|
+
const transaction = segment.transaction
|
|
14
|
+
const name = NAMES.CUSTOM + NAMES.ACTION_DELIMITER + segment.name
|
|
15
15
|
|
|
16
16
|
if (scope) {
|
|
17
17
|
transaction.measure(name, scope, duration, exclusive)
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
function record(segment, scope) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const duration = segment.getDurationInMillis()
|
|
10
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
11
|
+
const transaction = segment.transaction
|
|
12
12
|
|
|
13
13
|
if (scope) {
|
|
14
14
|
transaction.measure(segment.name, scope, duration, exclusive)
|
|
@@ -16,19 +16,19 @@ function recordWeb(segment, scope) {
|
|
|
16
16
|
return
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
const tx = segment.transaction
|
|
20
20
|
// if there was a nested webTransaction use its recorder instead
|
|
21
21
|
if (tx.type === 'web' && tx.baseSegment && segment !== tx.baseSegment) {
|
|
22
22
|
return
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
const duration = segment.getDurationInMillis()
|
|
26
|
+
const totalTime = tx.trace.getTotalTimeDurationInMillis()
|
|
27
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
28
|
+
const partial = segment.partialName
|
|
29
|
+
const config = segment.transaction.agent.config
|
|
30
30
|
// named / key transaction support requires per-name apdexT
|
|
31
|
-
|
|
31
|
+
const keyApdexInMillis = config.web_transactions_apdex[scope] * TO_MILLIS || 0
|
|
32
32
|
|
|
33
33
|
tx.measure(NAMES.WEB.RESPONSE_TIME, null, duration, exclusive)
|
|
34
34
|
tx.measure(NAMES.WEB.TOTAL_TIME, null, totalTime, exclusive)
|
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const EXTERNAL = require('../../metrics/names').EXTERNAL
|
|
9
9
|
|
|
10
10
|
function recordExternal(host, library) {
|
|
11
11
|
return function externalRecorder(segment, scope) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
const duration = segment.getDurationInMillis()
|
|
13
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
14
|
+
const transaction = segment.transaction
|
|
15
|
+
const metricName = EXTERNAL.PREFIX + host + '/' + library
|
|
16
|
+
const rollupType = transaction.isWeb() ? EXTERNAL.WEB : EXTERNAL.OTHER
|
|
17
|
+
const rollupHost = EXTERNAL.PREFIX + host + '/all'
|
|
18
18
|
|
|
19
19
|
if (segment.catId && segment.catTransaction) {
|
|
20
20
|
transaction.measure(
|
|
@@ -5,19 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const NAMES = require('../../metrics/names.js')
|
|
9
9
|
|
|
10
10
|
function recordMessageTransaction(segment, scope) {
|
|
11
|
-
|
|
11
|
+
const tx = segment.transaction
|
|
12
12
|
if (tx.type !== 'message' || tx.baseSegment !== segment) {
|
|
13
13
|
return
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const duration = segment.getDurationInMillis()
|
|
17
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
18
|
+
const totalTime = segment.transaction.trace.getTotalTimeDurationInMillis()
|
|
19
19
|
|
|
20
|
-
var tx = segment.transaction
|
|
21
20
|
if (scope) {
|
|
22
21
|
tx.measure(scope, null, duration, exclusive)
|
|
23
22
|
tx.measure(
|
|
@@ -10,15 +10,15 @@ const recordDistributedTrace = require('./distributed-trace')
|
|
|
10
10
|
|
|
11
11
|
function recordBackground(segment, scope) {
|
|
12
12
|
// if there was a nested otherTransaction use its recorder instead
|
|
13
|
-
|
|
13
|
+
const tx = segment.transaction
|
|
14
14
|
if (tx.type === 'bg' && tx.baseSegment && segment !== tx.baseSegment) {
|
|
15
15
|
return
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const duration = segment.getDurationInMillis()
|
|
19
|
+
const exclusive = segment.getExclusiveDurationInMillis()
|
|
20
|
+
const totalTime = segment.transaction.trace.getTotalTimeDurationInMillis()
|
|
21
|
+
const name = segment.partialName
|
|
22
22
|
|
|
23
23
|
if (scope) {
|
|
24
24
|
tx.measure(scope, null, duration, exclusive)
|
|
@@ -5,26 +5,32 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const logger = require('./logger.js').child({ component: 'proc-cpuinfo' })
|
|
9
9
|
module.exports = parseProcCPUInfo
|
|
10
10
|
|
|
11
11
|
function parseProcCPUInfo(data) {
|
|
12
|
-
|
|
12
|
+
const relevantAttributes = ['processor', 'physical id', 'cpu cores', 'core id']
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
let processorStats = {
|
|
15
15
|
logical: null,
|
|
16
16
|
cores: null,
|
|
17
17
|
packages: null
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// In some rare cases the OS may be locked down so that you cannot retrieve this info.
|
|
21
|
+
if (!data) {
|
|
22
|
+
logger.debug('No CPU data to parse, returning empty stats.')
|
|
23
|
+
return processorStats
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
// separate the processors
|
|
21
|
-
|
|
27
|
+
let splitData = data.split('\n').map(function formatAttribute(attr) {
|
|
22
28
|
return attr.split(':').map(function eliminateExtraWhitespace(s) {
|
|
23
29
|
return s.replace(/\\r|\\t| {2,}/g, '').trim()
|
|
24
30
|
})
|
|
25
31
|
})
|
|
26
32
|
|
|
27
|
-
|
|
33
|
+
const validData = splitData.filter(function checkForValidAttrs(a) {
|
|
28
34
|
return a.length === 2 && relevantAttributes.indexOf(a[0]) !== -1
|
|
29
35
|
})
|
|
30
36
|
if (validData.length === 0) {
|
|
@@ -34,7 +40,7 @@ function parseProcCPUInfo(data) {
|
|
|
34
40
|
|
|
35
41
|
splitData = collapseMultilineValues(splitData)
|
|
36
42
|
|
|
37
|
-
|
|
43
|
+
const processors = separateProcessors(splitData)
|
|
38
44
|
|
|
39
45
|
processorStats = countProcessorStats(processors)
|
|
40
46
|
if (!processorStats.cores) {
|
|
@@ -56,9 +62,9 @@ function parseProcCPUInfo(data) {
|
|
|
56
62
|
// some values are split up over multiple lines, these won't be broken
|
|
57
63
|
// by split(':'), and should be folded into the last seen valid value
|
|
58
64
|
function collapseMultilineValues(li) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for (
|
|
65
|
+
const tmp = []
|
|
66
|
+
let last
|
|
67
|
+
for (let i = 0; i < li.length; ++i) {
|
|
62
68
|
if (li[i].length === 2) {
|
|
63
69
|
// store the last valid entry to append invalid entries to
|
|
64
70
|
last = li[i]
|
|
@@ -73,12 +79,12 @@ function collapseMultilineValues(li) {
|
|
|
73
79
|
|
|
74
80
|
// walk through the processed list of key, value pairs and populate
|
|
75
81
|
// objects till you find a collision
|
|
76
|
-
function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
for (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
function separateProcessors(processorData) {
|
|
83
|
+
const processors = []
|
|
84
|
+
let processor = Object.create(null)
|
|
85
|
+
for (let i = 0; i < processorData.length; ++i) {
|
|
86
|
+
const key = processorData[i][0]
|
|
87
|
+
const value = processorData[i][1]
|
|
82
88
|
if (processor[key] !== undefined) {
|
|
83
89
|
processors.push(processor)
|
|
84
90
|
processor = Object.create(null)
|
|
@@ -90,11 +96,11 @@ function seperateProcessors(processorData) {
|
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
function countProcessorStats(processors) {
|
|
93
|
-
|
|
94
|
-
|
|
99
|
+
const phys = []
|
|
100
|
+
const cores = []
|
|
95
101
|
|
|
96
|
-
for (
|
|
97
|
-
|
|
102
|
+
for (let i = 0; i < processors.length; i++) {
|
|
103
|
+
const processor = processors[i]
|
|
98
104
|
if (
|
|
99
105
|
processor['physical id'] &&
|
|
100
106
|
processor['cpu cores'] &&
|
|
@@ -5,12 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const logger = require('./logger.js').child({ component: 'proc-meminfo' })
|
|
9
9
|
|
|
10
10
|
module.exports = parseProcMeminfo
|
|
11
11
|
|
|
12
12
|
function parseProcMeminfo(data) {
|
|
13
|
-
|
|
13
|
+
// In some rare cases the OS may be locked down so that you cannot retrieve this info.
|
|
14
|
+
if (!data) {
|
|
15
|
+
logger.debug('No memory data to parse.')
|
|
16
|
+
return null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const memTotal = parseInt(data.replace(/MemTotal:\s*(\d*)\skB/, '$1'), 10)
|
|
14
20
|
|
|
15
21
|
if (memTotal) {
|
|
16
22
|
return memTotal / 1024
|
|
@@ -35,7 +35,7 @@ class PrioritizedAttributes {
|
|
|
35
35
|
get(dest) {
|
|
36
36
|
const attrs = Object.create(null)
|
|
37
37
|
|
|
38
|
-
for (
|
|
38
|
+
for (const [key, attr] of this.attributes) {
|
|
39
39
|
if (!(attr.destinations & dest)) {
|
|
40
40
|
continue
|
|
41
41
|
}
|
|
@@ -127,7 +127,7 @@ class PrioritizedAttributes {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
addAttributes(destinations, attrs) {
|
|
130
|
-
for (
|
|
130
|
+
for (const key in attrs) {
|
|
131
131
|
if (properties.hasOwn(attrs, key)) {
|
|
132
132
|
this.addAttribute(destinations, key, attrs[key])
|
|
133
133
|
}
|
package/lib/priority-queue.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const Heap = require('@tyriar/fibonacci-heap').FibonacciHeap
|
|
9
9
|
|
|
10
10
|
function PriorityQueue(limit) {
|
|
11
11
|
this.limit = limit == null ? 10 : limit
|
|
@@ -20,7 +20,7 @@ function PriorityQueue(limit) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
PriorityQueue.prototype.overflow = function overflow() {
|
|
23
|
-
|
|
23
|
+
const diff = this.seen - this.limit
|
|
24
24
|
return diff >= 0 ? diff : 0
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -51,8 +51,8 @@ PriorityQueue.prototype._replace = function _replace(value, priority) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
PriorityQueue.prototype.getRawEvents = function getRawEvents() {
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
const events = []
|
|
55
|
+
const min = this._data.findMinimum()
|
|
56
56
|
|
|
57
57
|
if (min) {
|
|
58
58
|
_getRawEvents(min, events)
|
|
@@ -61,7 +61,7 @@ PriorityQueue.prototype.getRawEvents = function getRawEvents() {
|
|
|
61
61
|
return events
|
|
62
62
|
|
|
63
63
|
function _getRawEvents(head, evts) {
|
|
64
|
-
|
|
64
|
+
let current = head
|
|
65
65
|
|
|
66
66
|
do {
|
|
67
67
|
evts.push({ value: current.value, priority: current.key })
|
|
@@ -74,8 +74,8 @@ PriorityQueue.prototype.getRawEvents = function getRawEvents() {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
PriorityQueue.prototype.toArray = function toArray() {
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
const nodes = []
|
|
78
|
+
const min = this._data.findMinimum()
|
|
79
79
|
|
|
80
80
|
if (min) {
|
|
81
81
|
serializeHeap(min, nodes)
|
|
@@ -84,7 +84,7 @@ PriorityQueue.prototype.toArray = function toArray() {
|
|
|
84
84
|
return nodes
|
|
85
85
|
|
|
86
86
|
function serializeHeap(head, arr) {
|
|
87
|
-
|
|
87
|
+
let current = head
|
|
88
88
|
|
|
89
89
|
do {
|
|
90
90
|
arr.push(current.value)
|
|
@@ -110,11 +110,11 @@ PriorityQueue.prototype.merge = function merge(events) {
|
|
|
110
110
|
|
|
111
111
|
if (events instanceof PriorityQueue) {
|
|
112
112
|
while (events.length) {
|
|
113
|
-
|
|
113
|
+
const current = events._data.extractMinimum()
|
|
114
114
|
this.add(current.value, current.key)
|
|
115
115
|
}
|
|
116
116
|
} else {
|
|
117
|
-
for (
|
|
117
|
+
for (let i = 0; i < events.length; ++i) {
|
|
118
118
|
this.add(events[i].value, events[i].priority)
|
|
119
119
|
}
|
|
120
120
|
}
|
package/lib/reservoir.js
CHANGED
|
@@ -14,7 +14,7 @@ function Reservoir(limit) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
Reservoir.prototype.overflow = function overflow() {
|
|
17
|
-
|
|
17
|
+
const diff = this.seen - this.limit
|
|
18
18
|
return diff >= 0 ? diff : 0
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -29,7 +29,7 @@ Reservoir.prototype.add = function add(item) {
|
|
|
29
29
|
// This is effectively the same as adding the new element to the
|
|
30
30
|
// end, swapping the last element (the new one) with a random element in the list,
|
|
31
31
|
// then dropping the last element (the potentially swapped one) in the list.
|
|
32
|
-
|
|
32
|
+
const toReplace = Math.floor(Math.random() * (this.seen + 2))
|
|
33
33
|
if (toReplace < this.limit) {
|
|
34
34
|
this._data[toReplace] = item
|
|
35
35
|
}
|
|
@@ -48,7 +48,7 @@ Reservoir.prototype.merge = function merge(items) {
|
|
|
48
48
|
if (items === this._data) {
|
|
49
49
|
return
|
|
50
50
|
}
|
|
51
|
-
for (
|
|
51
|
+
for (let i = 0; i < items.length; i++) {
|
|
52
52
|
this.add(items[i])
|
|
53
53
|
}
|
|
54
54
|
}
|
package/lib/sampler.js
CHANGED
|
@@ -5,22 +5,22 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
const NAMES = require('./metrics/names')
|
|
9
|
+
const logger = require('./logger').child({ component: 'sampler' })
|
|
10
|
+
const Timer = require('./timer')
|
|
11
|
+
const os = require('os')
|
|
12
12
|
|
|
13
13
|
/*
|
|
14
14
|
*
|
|
15
15
|
* CONSTANTS
|
|
16
16
|
*
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const MILLIS = 1e3
|
|
19
|
+
const MICROS = 1e6
|
|
20
|
+
const CPUS = os.cpus().length
|
|
21
|
+
const SAMPLE_INTERVAL = 15 * MILLIS
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
let samplers = []
|
|
24
24
|
|
|
25
25
|
function Sampler(sampler, interval) {
|
|
26
26
|
this.id = setInterval(sampler, interval)
|
|
@@ -39,7 +39,7 @@ function recordQueueTime(agent, timer) {
|
|
|
39
39
|
function sampleMemory(agent) {
|
|
40
40
|
return function memorySampler() {
|
|
41
41
|
try {
|
|
42
|
-
|
|
42
|
+
const mem = process.memoryUsage()
|
|
43
43
|
agent.metrics.measureBytes(NAMES.MEMORY.PHYSICAL, mem.rss)
|
|
44
44
|
agent.metrics.measureBytes(NAMES.MEMORY.USED_HEAP, mem.heapUsed)
|
|
45
45
|
agent.metrics.measureBytes(NAMES.MEMORY.MAX_HEAP, mem.heapTotal)
|
|
@@ -54,7 +54,7 @@ function sampleMemory(agent) {
|
|
|
54
54
|
|
|
55
55
|
function checkEvents(agent) {
|
|
56
56
|
return function eventSampler() {
|
|
57
|
-
|
|
57
|
+
const timer = new Timer()
|
|
58
58
|
timer.begin()
|
|
59
59
|
setTimeout(recordQueueTime.bind(null, agent, timer), 0)
|
|
60
60
|
}
|
|
@@ -70,22 +70,22 @@ function getCpuSample(lastSample) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
function generateCPUMetricRecorder(agent) {
|
|
73
|
-
|
|
73
|
+
let lastSampleTime
|
|
74
74
|
// userTime and sysTime are in seconds
|
|
75
75
|
return function recordCPUMetrics(userTime, sysTime) {
|
|
76
|
-
|
|
76
|
+
let elapsedUptime
|
|
77
77
|
if (!lastSampleTime) {
|
|
78
78
|
elapsedUptime = process.uptime()
|
|
79
79
|
} else {
|
|
80
80
|
elapsedUptime = (Date.now() - lastSampleTime) / MILLIS
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
const totalCpuTime = CPUS * elapsedUptime
|
|
84
84
|
|
|
85
85
|
lastSampleTime = Date.now()
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
const userUtil = userTime / totalCpuTime
|
|
88
|
+
const sysUtil = sysTime / totalCpuTime
|
|
89
89
|
|
|
90
90
|
recordValue(agent, NAMES.CPU.USER_TIME, userTime)
|
|
91
91
|
recordValue(agent, NAMES.CPU.SYSTEM_TIME, sysTime)
|
|
@@ -95,10 +95,10 @@ function generateCPUMetricRecorder(agent) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
function sampleCpu(agent) {
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
let lastSample
|
|
99
|
+
const recordCPU = generateCPUMetricRecorder(agent)
|
|
100
100
|
return function cpuSampler() {
|
|
101
|
-
|
|
101
|
+
const cpuSample = getCpuSample(lastSample)
|
|
102
102
|
lastSample = getCpuSample()
|
|
103
103
|
|
|
104
104
|
if (lastSample == null) {
|
|
@@ -110,7 +110,7 @@ function sampleCpu(agent) {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
function sampleCpuNative(agent, nativeMetrics) {
|
|
113
|
-
|
|
113
|
+
const recordCPU = generateCPUMetricRecorder(agent)
|
|
114
114
|
nativeMetrics.on('usage', function collectResourceUsage(usage) {
|
|
115
115
|
recordCPU(usage.diff.ru_utime / MILLIS, usage.diff.ru_stime / MILLIS)
|
|
116
116
|
})
|
|
@@ -149,7 +149,7 @@ function sampleGc(agent, nativeMetrics) {
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
module.exports = {
|
|
153
153
|
state: 'stopped',
|
|
154
154
|
sampleMemory: sampleMemory,
|
|
155
155
|
checkEvents: checkEvents,
|
|
@@ -206,7 +206,7 @@ var sampler = (module.exports = {
|
|
|
206
206
|
logger.debug('Not adding CPU metric sampler.')
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
this.state = 'running'
|
|
210
210
|
},
|
|
211
211
|
|
|
212
212
|
stop: function stop() {
|
|
@@ -214,7 +214,7 @@ var sampler = (module.exports = {
|
|
|
214
214
|
s.stop()
|
|
215
215
|
})
|
|
216
216
|
samplers = []
|
|
217
|
-
|
|
217
|
+
this.state = 'stopped'
|
|
218
218
|
if (this.nativeMetrics) {
|
|
219
219
|
this.nativeMetrics.unbind()
|
|
220
220
|
this.nativeMetrics.removeAllListeners()
|
|
@@ -224,16 +224,16 @@ var sampler = (module.exports = {
|
|
|
224
224
|
this.nativeMetrics = null
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
|
-
}
|
|
227
|
+
}
|
|
228
228
|
|
|
229
229
|
function recordValue(agent, metric, value) {
|
|
230
|
-
|
|
230
|
+
const stats = agent.metrics.getOrCreateMetric(metric)
|
|
231
231
|
stats.recordValue(value)
|
|
232
232
|
logger.trace('Recorded metric %s: %j', metric, value)
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
function recordCompleteMetric(agent, metricName, metric) {
|
|
236
|
-
|
|
236
|
+
const stats = agent.metrics.getOrCreateMetric(metricName)
|
|
237
237
|
stats.merge(metric)
|
|
238
238
|
logger.trace('Recorded metric %s: %j', metricName, metric)
|
|
239
239
|
}
|
|
@@ -82,8 +82,14 @@ class AwsLambda {
|
|
|
82
82
|
// NOTE: This may be converted to holding onto a single ender function if only
|
|
83
83
|
// one invocation is executing at a time.
|
|
84
84
|
shim.wrap(process, 'emit', function wrapEmit(shim, emit) {
|
|
85
|
-
return function wrappedEmit(ev) {
|
|
86
|
-
|
|
85
|
+
return function wrappedEmit(ev, error) {
|
|
86
|
+
// need to add error as uncaughtException to be used
|
|
87
|
+
// later to add to transaction errors
|
|
88
|
+
if (ev === 'unhandledRejection') {
|
|
89
|
+
uncaughtException = error
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (['beforeExit', 'unhandledRejection'].includes(ev)) {
|
|
87
93
|
transactionEnders.forEach((ender) => {
|
|
88
94
|
ender()
|
|
89
95
|
})
|