Skip to content

Commit 8941f1d

Browse files
Qardwatson
authored andcommitted
feat(metrics): add metricsLimit option (#1273)
Fixes #1249
1 parent 328aacc commit 8941f1d

File tree

7 files changed

+45
-2
lines changed

7 files changed

+45
-2
lines changed

docs/configuration.asciidoc

+11
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,17 @@ or should include a time suffix.
719719
To disable metrics reporting,
720720
set the interval to `0`.
721721

722+
[[metrics-limit]]
723+
==== `metricsLimit`
724+
725+
* *Type:* Number
726+
* *Default:* `1000`
727+
* *Env:* `ELASTIC_APM_METRICS_LIMIT`
728+
729+
Specify the maximum number of metrics to track at any given time.
730+
When a new metric is inserted which would exceed the limit,
731+
the oldest metric will be dropped to give it space.
732+
722733
[[global-labels]]
723734
==== `globalLabels`
724735

lib/config.js

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ var DEFAULTS = {
6868
kubernetesPodUID: undefined,
6969
logLevel: 'info',
7070
metricsInterval: '30s',
71+
metricsLimit: 1000,
7172
centralConfig: true,
7273
serverTimeout: '30s',
7374
sourceLinesErrorAppFrames: 5,
@@ -111,6 +112,7 @@ var ENV_TABLE = {
111112
kubernetesPodUID: ['ELASTIC_APM_KUBERNETES_POD_UID', 'KUBERNETES_POD_UID'],
112113
logLevel: 'ELASTIC_APM_LOG_LEVEL',
113114
metricsInterval: 'ELASTIC_APM_METRICS_INTERVAL',
115+
metricsLimit: 'ELASTIC_APM_METRICS_LIMIT',
114116
payloadLogFile: 'ELASTIC_APM_PAYLOAD_LOG_FILE',
115117
centralConfig: 'ELASTIC_APM_CENTRAL_CONFIG',
116118
secretToken: 'ELASTIC_APM_SECRET_TOKEN',
@@ -153,6 +155,7 @@ var BOOL_OPTS = [
153155
]
154156

155157
var NUM_OPTS = [
158+
'metricsLimit',
156159
'sourceLinesErrorAppFrames',
157160
'sourceLinesErrorLibraryFrames',
158161
'sourceLinesSpanAppFrames',

lib/metrics/registry.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const os = require('os')
44

55
const { SelfReportingMetricsRegistry } = require('measured-reporting')
6+
const DimensionAwareMetricsRegistry = require('measured-reporting/lib/registries/DimensionAwareMetricsRegistry')
67

78
const MetricsReporter = require('./reporter')
89
const createRuntimeMetrics = require('./runtime')
@@ -11,7 +12,7 @@ const createSystemMetrics = process.platform === 'linux'
1112
: require('./platforms/generic')
1213

1314
class MetricsRegistry extends SelfReportingMetricsRegistry {
14-
constructor (agent, { reporterOptions, registryOptions } = {}) {
15+
constructor (agent, { reporterOptions, registryOptions = {} } = {}) {
1516
const defaultReporterOptions = {
1617
defaultDimensions: {
1718
hostname: agent._conf.hostname || os.hostname(),
@@ -22,6 +23,10 @@ class MetricsRegistry extends SelfReportingMetricsRegistry {
2223
const options = Object.assign({}, defaultReporterOptions, reporterOptions)
2324
const reporter = new MetricsReporter(agent, options)
2425

26+
registryOptions.registry = new DimensionAwareMetricsRegistry({
27+
metricLimit: agent._conf.metricsLimit
28+
})
29+
2530
super(reporter, registryOptions)
2631
this._agent = agent
2732

lib/metrics/reporter.js

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class MetricsReporter extends Reporter {
2828
const seen = new ObjectIdentityMap()
2929

3030
for (const metric of metrics) {
31+
// Due to limitations in measured-reporting, metrics dropped
32+
// due to `metricsLimit` leave empty slots in the list.
33+
if (!metric) continue
3134
const data = seen.ensure(metric.dimensions, () => {
3235
const metricData = unflattenBreakdown(metric.dimensions)
3336
const merged = Object.assign({ samples: {} }, baseDimensions, metricData)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"fast-safe-stringify": "^2.0.6",
8585
"http-headers": "^3.0.2",
8686
"is-native": "^1.0.1",
87-
"measured-reporting": "^1.49.0",
87+
"measured-reporting": "^1.50.0",
8888
"monitor-event-loop-delay": "^1.0.0",
8989
"object-filter-sequence": "^1.0.0",
9090
"object-identity-map": "^1.0.1",

test/config.js

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ var optionFixtures = [
5252
['kubernetesPodUID', 'KUBERNETES_POD_UID'],
5353
['logLevel', 'LOG_LEVEL', 'info'],
5454
['metricsInterval', 'METRICS_INTERVAL', 30],
55+
['metricsLimit', 'METRICS_LIMIT', 1000],
5556
['secretToken', 'SECRET_TOKEN'],
5657
['serverTimeout', 'SERVER_TIMEOUT', 30],
5758
['serverUrl', 'SERVER_URL'],

test/metrics/index.js

+20
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,26 @@ test('reports expected metrics', function (t) {
145145
metrics.start()
146146
})
147147

148+
test('applies metrics limit', function (t) {
149+
agent = mockAgent({
150+
metricsInterval: 10,
151+
metricsLimit: 2,
152+
hostname: 'foo',
153+
environment: 'bar'
154+
}, (metricset = {}) => {
155+
t.equal(Object.keys(metricset.samples).length, 2, 'has expected number of metrics')
156+
t.end()
157+
})
158+
159+
metrics = new Metrics(agent)
160+
metrics.start()
161+
162+
// Ensure there are at least two counters
163+
metrics.getOrCreateCounter('first').inc()
164+
metrics.getOrCreateCounter('second').inc()
165+
metrics.getOrCreateCounter('third').inc()
166+
})
167+
148168
function spinCPUFor (durationMs) {
149169
const start = Date.now()
150170
while (Date.now() - start < durationMs) {}

0 commit comments

Comments
 (0)