Skip to content

Commit e0d4c62

Browse files
authored
Add fake metric entry to populate prometheus (#35)
* Add fake metric entry to populate prometheus Signed-off-by: Matteo Collina <hello@matteocollina.com> * fixup Signed-off-by: Matteo Collina <hello@matteocollina.com> * added zeroFill Signed-off-by: Matteo Collina <hello@matteocollina.com> --------- Signed-off-by: Matteo Collina <hello@matteocollina.com>
1 parent b312216 commit e0d4c62

File tree

3 files changed

+114
-6
lines changed

3 files changed

+114
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ app.listen({ port: 0 }, (err, address) => {
5151
- __`ignore(req, res, server)`__ `<function>` A function that returns a boolean indicating whether to ignore the request when collecting metrics. The function receives the request object as a first argument and a response object as a second argument.
5252
- __`histogram`__ `<object>` prom-client [histogram options](https://github.com/siimon/prom-client?tab=readme-ov-file#histogram). Use it if you want to customize the histogram.
5353
- __`summary`__ `<object>` prom-client [summary options](https://github.com/siimon/prom-client?tab=readme-ov-file#summary). Use it if you want to customize the summary.
54+
- __`zeroFill`__ `<boolean>` Whether to zero-fill the histogram and summary buckets. Default: `false`.
5455

5556
## License
5657

index.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module.exports = fp(async function (fastify, opts) {
1717
const ignoreMethods = opts.ignoreMethods || defaultIgnoreMethods
1818
const ignoreRoutes = opts.ignoreRoutes || []
1919
const ignore = opts.ignore || (() => false)
20+
const zeroFill = opts.zeroFill || false
2021

2122
function ignoreRoute (request) {
2223
if (ignoreMethods.includes(request.method)) return true
@@ -35,6 +36,10 @@ module.exports = fp(async function (fastify, opts) {
3536
...opts.summary,
3637
})
3738

39+
if (zeroFill) {
40+
summary.observe({ method: 'GET', route: '/__empty_metrics', status_code: 404 }, 0)
41+
}
42+
3843
const histogram = new Histogram({
3944
name: 'http_request_duration_seconds',
4045
help: 'request duration in seconds',
@@ -43,6 +48,10 @@ module.exports = fp(async function (fastify, opts) {
4348
...opts.histogram,
4449
})
4550

51+
if (zeroFill) {
52+
histogram.zero({ method: 'GET', route: '/__empty_metrics', status_code: 404 })
53+
}
54+
4655
const timers = new WeakMap()
4756

4857
fastify.addHook('onRequest', async (req) => {
@@ -73,8 +82,12 @@ module.exports = fp(async function (fastify, opts) {
7382
...getCustomLabels(req, reply),
7483
}
7584

76-
if (summaryTimer) summaryTimer(labels)
77-
if (histogramTimer) histogramTimer(labels)
85+
if (summaryTimer) {
86+
summaryTimer(labels)
87+
}
88+
if (histogramTimer) {
89+
histogramTimer(labels)
90+
}
7891
})
7992
}, {
8093
name: 'fastify-http-metrics'

test/http-metrics.test.js

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,18 @@ test('should calculate the http request duration histogram', async (t) => {
4242

4343
{
4444
const histogramCount = histogramValues.find(
45-
({ metricName }) => metricName === 'http_request_duration_seconds_count'
45+
({ metricName, labels: { route } }) => {
46+
return metricName === 'http_request_duration_seconds_count' && route !== '/__empty_metrics'
47+
}
4648
)
4749
assert.strictEqual(histogramCount.value, expectedMeasurements.length)
4850
}
4951

5052
{
5153
const histogramSum = histogramValues.find(
52-
({ metricName }) => metricName === 'http_request_duration_seconds_sum'
54+
({ metricName, labels: { route } }) => {
55+
return metricName === 'http_request_duration_seconds_sum' && route !== '/__empty_metrics'
56+
}
5357
)
5458
const value = histogramSum.value
5559
const expectedValue = expectedMeasurements.reduce((a, b) => a + b, 0)
@@ -305,14 +309,14 @@ test('should calculate the http request duration histogram for injects', async (
305309

306310
{
307311
const histogramCount = histogramValues.find(
308-
({ metricName }) => metricName === 'http_request_duration_seconds_count'
312+
({ metricName, labels: { route } }) => metricName === 'http_request_duration_seconds_count' && route !== '/__empty_metrics'
309313
)
310314
assert.strictEqual(histogramCount.value, expectedMeasurements.length)
311315
}
312316

313317
{
314318
const histogramSum = histogramValues.find(
315-
({ metricName }) => metricName === 'http_request_duration_seconds_sum'
319+
({ metricName, labels: { route } }) => metricName === 'http_request_duration_seconds_sum' && route !== '/__empty_metrics'
316320
)
317321
const value = histogramSum.value
318322
const expectedValue = expectedMeasurements.reduce((a, b) => a + b, 0)
@@ -324,6 +328,8 @@ test('should calculate the http request duration histogram for injects', async (
324328
}
325329

326330
for (const { metricName, labels, value } of histogramValues) {
331+
if (labels.route === '/__empty_metrics') continue
332+
327333
assert.strictEqual(labels.method, 'GET')
328334
assert.strictEqual(labels.status_code, 200)
329335

@@ -446,3 +452,91 @@ test('should not throw if request timers are not found', async (t) => {
446452
const histogramValues = histogramMetric.values
447453
assert.strictEqual(histogramValues.length, 0)
448454
})
455+
456+
test('should provide a default timer value so that the summary and histogram are not empty', async (t) => {
457+
const app = createFastifyApp()
458+
459+
const registry = new Registry()
460+
app.register(httpMetrics, { registry, zeroFill: true })
461+
462+
await app.listen({ port: 0 })
463+
t.after(() => app.close())
464+
465+
const metrics = await registry.getMetricsAsJSON()
466+
assert.strictEqual(metrics.length, 2)
467+
468+
const histogramMetric = metrics.find(
469+
(metric) => metric.name === 'http_request_duration_seconds'
470+
)
471+
assert.strictEqual(histogramMetric.name, 'http_request_duration_seconds')
472+
assert.strictEqual(histogramMetric.type, 'histogram')
473+
assert.strictEqual(histogramMetric.help, 'request duration in seconds')
474+
assert.strictEqual(histogramMetric.aggregator, 'sum')
475+
476+
const histogramValues = histogramMetric.values
477+
478+
{
479+
const histogramCount = histogramValues.find(
480+
({ metricName }) => metricName === 'http_request_duration_seconds_count'
481+
)
482+
assert.strictEqual(histogramCount.value, 0)
483+
}
484+
485+
{
486+
const histogramSum = histogramValues.find(
487+
({ metricName }) => metricName === 'http_request_duration_seconds_sum'
488+
)
489+
const value = histogramSum.value
490+
assert.ok(
491+
value < 0.1
492+
)
493+
}
494+
495+
for (const { metricName, labels, value } of histogramValues) {
496+
assert.strictEqual(labels.method, 'GET')
497+
assert.strictEqual(labels.status_code, 404)
498+
499+
if (metricName !== 'http_request_duration_seconds_bucket') continue
500+
501+
assert.strictEqual(value, 0)
502+
}
503+
504+
const summaryMetric = metrics.find(
505+
(metric) => metric.name === 'http_request_summary_seconds'
506+
)
507+
assert.strictEqual(summaryMetric.name, 'http_request_summary_seconds')
508+
assert.strictEqual(summaryMetric.type, 'summary')
509+
assert.strictEqual(summaryMetric.help, 'request duration in seconds summary')
510+
assert.strictEqual(summaryMetric.aggregator, 'sum')
511+
512+
const summaryValues = summaryMetric.values
513+
514+
{
515+
const summaryCount = summaryValues.find(
516+
({ metricName }) => metricName === 'http_request_summary_seconds_count'
517+
)
518+
assert.strictEqual(summaryCount.value, 1)
519+
}
520+
521+
{
522+
const summarySum = summaryValues.find(
523+
({ metricName }) => metricName === 'http_request_summary_seconds_sum'
524+
)
525+
const value = summarySum.value
526+
assert.ok(
527+
value < 0.1
528+
)
529+
}
530+
531+
for (const { labels, value } of summaryValues) {
532+
assert.strictEqual(labels.method, 'GET')
533+
assert.strictEqual(labels.status_code, 404)
534+
535+
const quantile = labels.quantile
536+
if (quantile === undefined) continue
537+
538+
assert.ok(
539+
value < 0.1
540+
)
541+
}
542+
})

0 commit comments

Comments
 (0)