diff --git a/lib/metrics.js b/lib/metrics.js index 1a7b6252ed..d1958d99c9 100644 --- a/lib/metrics.js +++ b/lib/metrics.js @@ -8,7 +8,12 @@ const { FEATURE_REVIVED, } = require('./event-type'); -exports.startMonitoring = (enable, eventBus, eventStore) => { +exports.startMonitoring = ( + enable, + eventBus, + eventStore, + clientMetricsStore +) => { if (!enable) { return; } @@ -30,6 +35,11 @@ exports.startMonitoring = (enable, eventBus, eventStore) => { help: 'Number of times a toggle has been updated', labelNames: ['toggle'], }); + const featureToggleUsageTotal = new client.Counter({ + name: 'feature_toggle_usage_total', + help: 'Number of times a feature toggle has been used', + labelNames: ['toggle', 'active'], + }); eventBus.on(events.REQUEST_TIME, ({ path, method, time, statusCode }) => { requestDuration.labels(path, method, statusCode).observe(time); @@ -47,4 +57,11 @@ exports.startMonitoring = (enable, eventBus, eventStore) => { eventStore.on(FEATURE_REVIVED, ({ data }) => { featureToggleUpdateTotal.labels(data.name).inc(); }); + + clientMetricsStore.on('metrics', m => { + for (const [feature, { yes, no }] of Object.entries(m.bucket.toggles)) { + featureToggleUsageTotal.labels(feature, true).inc(yes); + featureToggleUsageTotal.labels(feature, false).inc(no); + } + }); }; diff --git a/lib/metrics.test.js b/lib/metrics.test.js index a86dbd5e6f..43385addd1 100644 --- a/lib/metrics.test.js +++ b/lib/metrics.test.js @@ -4,13 +4,14 @@ const { test } = require('ava'); const { EventEmitter } = require('events'); const eventBus = new EventEmitter(); const eventStore = new EventEmitter(); +const clientMetricsStore = 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); + startMonitoring(true, eventBus, eventStore, clientMetricsStore); }); test('should collect metrics for requests', t => { @@ -36,3 +37,22 @@ test('should collect metrics for updated toggles', t => { const metrics = prometheusRegister.metrics(); t.regex(metrics, /feature_toggle_update_total{toggle="TestToggle"} 1/); }); + +test('should collect metrics for client metric reports', t => { + clientMetricsStore.emit('metrics', { + bucket: { + toggles: { + TestToggle: { + yes: 10, + no: 5, + }, + }, + }, + }); + + const metrics = prometheusRegister.metrics(); + t.regex( + metrics, + /feature_toggle_usage_total{toggle="TestToggle",active="true"} 10\nfeature_toggle_usage_total{toggle="TestToggle",active="false"} 5/ + ); +}); diff --git a/lib/server-impl.js b/lib/server-impl.js index b730105ef6..f21b389859 100644 --- a/lib/server-impl.js +++ b/lib/server-impl.js @@ -26,7 +26,12 @@ function createApp(options) { ); const app = getApp(config); - startMonitoring(options.serverMetrics, eventBus, stores.eventStore); + startMonitoring( + options.serverMetrics, + eventBus, + stores.eventStore, + stores.clientMetricsStore + ); const server = app.listen({ port: options.port, host: options.host }, () => logger.info(`Unleash started on port ${server.address().port}`)