diff --git a/README.md b/README.md index 9e6dd7c..98bd22d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,11 @@ This module provides [Prometheus](https://prometheus.io/) metrics for it with your circuit breakers, just pass them in to the `PrometheusMetrics` constructor. +For each circuit breaker, the metrics are: + + * a `prometheus counter` for each event name + * a `prometheus summary` for the events `success`, `failed` execution time. + Example: ```js diff --git a/index.js b/index.js index 8820282..02f5ede 100644 --- a/index.js +++ b/index.js @@ -23,6 +23,7 @@ class PrometheusMetrics { this._registry = registry || client.register; this._client = client; this.counters = []; + this.summaries = []; if (!registry) { this.interval = this._client @@ -52,6 +53,20 @@ class PrometheusMetrics { counter.inc(); }); this.counters.push(counter); + + if (eventName === 'success' || eventName === 'failure') { + // not the timeout event because runtime == timeout + const summary = new this._client.Summary({ + name: `${prefix}${eventName}_perf`, + help: + `A summary of the ${circuit.name} circuit's ${eventName} event`, + registers: [this._registry] + }); + circuit.on(eventName, (result, runTime) => { + summary.observe(runTime); + }); + this.summaries.push(summary); + } } }); } diff --git a/test/prometheus-test.js b/test/prometheus-test.js index 44d32b4..b664f98 100644 --- a/test/prometheus-test.js +++ b/test/prometheus-test.js @@ -31,30 +31,33 @@ test('The factory function accept no parameter', t => { }); test('The factory function takes an object instead of just an Array', t => { - t.plan(2); + t.plan(3); const c1 = new CircuitBreaker(passFail, { name: 'fred' }); const prometheus = new PrometheusMetrics(c1); t.equal(c1.name, 'fred'); t.ok(/circuit_fred_/.test(prometheus.metrics)); + t.ok(/circuit_fred_.*perf/.test(prometheus.metrics)); prometheus.clear(); t.end(); }); test('The factory function provides access to metrics for all circuits', t => { - t.plan(4); + t.plan(6); const c1 = new CircuitBreaker(passFail, { name: 'fred' }); const c2 = new CircuitBreaker(passFail, { name: 'bob' }); const prometheus = new PrometheusMetrics([c1, c2]); t.equal(c1.name, 'fred'); t.equal(c2.name, 'bob'); t.ok(/circuit_fred_/.test(prometheus.metrics)); + t.ok(/circuit_fred_.*perf/.test(prometheus.metrics)); t.ok(/circuit_bob_/.test(prometheus.metrics)); + t.ok(/circuit_bob_.*perf/.test(prometheus.metrics)); prometheus.clear(); t.end(); }); test('The factory function uses a custom prom-client registry', t => { - t.plan(6); + t.plan(10); const registry = new Registry(); const c1 = new CircuitBreaker(passFail, { name: 'fred' @@ -66,26 +69,31 @@ test('The factory function uses a custom prom-client registry', t => { t.equal(c1.name, 'fred'); t.equal(c2.name, 'bob'); t.ok(/circuit_fred_/.test(registry.metrics())); + t.ok(/circuit_fred_.*perf/.test(registry.metrics())); t.ok(/circuit_bob_/.test(registry.metrics())); + t.ok(/circuit_bob_.*perf/.test(registry.metrics())); t.ok(/circuit_fred_/.test(prometheus.metrics)); + t.ok(/circuit_fred_.*perf/.test(prometheus.metrics)); t.ok(/circuit_bob_/.test(prometheus.metrics)); + t.ok(/circuit_bob_.*perf/.test(prometheus.metrics)); prometheus.clear(); t.end(); }); test('The add function takes an object instead of just an Array', t => { - t.plan(2); + t.plan(3); const c1 = new CircuitBreaker(passFail, { name: 'fred' }); const prometheus = new PrometheusMetrics(); prometheus.add(c1); t.equal(c1.name, 'fred'); t.ok(/circuit_fred_/.test(prometheus.metrics)); + t.ok(/circuit_fred_.*perf/.test(prometheus.metrics)); prometheus.clear(); t.end(); }); test('The add function provides access to metrics for all circuits', t => { - t.plan(6); + t.plan(9); const c1 = new CircuitBreaker(passFail, { name: 'fred' }); const c2 = new CircuitBreaker(passFail, { name: 'bob' }); const c3 = new CircuitBreaker(passFail, { name: 'foo' }); @@ -95,13 +103,16 @@ test('The add function provides access to metrics for all circuits', t => { t.equal(c2.name, 'bob'); t.equal(c3.name, 'foo'); t.ok(/circuit_fred_/.test(prometheus.metrics)); + t.ok(/circuit_fred_.*perf/.test(prometheus.metrics)); t.ok(/circuit_bob_/.test(prometheus.metrics)); + t.ok(/circuit_bob_.*perf/.test(prometheus.metrics)); t.ok(/circuit_foo_/.test(prometheus.metrics)); + t.ok(/circuit_foo_.*perf/.test(prometheus.metrics)); prometheus.clear(); t.end(); }); -test('The add function accepts zero parameters', t => { +test('The add function called without parameter do nothing', t => { t.plan(1); const prometheus = new PrometheusMetrics(); prometheus.add();