newrelic 7.5.2 → 8.3.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 +4989 -4886
- package/THIRD_PARTY_NOTICES.md +625 -216
- package/api.js +105 -174
- package/bin/test-naming-rules.js +38 -32
- package/bin/tracetractor +0 -1
- package/index.js +12 -18
- package/lib/agent.js +108 -111
- package/lib/aggregators/base-aggregator.js +1 -1
- package/lib/aggregators/event-aggregator.js +6 -6
- package/lib/attributes.js +12 -13
- package/lib/collector/api.js +32 -42
- package/lib/collector/facts.js +67 -65
- package/lib/collector/http-agents.js +30 -27
- package/lib/collector/parse-response.js +1 -2
- package/lib/collector/remote-method.js +43 -36
- package/lib/collector/serverless.js +13 -18
- package/lib/collector/ssl/certificates.js +1056 -1056
- package/lib/config/attribute-filter.js +90 -82
- package/lib/config/default.js +30 -18
- package/lib/config/env.js +17 -12
- package/lib/config/harvest-config-validator.js +1 -1
- package/lib/config/index.js +160 -177
- package/lib/config/merge-server-config.js +7 -5
- package/lib/custom-events/custom-event-aggregator.js +1 -1
- package/lib/db/parse-sql.js +6 -9
- package/lib/db/parsed-statement.js +6 -13
- package/lib/db/query-parsers/sql.js +6 -9
- package/lib/db/query-sample.js +7 -3
- package/lib/db/query-trace-aggregator.js +12 -12
- package/lib/db/utils.js +1 -1
- package/lib/environment.js +173 -138
- package/lib/errors/error-collector.js +18 -31
- package/lib/errors/error-event-aggregator.js +1 -1
- package/lib/errors/error-trace-aggregator.js +2 -3
- package/lib/errors/helper.js +21 -30
- package/lib/errors/index.js +16 -28
- package/lib/feature_flags.js +5 -8
- package/lib/grpc/connection/states.js +6 -6
- package/lib/grpc/connection.js +35 -46
- package/lib/header-attributes.js +49 -53
- package/lib/instrumentation/amqplib.js +8 -17
- package/lib/instrumentation/bluebird.js +61 -20
- package/lib/instrumentation/cassandra-driver.js +2 -2
- package/lib/instrumentation/connect.js +4 -3
- package/lib/instrumentation/core/async_hooks.js +11 -4
- 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 +2 -8
- package/lib/instrumentation/core/fs.js +22 -37
- package/lib/instrumentation/core/globals.js +3 -7
- package/lib/instrumentation/core/http-outbound.js +15 -40
- package/lib/instrumentation/core/http.js +29 -63
- package/lib/instrumentation/core/inspector.js +6 -10
- package/lib/instrumentation/core/net.js +3 -1
- package/lib/instrumentation/core/timers.js +17 -24
- package/lib/instrumentation/core/zlib.js +2 -10
- package/lib/instrumentation/express.js +4 -2
- package/lib/instrumentation/fastify/spec-builders.js +5 -0
- package/lib/instrumentation/fastify.js +37 -10
- package/lib/instrumentation/hapi/hapi-17.js +9 -10
- package/lib/instrumentation/hapi.js +15 -15
- package/lib/instrumentation/ioredis.js +1 -2
- package/lib/instrumentation/memcached.js +39 -43
- package/lib/instrumentation/mongodb/common.js +218 -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 +33 -26
- package/lib/instrumentation/oracle.js +10 -14
- package/lib/instrumentation/pg.js +30 -21
- package/lib/instrumentation/promise.js +20 -17
- package/lib/instrumentation/redis.js +30 -30
- package/lib/instrumentation/when.js +9 -1
- package/lib/instrumentations.js +24 -24
- package/lib/logger.js +1 -1
- package/lib/metrics/index.js +37 -17
- package/lib/metrics/mapper.js +9 -9
- package/lib/metrics/metric-aggregator.js +5 -10
- package/lib/metrics/names.js +8 -7
- package/lib/metrics/normalizer/rule.js +6 -7
- package/lib/metrics/normalizer/tx_segment.js +17 -13
- package/lib/metrics/normalizer.js +30 -33
- package/lib/metrics/recorders/custom.js +3 -1
- package/lib/metrics/recorders/distributed-trace.js +3 -18
- package/lib/metrics/recorders/generic.js +3 -2
- package/lib/metrics/recorders/http.js +4 -6
- package/lib/metrics/recorders/http_external.js +1 -3
- package/lib/metrics/recorders/message-transaction.js +2 -12
- package/lib/metrics/recorders/other.js +2 -12
- package/lib/parse-proc-cpuinfo.js +11 -16
- package/lib/parse-proc-meminfo.js +5 -3
- package/lib/prioritized-attributes.js +12 -17
- package/lib/priority-queue.js +1 -1
- package/lib/proxy/grpc.js +1 -1
- package/lib/reservoir.js +9 -3
- package/lib/sampler.js +12 -13
- 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 +29 -38
- package/lib/shim/index.js +8 -9
- package/lib/shim/message-shim.js +111 -113
- package/lib/shim/promise-shim.js +18 -13
- package/lib/shim/shim.js +72 -66
- package/lib/shim/specs/index.js +18 -19
- package/lib/shim/transaction-shim.js +26 -36
- package/lib/shim/webframework-shim.js +25 -35
- package/lib/shimmer.js +184 -166
- package/lib/spans/create-span-event-aggregator.js +24 -44
- package/lib/spans/span-context.js +4 -10
- package/lib/spans/span-event-aggregator.js +68 -13
- package/lib/spans/span-event.js +5 -7
- package/lib/spans/span-streamer.js +10 -18
- package/lib/spans/streaming-span-event-aggregator.js +1 -1
- package/lib/spans/streaming-span-event.js +4 -4
- package/lib/stats/apdex.js +5 -11
- package/lib/stats/index.js +12 -17
- package/lib/system-info.js +7 -3
- package/lib/timer.js +30 -16
- package/lib/transaction/dt-payload.js +1 -1
- package/lib/transaction/handle.js +19 -19
- package/lib/transaction/index.js +94 -112
- package/lib/transaction/name-state.js +5 -6
- package/lib/transaction/trace/aggregator.js +78 -73
- package/lib/transaction/trace/exclusive-time-calculator.js +5 -9
- package/lib/transaction/trace/index.js +26 -24
- package/lib/transaction/trace/segment.js +39 -56
- package/lib/transaction/tracecontext.js +37 -45
- package/lib/transaction/tracer/index.js +79 -44
- package/lib/transaction/transaction-event-aggregator.js +29 -31
- package/lib/uninstrumented.js +4 -5
- package/lib/util/attribute-types.js +1 -5
- package/lib/util/byte-limit.js +0 -1
- package/lib/util/cat.js +5 -13
- package/lib/util/codec.js +8 -4
- package/lib/util/deep-equal.js +48 -18
- package/lib/util/flatten.js +5 -2
- package/lib/util/hashes.js +2 -2
- package/lib/util/label-parser.js +7 -13
- package/lib/util/logger.js +31 -13
- package/lib/util/process-version.js +1 -1
- package/lib/util/properties.js +1 -1
- package/lib/util/sql/obfuscate.js +7 -17
- package/lib/util/stream-sink.js +2 -3
- package/lib/util/urltils.js +9 -13
- package/lib/utilization/aws-info.js +2 -3
- package/lib/utilization/azure-info.js +32 -30
- package/lib/utilization/common.js +5 -4
- package/lib/utilization/docker-info.js +4 -6
- package/lib/utilization/gcp-info.js +36 -35
- package/lib/utilization/index.js +1 -1
- package/lib/utilization/kubernetes-info.js +2 -2
- package/lib/utilization/pcf-info.js +4 -4
- package/package.json +32 -18
- package/stub_api.js +8 -6
|
@@ -9,7 +9,6 @@ var util = require('util')
|
|
|
9
9
|
var properties = require('../util/properties')
|
|
10
10
|
var shimmer = require('../shimmer')
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
/**
|
|
14
13
|
* @namespace Library.Spec
|
|
15
14
|
*
|
|
@@ -84,6 +83,7 @@ var shimmer = require('../shimmer')
|
|
|
84
83
|
* @param {function} library - The promise library.
|
|
85
84
|
* @param {?Library.Spec} spec - Spec for this promise library mapping.
|
|
86
85
|
*/
|
|
86
|
+
/* eslint-disable camelcase */
|
|
87
87
|
module.exports = function initialize(agent, library, spec) {
|
|
88
88
|
if (spec.useFinally == null) {
|
|
89
89
|
spec.useFinally = true
|
|
@@ -189,7 +189,7 @@ module.exports = function initialize(agent, library, spec) {
|
|
|
189
189
|
// implementation uses promise.constructor to create new Promises for
|
|
190
190
|
// calls to `then`, `chain` and `catch` which allows these Promises to
|
|
191
191
|
// also be instrumented.
|
|
192
|
-
promise.__proto__ = wrappedPromise.prototype
|
|
192
|
+
promise.__proto__ = wrappedPromise.prototype // eslint-disable-line no-proto
|
|
193
193
|
|
|
194
194
|
return promise
|
|
195
195
|
}
|
|
@@ -200,7 +200,7 @@ module.exports = function initialize(agent, library, spec) {
|
|
|
200
200
|
return
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
name = name ||
|
|
203
|
+
name = name || spec.constructor + '.prototype'
|
|
204
204
|
|
|
205
205
|
// Wrap up instance methods.
|
|
206
206
|
_safeWrap(PromiseProto, name, spec.$proto.executor, wrapExecutorCaller)
|
|
@@ -340,9 +340,9 @@ module.exports = function initialize(agent, library, spec) {
|
|
|
340
340
|
|
|
341
341
|
function wrapHandler(fn, i, arr) {
|
|
342
342
|
if (
|
|
343
|
-
typeof fn !== 'function' ||
|
|
344
|
-
fn.name === '__NR_wrappedThenHandler' ||
|
|
345
|
-
(!useAllParams && i !==
|
|
343
|
+
typeof fn !== 'function' || // Not a function
|
|
344
|
+
fn.name === '__NR_wrappedThenHandler' || // Already wrapped
|
|
345
|
+
(!useAllParams && i !== arr.length - 1) // Don't want all and not last
|
|
346
346
|
) {
|
|
347
347
|
isWrapped = fn && fn.name === '__NR_wrappedThenHandler'
|
|
348
348
|
return fn
|
|
@@ -413,8 +413,7 @@ module.exports = function initialize(agent, library, spec) {
|
|
|
413
413
|
return __NR_wrappedPromisified
|
|
414
414
|
function __NR_wrappedPromisified() {
|
|
415
415
|
var segment = _createSegment(WRAP_SEGMENT_NAME)
|
|
416
|
-
var prom = agent.tracer.bindFunction(promisified, segment, true)
|
|
417
|
-
.apply(this, arguments)
|
|
416
|
+
var prom = agent.tracer.bindFunction(promisified, segment, true).apply(this, arguments)
|
|
418
417
|
|
|
419
418
|
if (segment) {
|
|
420
419
|
Contextualizer.link(null, prom, segment, spec.useFinally)
|
|
@@ -428,7 +427,7 @@ module.exports = function initialize(agent, library, spec) {
|
|
|
428
427
|
function _createSegment(name, parent) {
|
|
429
428
|
return agent.config.feature_flag.promise_segments === true
|
|
430
429
|
? agent.tracer.createSegment(name, null, parent)
|
|
431
|
-
:
|
|
430
|
+
: parent || agent.tracer.getSegment()
|
|
432
431
|
}
|
|
433
432
|
}
|
|
434
433
|
|
|
@@ -543,7 +542,7 @@ Contextualizer.prototype.getSegment = function getSegment() {
|
|
|
543
542
|
}
|
|
544
543
|
|
|
545
544
|
Contextualizer.prototype.setSegment = function setSegment(segment) {
|
|
546
|
-
return this.context.segments[this.idx] = segment
|
|
545
|
+
return (this.context.segments[this.idx] = segment)
|
|
547
546
|
}
|
|
548
547
|
|
|
549
548
|
Contextualizer.prototype.toJSON = function toJSON() {
|
|
@@ -564,15 +563,19 @@ Contextualizer.prototype.continue = function continueContext(prom) {
|
|
|
564
563
|
|
|
565
564
|
// No `finally` means we need to hook into resolve and reject individually and
|
|
566
565
|
// pass through whatever happened.
|
|
567
|
-
return prom.then(
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
566
|
+
return prom.then(
|
|
567
|
+
function __NR_thenContext(val) {
|
|
568
|
+
__NR_continueContext()
|
|
569
|
+
return val
|
|
570
|
+
},
|
|
571
|
+
function __NR_catchContext(err) {
|
|
572
|
+
__NR_continueContext()
|
|
573
|
+
throw err // Re-throwing promise rejection, this is not New Relic's error.
|
|
574
|
+
}
|
|
575
|
+
)
|
|
574
576
|
|
|
575
577
|
function __NR_continueContext() {
|
|
576
578
|
self.setSegment(nextContext.getSegment())
|
|
577
579
|
}
|
|
578
580
|
}
|
|
581
|
+
/* eslint-disable camelcase */
|
|
@@ -19,7 +19,7 @@ module.exports = function initialize(agent, redis, moduleName, shim) {
|
|
|
19
19
|
shim.recordOperation(
|
|
20
20
|
proto,
|
|
21
21
|
'internal_send_command',
|
|
22
|
-
function wrapInternalSendCommand(shim,
|
|
22
|
+
function wrapInternalSendCommand(shim, _, __, args) {
|
|
23
23
|
var commandObject = args[0]
|
|
24
24
|
var keys = commandObject.args
|
|
25
25
|
var parameters = getInstanceParameters(this)
|
|
@@ -41,11 +41,15 @@ module.exports = function initialize(agent, redis, moduleName, shim) {
|
|
|
41
41
|
shim.bindCallbackSegment(commandObject, 'callback', segment)
|
|
42
42
|
} else {
|
|
43
43
|
var self = this
|
|
44
|
-
commandObject.callback = shim.bindSegment(
|
|
45
|
-
|
|
46
|
-
self.emit
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
commandObject.callback = shim.bindSegment(
|
|
45
|
+
function NRCallback(err) {
|
|
46
|
+
if (err && self.emit instanceof Function) {
|
|
47
|
+
self.emit('error', err)
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
segment,
|
|
51
|
+
true
|
|
52
|
+
)
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -53,36 +57,32 @@ module.exports = function initialize(agent, redis, moduleName, shim) {
|
|
|
53
57
|
)
|
|
54
58
|
} else {
|
|
55
59
|
// For redis versions <2.6.1
|
|
56
|
-
shim.recordOperation(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
function wrapSendCommand(shim, send_command, name, args) {
|
|
60
|
-
var keys = args[1]
|
|
61
|
-
var parameters = getInstanceParameters(this)
|
|
60
|
+
shim.recordOperation(proto, 'send_command', function wrapSendCommand(shim, _, __, args) {
|
|
61
|
+
var keys = args[1]
|
|
62
|
+
var parameters = getInstanceParameters(this)
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
64
|
+
if (keys && !shim.isFunction(keys)) {
|
|
65
|
+
try {
|
|
66
|
+
parameters.key = stringify(keys[0])
|
|
67
|
+
} catch (err) {
|
|
68
|
+
shim.logger.debug(err, 'Failed to stringify redis key for send command')
|
|
69
|
+
parameters.key = '<unknown>'
|
|
70
70
|
}
|
|
71
|
+
}
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
73
|
+
return {
|
|
74
|
+
name: args[0] || 'other',
|
|
75
|
+
parameters: parameters,
|
|
76
|
+
callback: function bindCallback(shim, _f, _n, segment) {
|
|
77
|
+
var last = args[args.length - 1]
|
|
78
|
+
if (shim.isFunction(last)) {
|
|
79
|
+
shim.bindCallbackSegment(args, shim.LAST, segment)
|
|
80
|
+
} else if (shim.isArray(last) && shim.isFunction(last[last.length - 1])) {
|
|
81
|
+
shim.bindCallbackSegment(last, shim.LAST, segment)
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
)
|
|
85
|
+
})
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
function getInstanceParameters(client) {
|
|
@@ -8,7 +8,15 @@
|
|
|
8
8
|
var promInit = require('./promise')
|
|
9
9
|
|
|
10
10
|
var STATIC_PROMISE_METHODS = [
|
|
11
|
-
'reject',
|
|
11
|
+
'reject',
|
|
12
|
+
'resolve',
|
|
13
|
+
'all',
|
|
14
|
+
'any',
|
|
15
|
+
'some',
|
|
16
|
+
'map',
|
|
17
|
+
'reduce',
|
|
18
|
+
'filter',
|
|
19
|
+
'reduceRight'
|
|
12
20
|
]
|
|
13
21
|
|
|
14
22
|
var WHEN_SPEC = {
|
package/lib/instrumentations.js
CHANGED
|
@@ -10,29 +10,29 @@ var MODULE_TYPE = require('./shim/constants').MODULE_TYPE
|
|
|
10
10
|
// Return a new copy of this array every time we're called
|
|
11
11
|
module.exports = function instrumentations() {
|
|
12
12
|
return {
|
|
13
|
-
'aws-sdk': {module: '@newrelic/aws-sdk'},
|
|
14
|
-
'amqplib': {type: MODULE_TYPE.MESSAGE},
|
|
15
|
-
'cassandra-driver': {type: MODULE_TYPE.DATASTORE},
|
|
16
|
-
'connect': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
17
|
-
'bluebird': {type: MODULE_TYPE.PROMISE},
|
|
18
|
-
'director': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
19
|
-
'express': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
20
|
-
'fastify': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
21
|
-
'generic-pool': {type: MODULE_TYPE.GENERIC},
|
|
22
|
-
'@hapi/hapi': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
23
|
-
'hapi': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
24
|
-
'ioredis': {type: MODULE_TYPE.DATASTORE},
|
|
25
|
-
'koa': {module: '@newrelic/koa'},
|
|
26
|
-
'memcached': {type: MODULE_TYPE.DATASTORE},
|
|
27
|
-
'mongodb': {type: MODULE_TYPE.DATASTORE},
|
|
28
|
-
'mysql': {type: MODULE_TYPE.DATASTORE},
|
|
29
|
-
'pg': {type: MODULE_TYPE.DATASTORE},
|
|
30
|
-
'q': {type: null},
|
|
31
|
-
'redis': {type: MODULE_TYPE.DATASTORE},
|
|
32
|
-
'restify': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
33
|
-
'superagent': {module: '@newrelic/superagent'},
|
|
34
|
-
'oracle': {type: null},
|
|
35
|
-
'vision': {type: MODULE_TYPE.WEB_FRAMEWORK},
|
|
36
|
-
'when': {type: null}
|
|
13
|
+
'aws-sdk': { module: '@newrelic/aws-sdk' },
|
|
14
|
+
'amqplib': { type: MODULE_TYPE.MESSAGE },
|
|
15
|
+
'cassandra-driver': { type: MODULE_TYPE.DATASTORE },
|
|
16
|
+
'connect': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
17
|
+
'bluebird': { type: MODULE_TYPE.PROMISE },
|
|
18
|
+
'director': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
19
|
+
'express': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
20
|
+
'fastify': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
21
|
+
'generic-pool': { type: MODULE_TYPE.GENERIC },
|
|
22
|
+
'@hapi/hapi': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
23
|
+
'hapi': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
24
|
+
'ioredis': { type: MODULE_TYPE.DATASTORE },
|
|
25
|
+
'koa': { module: '@newrelic/koa' },
|
|
26
|
+
'memcached': { type: MODULE_TYPE.DATASTORE },
|
|
27
|
+
'mongodb': { type: MODULE_TYPE.DATASTORE },
|
|
28
|
+
'mysql': { type: MODULE_TYPE.DATASTORE },
|
|
29
|
+
'pg': { type: MODULE_TYPE.DATASTORE },
|
|
30
|
+
'q': { type: null },
|
|
31
|
+
'redis': { type: MODULE_TYPE.DATASTORE },
|
|
32
|
+
'restify': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
33
|
+
'superagent': { module: '@newrelic/superagent' },
|
|
34
|
+
'oracle': { type: null },
|
|
35
|
+
'vision': { type: MODULE_TYPE.WEB_FRAMEWORK },
|
|
36
|
+
'when': { type: null }
|
|
37
37
|
}
|
|
38
38
|
}
|
package/lib/logger.js
CHANGED
|
@@ -43,7 +43,7 @@ if (config) {
|
|
|
43
43
|
break
|
|
44
44
|
|
|
45
45
|
default:
|
|
46
|
-
stream = fs.createWriteStream(config.logging.filepath, {flags: 'a+'})
|
|
46
|
+
stream = fs.createWriteStream(config.logging.filepath, { flags: 'a+' })
|
|
47
47
|
stream.on('error', function logStreamOnError(err) {
|
|
48
48
|
/* eslint-disable no-console */
|
|
49
49
|
// Since our normal logging didn't work, dump this to stderr.
|
package/lib/metrics/index.js
CHANGED
|
@@ -9,7 +9,6 @@ const Stats = require('../stats')
|
|
|
9
9
|
const ApdexStats = require('../stats/apdex.js')
|
|
10
10
|
const NAMES = require('./names')
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
/*
|
|
14
13
|
*
|
|
15
14
|
* CONSTANTS
|
|
@@ -48,10 +47,14 @@ const FROM_MILLIS = 1e-3
|
|
|
48
47
|
*/
|
|
49
48
|
function Metrics(apdexT, mapper, normalizer) {
|
|
50
49
|
if (apdexT == null || apdexT === '') {
|
|
51
|
-
throw new Error(
|
|
50
|
+
throw new Error('metrics must be created with apdexT')
|
|
51
|
+
}
|
|
52
|
+
if (!mapper) {
|
|
53
|
+
throw new Error('metrics must be created with a mapper')
|
|
54
|
+
}
|
|
55
|
+
if (!normalizer) {
|
|
56
|
+
throw new Error('metrics must be created with a name normalizer')
|
|
52
57
|
}
|
|
53
|
-
if (!mapper) throw new Error("metrics must be created with a mapper")
|
|
54
|
-
if (!normalizer) throw new Error("metrics must be created with a name normalizer")
|
|
55
58
|
|
|
56
59
|
this.empty = true
|
|
57
60
|
this.started = Date.now()
|
|
@@ -134,7 +137,9 @@ Metrics.prototype.getOrCreateMetric = function getOrCreateMetric(name, scope) {
|
|
|
134
137
|
Metrics.prototype.getOrCreateApdexMetric = getOrCreateApdexMetric
|
|
135
138
|
|
|
136
139
|
function getOrCreateApdexMetric(name, scope, overrideApdex) {
|
|
137
|
-
if (!name)
|
|
140
|
+
if (!name) {
|
|
141
|
+
throw new Error('Metrics must be named')
|
|
142
|
+
}
|
|
138
143
|
|
|
139
144
|
var resolved = this._resolve(scope)
|
|
140
145
|
|
|
@@ -143,8 +148,8 @@ function getOrCreateApdexMetric(name, scope, overrideApdex) {
|
|
|
143
148
|
|
|
144
149
|
// Only use the given override to create the metric if this is not the
|
|
145
150
|
// global apdex AND we have a valid value.
|
|
146
|
-
var apdexT =
|
|
147
|
-
?
|
|
151
|
+
var apdexT =
|
|
152
|
+
name !== NAMES.APDEX && overrideApdex > 0 ? overrideApdex * FROM_MILLIS : this.apdexT
|
|
148
153
|
resolved[name] = new ApdexStats(apdexT)
|
|
149
154
|
}
|
|
150
155
|
return resolved[name]
|
|
@@ -162,7 +167,9 @@ function getOrCreateApdexMetric(name, scope, overrideApdex) {
|
|
|
162
167
|
* undefined.
|
|
163
168
|
*/
|
|
164
169
|
Metrics.prototype.getMetric = function getMetric(name, scope) {
|
|
165
|
-
if (!name)
|
|
170
|
+
if (!name) {
|
|
171
|
+
throw new Error('Metrics must be named')
|
|
172
|
+
}
|
|
166
173
|
|
|
167
174
|
return this._resolve(scope)[name]
|
|
168
175
|
}
|
|
@@ -201,7 +208,8 @@ Metrics.prototype.merge = function merge(other, adjustStartTime) {
|
|
|
201
208
|
|
|
202
209
|
// Loop through all scopes and merge them. Since we know `.scoped` has a `null`
|
|
203
210
|
// prototype we don't need to worry about own property checks.
|
|
204
|
-
|
|
211
|
+
// eslint-disable-next-line guard-for-in
|
|
212
|
+
for (var scope in other.scoped) {
|
|
205
213
|
_merge(this._resolve(scope), other.scoped[scope])
|
|
206
214
|
}
|
|
207
215
|
}
|
|
@@ -243,10 +251,14 @@ Metrics.prototype._resolve = function _resolve(scope) {
|
|
|
243
251
|
* @param {string} name The string to look up.
|
|
244
252
|
*/
|
|
245
253
|
Metrics.prototype._getUnscopedData = function _getUnscopedData(name) {
|
|
246
|
-
if (!this.unscoped[name])
|
|
254
|
+
if (!this.unscoped[name]) {
|
|
255
|
+
return
|
|
256
|
+
}
|
|
247
257
|
|
|
248
258
|
var normalized = this.normalizer.normalize(name)
|
|
249
|
-
if (normalized.ignore || !normalized.value)
|
|
259
|
+
if (normalized.ignore || !normalized.value) {
|
|
260
|
+
return
|
|
261
|
+
}
|
|
250
262
|
|
|
251
263
|
return [this.mapper.map(normalized.value), this.unscoped[name]]
|
|
252
264
|
}
|
|
@@ -258,10 +270,14 @@ Metrics.prototype._getUnscopedData = function _getUnscopedData(name) {
|
|
|
258
270
|
* @param {string} name The string to look up.
|
|
259
271
|
*/
|
|
260
272
|
Metrics.prototype._getScopedData = function _getScopedData(name, scope) {
|
|
261
|
-
if (!this.scoped[scope][name])
|
|
273
|
+
if (!this.scoped[scope][name]) {
|
|
274
|
+
return
|
|
275
|
+
}
|
|
262
276
|
|
|
263
277
|
var normalized = this.normalizer.normalize(name)
|
|
264
|
-
if (normalized.ignore || !normalized.value)
|
|
278
|
+
if (normalized.ignore || !normalized.value) {
|
|
279
|
+
return
|
|
280
|
+
}
|
|
265
281
|
|
|
266
282
|
return [this.mapper.map(normalized.value, scope), this.scoped[scope][name]]
|
|
267
283
|
}
|
|
@@ -273,10 +289,12 @@ Metrics.prototype._getScopedData = function _getScopedData(name, scope) {
|
|
|
273
289
|
Metrics.prototype._toUnscopedData = function _toUnscopedData() {
|
|
274
290
|
var metricData = []
|
|
275
291
|
|
|
276
|
-
Object.keys(this.unscoped).forEach(
|
|
292
|
+
Object.keys(this.unscoped).forEach((name) => {
|
|
277
293
|
var data = this._getUnscopedData(name)
|
|
278
|
-
if (data)
|
|
279
|
-
|
|
294
|
+
if (data) {
|
|
295
|
+
metricData.push(data)
|
|
296
|
+
}
|
|
297
|
+
})
|
|
280
298
|
|
|
281
299
|
return metricData
|
|
282
300
|
}
|
|
@@ -291,7 +309,9 @@ Metrics.prototype._toScopedData = function _toScopedData() {
|
|
|
291
309
|
Object.keys(this.scoped).forEach(function forEachScope(scope) {
|
|
292
310
|
Object.keys(this.scoped[scope]).forEach(function forEachMetric(name) {
|
|
293
311
|
var data = this._getScopedData(name, scope)
|
|
294
|
-
if (data)
|
|
312
|
+
if (data) {
|
|
313
|
+
metricData.push(data)
|
|
314
|
+
}
|
|
295
315
|
}, this)
|
|
296
316
|
}, this)
|
|
297
317
|
|
package/lib/metrics/mapper.js
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
var logger = require('../logger').child({component: 'mapper'})
|
|
9
|
-
|
|
8
|
+
var logger = require('../logger').child({ component: 'mapper' })
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* To tighten up the metrics JSON, the collector will maintain a list of
|
|
@@ -38,7 +37,7 @@ function MetricMapper(raw) {
|
|
|
38
37
|
*/
|
|
39
38
|
MetricMapper.prototype.load = function load(raw) {
|
|
40
39
|
if (!(raw && raw.length)) {
|
|
41
|
-
logger.debug(
|
|
40
|
+
logger.debug('No new metric mappings from server.')
|
|
42
41
|
return
|
|
43
42
|
}
|
|
44
43
|
|
|
@@ -49,7 +48,6 @@ MetricMapper.prototype.load = function load(raw) {
|
|
|
49
48
|
var id = raw[i][1]
|
|
50
49
|
var resolved
|
|
51
50
|
|
|
52
|
-
|
|
53
51
|
if (scope) {
|
|
54
52
|
if (!this.scoped[scope]) {
|
|
55
53
|
this.scoped[scope] = Object.create(null)
|
|
@@ -59,11 +57,13 @@ MetricMapper.prototype.load = function load(raw) {
|
|
|
59
57
|
resolved = this.unscoped
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
if (!resolved[name])
|
|
60
|
+
if (!resolved[name]) {
|
|
61
|
+
this.length++
|
|
62
|
+
}
|
|
63
63
|
resolved[name] = id
|
|
64
|
-
logger.trace(
|
|
64
|
+
logger.trace('Metric spec %s has been mapped to ID %s.', spec, id)
|
|
65
65
|
}
|
|
66
|
-
logger.debug(
|
|
66
|
+
logger.debug('Parsed %d metric ids (%d total).', raw.length, this.length)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -78,14 +78,14 @@ MetricMapper.prototype.map = function map(name, scope) {
|
|
|
78
78
|
if (this.scoped[scope] && this.scoped[scope][name]) {
|
|
79
79
|
return this.scoped[scope][name]
|
|
80
80
|
}
|
|
81
|
-
return {name: name, scope: scope}
|
|
81
|
+
return { name: name, scope: scope }
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
if (this.unscoped[name]) {
|
|
85
85
|
return this.unscoped[name]
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
return {name: name}
|
|
88
|
+
return { name: name }
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
module.exports = MetricMapper
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
const logger = require('../logger').child({component: 'metric-aggregator'})
|
|
8
|
+
const logger = require('../logger').child({ component: 'metric-aggregator' })
|
|
9
9
|
const Aggregator = require('../aggregators/base-aggregator')
|
|
10
10
|
const Metrics = require('../metrics')
|
|
11
11
|
|
|
@@ -43,12 +43,7 @@ class MetricAggregator extends Aggregator {
|
|
|
43
43
|
const beginSeconds = this._metrics.started * FROM_MILLIS
|
|
44
44
|
const endSeconds = Date.now() * FROM_MILLIS
|
|
45
45
|
|
|
46
|
-
const payload = [
|
|
47
|
-
this.runId,
|
|
48
|
-
beginSeconds,
|
|
49
|
-
endSeconds,
|
|
50
|
-
this._metrics.toJSON()
|
|
51
|
-
]
|
|
46
|
+
const payload = [this.runId, beginSeconds, endSeconds, this._metrics.toJSON()]
|
|
52
47
|
|
|
53
48
|
return payload
|
|
54
49
|
}
|
|
@@ -164,15 +159,15 @@ function _isValidOrThrow(opts) {
|
|
|
164
159
|
}
|
|
165
160
|
|
|
166
161
|
if (opts.apdexT == null || opts.apdexT === '') {
|
|
167
|
-
throw new Error(
|
|
162
|
+
throw new Error('Metric aggregator must be created with apdexT')
|
|
168
163
|
}
|
|
169
164
|
|
|
170
165
|
if (!opts.mapper) {
|
|
171
|
-
throw new Error(
|
|
166
|
+
throw new Error('Metric aggregator must be created with a mapper')
|
|
172
167
|
}
|
|
173
168
|
|
|
174
169
|
if (!opts.normalizer) {
|
|
175
|
-
throw new Error(
|
|
170
|
+
throw new Error('Metric aggregator must be created with a name normalizer')
|
|
176
171
|
}
|
|
177
172
|
}
|
|
178
173
|
|
package/lib/metrics/names.js
CHANGED
|
@@ -143,7 +143,6 @@ const CASSANDRA = {
|
|
|
143
143
|
STATEMENT: DB.STATEMENT + '/Cassandra/',
|
|
144
144
|
INSTANCE: DB.INSTANCE + '/Cassandra/',
|
|
145
145
|
ALL: DB.PREFIX + 'Cassandra/' + ALL
|
|
146
|
-
|
|
147
146
|
}
|
|
148
147
|
|
|
149
148
|
const ORACLE = {
|
|
@@ -165,7 +164,7 @@ const RESTIFY = {
|
|
|
165
164
|
|
|
166
165
|
const HAPI = {
|
|
167
166
|
PREFIX: 'Hapi/',
|
|
168
|
-
MIDDLEWARE: MIDDLEWARE.PREFIX + 'Hapi/'
|
|
167
|
+
MIDDLEWARE: MIDDLEWARE.PREFIX + 'Hapi/'
|
|
169
168
|
}
|
|
170
169
|
|
|
171
170
|
const UTILIZATION = {
|
|
@@ -177,7 +176,6 @@ const UTILIZATION = {
|
|
|
177
176
|
BOOT_ID_ERROR: SUPPORTABILITY.UTILIZATION + '/boot_id/error'
|
|
178
177
|
}
|
|
179
178
|
|
|
180
|
-
|
|
181
179
|
const CUSTOM_EVENTS = {
|
|
182
180
|
PREFIX: SUPPORTABILITY.EVENTS + '/Customer/',
|
|
183
181
|
DROPPED: SUPPORTABILITY.EVENTS + '/Customer/Dropped',
|
|
@@ -232,10 +230,13 @@ const DISTRIBUTED_TRACE = {
|
|
|
232
230
|
TRANSPORT: 'TransportDuration'
|
|
233
231
|
}
|
|
234
232
|
|
|
233
|
+
const SPAN_EVENT_PREFIX = 'SpanEvent/'
|
|
234
|
+
|
|
235
235
|
const SPAN_EVENTS = {
|
|
236
|
-
SEEN: SUPPORTABILITY.PREFIX + '
|
|
237
|
-
SENT: SUPPORTABILITY.PREFIX + '
|
|
238
|
-
DROPPED: SUPPORTABILITY.PREFIX + '
|
|
236
|
+
SEEN: SUPPORTABILITY.PREFIX + SPAN_EVENT_PREFIX + 'TotalEventsSeen',
|
|
237
|
+
SENT: SUPPORTABILITY.PREFIX + SPAN_EVENT_PREFIX + 'TotalEventsSent',
|
|
238
|
+
DROPPED: SUPPORTABILITY.PREFIX + SPAN_EVENT_PREFIX + 'Discarded',
|
|
239
|
+
LIMIT: SUPPORTABILITY.PREFIX + SPAN_EVENT_PREFIX + 'Limit'
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
const INFINITE_TRACING = {
|
|
@@ -247,7 +248,7 @@ const INFINITE_TRACING = {
|
|
|
247
248
|
SPAN_RESPONSE_GRPC_STATUS: SUPPORTABILITY.INFINITE_TRACING + '/Span/gRPC/%s',
|
|
248
249
|
QUEUE_CAPACITY: SUPPORTABILITY.INFINITE_TRACING + '/Span/QueueCapacity',
|
|
249
250
|
QUEUE_SIZE: SUPPORTABILITY.INFINITE_TRACING + '/Span/QueueSize',
|
|
250
|
-
DRAIN_DURATION: SUPPORTABILITY.INFINITE_TRACING + '/Drain/Duration'
|
|
251
|
+
DRAIN_DURATION: SUPPORTABILITY.INFINITE_TRACING + '/Drain/Duration'
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
const FEATURES = {
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
var logger = require('../../logger').child({component: 'normalizer_rule'})
|
|
9
|
-
|
|
8
|
+
var logger = require('../../logger').child({ component: 'normalizer_rule' })
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* JavaScript just has to do things slightly differently.
|
|
@@ -26,9 +25,7 @@ var replaceReplacer = function replaceReplacer(input) {
|
|
|
26
25
|
*/
|
|
27
26
|
function NormalizerRule(json) {
|
|
28
27
|
if (!json) {
|
|
29
|
-
logger.debug(
|
|
30
|
-
"Received incompletely specified metric normalization rule from collector."
|
|
31
|
-
)
|
|
28
|
+
logger.debug('Received incompletely specified metric normalization rule from collector.')
|
|
32
29
|
json = Object.create(null)
|
|
33
30
|
}
|
|
34
31
|
|
|
@@ -41,7 +38,9 @@ function NormalizerRule(json) {
|
|
|
41
38
|
this.matched = false
|
|
42
39
|
|
|
43
40
|
var modifiers = 'i'
|
|
44
|
-
if (this.replaceAll)
|
|
41
|
+
if (this.replaceAll) {
|
|
42
|
+
modifiers += 'g'
|
|
43
|
+
}
|
|
45
44
|
|
|
46
45
|
// don't allow this to fail
|
|
47
46
|
if (json.match_expression instanceof RegExp) {
|
|
@@ -50,7 +49,7 @@ function NormalizerRule(json) {
|
|
|
50
49
|
try {
|
|
51
50
|
this.pattern = new RegExp(json.match_expression || '^$', modifiers)
|
|
52
51
|
} catch (error) {
|
|
53
|
-
logger.warn(error,
|
|
52
|
+
logger.warn(error, 'Problem compiling metric normalization rule pattern.')
|
|
54
53
|
this.pattern = /^$/
|
|
55
54
|
}
|
|
56
55
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
-
var logger = require('../../logger').child({component: 'tx_segment_normalizer'})
|
|
8
|
+
var logger = require('../../logger').child({ component: 'tx_segment_normalizer' })
|
|
9
9
|
|
|
10
10
|
module.exports = TxSegmentNormalizer
|
|
11
11
|
|
|
@@ -50,13 +50,17 @@ TxSegmentNormalizer.prototype.normalize = function normalize(path) {
|
|
|
50
50
|
for (var j = 0; j < parts.length; j++) {
|
|
51
51
|
segment = parts[j]
|
|
52
52
|
|
|
53
|
-
if (segment === '' && j + 1 === parts.length)
|
|
53
|
+
if (segment === '' && j + 1 === parts.length) {
|
|
54
|
+
break
|
|
55
|
+
}
|
|
54
56
|
|
|
55
57
|
if (currentTerm.terms.indexOf(segment) === -1) {
|
|
56
|
-
if (prev === '*')
|
|
57
|
-
|
|
58
|
+
if (prev === '*') {
|
|
59
|
+
continue
|
|
60
|
+
}
|
|
61
|
+
result.push((prev = '*'))
|
|
58
62
|
} else {
|
|
59
|
-
result.push(prev = segment)
|
|
63
|
+
result.push((prev = segment))
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
logger.trace('Normalizing %s because of rule: %s', path, currentTerm)
|
|
@@ -69,7 +73,7 @@ TxSegmentNormalizer.prototype.normalize = function normalize(path) {
|
|
|
69
73
|
|
|
70
74
|
return {
|
|
71
75
|
matched: false, // To match MetricNormalizer
|
|
72
|
-
ignore: false,
|
|
76
|
+
ignore: false, // ^^
|
|
73
77
|
value: path
|
|
74
78
|
}
|
|
75
79
|
}
|
|
@@ -78,11 +82,7 @@ TxSegmentNormalizer.prototype.load = function load(json) {
|
|
|
78
82
|
if (Array.isArray(json)) {
|
|
79
83
|
this.terms = filterRules(json)
|
|
80
84
|
} else {
|
|
81
|
-
logger.warn(
|
|
82
|
-
'transaction_segment_terms was not an array got: %s (%s)',
|
|
83
|
-
typeof json,
|
|
84
|
-
json
|
|
85
|
-
)
|
|
85
|
+
logger.warn('transaction_segment_terms was not an array got: %s (%s)', typeof json, json)
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -92,7 +92,9 @@ function filterRules(rules) {
|
|
|
92
92
|
for (var i = 0, l = rules.length; i < l; ++i) {
|
|
93
93
|
var prefix = rules[i].prefix
|
|
94
94
|
|
|
95
|
-
if (!prefix || typeof prefix !== 'string')
|
|
95
|
+
if (!prefix || typeof prefix !== 'string') {
|
|
96
|
+
continue
|
|
97
|
+
}
|
|
96
98
|
|
|
97
99
|
if (prefix[prefix.length - 1] !== '/') {
|
|
98
100
|
prefix = prefix + '/'
|
|
@@ -100,7 +102,9 @@ function filterRules(rules) {
|
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
var segments = prefix.split('/')
|
|
103
|
-
if (segments.length !== 3 || !segments[0] || !segments[1] || segments[3])
|
|
105
|
+
if (segments.length !== 3 || !segments[0] || !segments[1] || segments[3]) {
|
|
106
|
+
continue
|
|
107
|
+
}
|
|
104
108
|
|
|
105
109
|
if (Array.isArray(rules[i].terms)) {
|
|
106
110
|
map[prefix] = rules[i]
|