From bc359c2b82a6bc42b83fb29a79810440304a1470 Mon Sep 17 00:00:00 2001 From: ivaosthu Date: Wed, 23 May 2018 11:24:24 +0200 Subject: [PATCH] feat(metrics): Expose toggle updates to prometheus closes #323 --- docs/api/internal-backstage-api.md | 13 ++++++++++++- lib/metrics.js | 26 +++++++++++++++++++++++++- lib/metrics.test.js | 16 +++++++++++++++- lib/server-impl.js | 2 +- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/docs/api/internal-backstage-api.md b/docs/api/internal-backstage-api.md index 5146d8baaf..ab11889779 100644 --- a/docs/api/internal-backstage-api.md +++ b/docs/api/internal-backstage-api.md @@ -5,4 +5,15 @@ Unleash uses prometheus internally to collect metrics. These are available on the given url if the `serverMetrics` option is enabled (default=true). -[Read more about Prometheus](https://prometheus.io/) \ No newline at end of file +[Read more about Prometheus](https://prometheus.io/) + +## Annotations + +Unleash will automatically count all updates for all toggles under the metric name `feature_toggle_update_total`, and the toggle name is will be set as a label value. This information can be used to create annotations in grafana for everytime a feature toggle is changed. + +You can use this query in grafana to achive this: + +``` +delta(feature_toggle_update_total{toggle="Demo"}[1m]) != bool 0? +``` + diff --git a/lib/metrics.js b/lib/metrics.js index f88b13dc28..1a7b6252ed 100644 --- a/lib/metrics.js +++ b/lib/metrics.js @@ -1,8 +1,14 @@ 'use strict'; const events = require('./events'); +const { + FEATURE_CREATED, + FEATURE_UPDATED, + FEATURE_ARCHIVED, + FEATURE_REVIVED, +} = require('./event-type'); -exports.startMonitoring = (enable, eventBus) => { +exports.startMonitoring = (enable, eventBus, eventStore) => { if (!enable) { return; } @@ -19,8 +25,26 @@ exports.startMonitoring = (enable, eventBus) => { labelNames: ['path', 'method', 'status'], percentiles: [0.1, 0.5, 0.9, 0.99], }); + const featureToggleUpdateTotal = new client.Counter({ + name: 'feature_toggle_update_total', + help: 'Number of times a toggle has been updated', + labelNames: ['toggle'], + }); eventBus.on(events.REQUEST_TIME, ({ path, method, time, statusCode }) => { requestDuration.labels(path, method, statusCode).observe(time); }); + + eventStore.on(FEATURE_CREATED, ({ data }) => { + featureToggleUpdateTotal.labels(data.name).inc(); + }); + eventStore.on(FEATURE_UPDATED, ({ data }) => { + featureToggleUpdateTotal.labels(data.name).inc(); + }); + eventStore.on(FEATURE_ARCHIVED, ({ data }) => { + featureToggleUpdateTotal.labels(data.name).inc(); + }); + eventStore.on(FEATURE_REVIVED, ({ data }) => { + featureToggleUpdateTotal.labels(data.name).inc(); + }); }; diff --git a/lib/metrics.test.js b/lib/metrics.test.js index 729984805f..a86dbd5e6f 100644 --- a/lib/metrics.test.js +++ b/lib/metrics.test.js @@ -3,12 +3,17 @@ const { test } = require('ava'); const { EventEmitter } = require('events'); const eventBus = new EventEmitter(); +const eventStore = new EventEmitter(); const { REQUEST_TIME } = require('./events'); +const { FEATURE_UPDATED } = require('./event-type'); const { startMonitoring } = require('./metrics'); const { register: prometheusRegister } = require('prom-client'); +test.before(() => { + startMonitoring(true, eventBus, eventStore); +}); + test('should collect metrics for requests', t => { - startMonitoring(true, eventBus); eventBus.emit(REQUEST_TIME, { path: 'somePath', method: 'GET', @@ -22,3 +27,12 @@ test('should collect metrics for requests', t => { /http_request_duration_milliseconds{quantile="0\.99",path="somePath",method="GET",status="200"} 1337/ ); }); + +test('should collect metrics for updated toggles', t => { + eventStore.emit(FEATURE_UPDATED, { + data: { name: 'TestToggle' }, + }); + + const metrics = prometheusRegister.metrics(); + t.regex(metrics, /feature_toggle_update_total{toggle="TestToggle"} 1/); +}); diff --git a/lib/server-impl.js b/lib/server-impl.js index 167eef71f9..b730105ef6 100644 --- a/lib/server-impl.js +++ b/lib/server-impl.js @@ -26,7 +26,7 @@ function createApp(options) { ); const app = getApp(config); - startMonitoring(options.serverMetrics, eventBus); + startMonitoring(options.serverMetrics, eventBus, stores.eventStore); const server = app.listen({ port: options.port, host: options.host }, () => logger.info(`Unleash started on port ${server.address().port}`)