Skip to content

Commit

Permalink
feat: add stats (percentiles stats, reponse times) in Prometheus metr…
Browse files Browse the repository at this point in the history
…ics (nodeshift#10)

Fixes: nodeshift#1
  • Loading branch information
franckOL authored and lance committed Oct 2, 2019
1 parent 910e5db commit 712fa2d
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class PrometheusMetrics {
this._registry = registry || client.register;
this._client = client;
this.counters = [];
this.summaries = [];

if (!registry) {
this.interval = this._client
Expand Down Expand Up @@ -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);
}
}
});
}
Expand Down
23 changes: 17 additions & 6 deletions test/prometheus-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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' });
Expand All @@ -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();
Expand Down

0 comments on commit 712fa2d

Please sign in to comment.