Skip to content

Commit afbaef2

Browse files
franckOLlholmquist
authored andcommitted
feat: allow to add circuits dynamicaly (nodeshift#7)
* feat: allow to add circuits dynamically
1 parent 02ca8f5 commit afbaef2

File tree

3 files changed

+91
-8
lines changed

3 files changed

+91
-8
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ Example:
2424
// Provide them to the constructor
2525
const prometheus = new PrometheusMetrics([c1, c2]);
2626

27+
//...
28+
// Provide other circuit breaker later
29+
const c3 = new CircuitBreaker(someOtherfunction3);
30+
prometheus.add([C3]);
31+
2732
// Write metrics to the console
2833
console.log(prometheus.metrics);
2934
```

index.js

+13-4
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ function normalizePrefix (prefixName) {
1515

1616
class PrometheusMetrics {
1717
constructor (circuits, registry) {
18-
if (!circuits) {
19-
throw new Error('A circuit or a list of circuits is required');
18+
if (circuits instanceof client.Registry) {
19+
registry = circuits;
20+
circuits = undefined;
2021
}
2122

22-
circuits = Array.isArray(circuits) ? circuits : [circuits];
23-
2423
this._registry = registry || client.register;
2524
this._client = client;
2625
this.counters = [];
@@ -30,6 +29,16 @@ class PrometheusMetrics {
3029
.collectDefaultMetrics({ prefix: 'opossum_', timeout: 5000 });
3130
}
3231

32+
if (circuits) {
33+
this.add(circuits);
34+
}
35+
}
36+
37+
add (circuits) {
38+
if (!circuits) {
39+
return;
40+
}
41+
circuits = Array.isArray(circuits) ? circuits : [circuits];
3342
let prefix;
3443
circuits.forEach(circuit => {
3544
prefix = normalizePrefix(circuit.name);

test/prometheus-test.js

+73-4
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ function passFail (x) {
2020
});
2121
}
2222

23-
test('The factory function errors when no circuits are passed in', t => {
23+
test('The factory function accept no parameter', t => {
2424
t.plan(1);
2525

26-
t.throws(() => {
27-
new PrometheusMetrics();
28-
}, 'A circuit or a list of circuits is required');
26+
const prometheus = new PrometheusMetrics();
27+
t.ok(prometheus);
28+
prometheus.clear();
2929

3030
t.end();
3131
});
@@ -73,6 +73,43 @@ test('The factory function uses a custom prom-client registry', t => {
7373
t.end();
7474
});
7575

76+
test('The add function takes an object instead of just an Array', t => {
77+
t.plan(2);
78+
const c1 = new CircuitBreaker(passFail, { name: 'fred' });
79+
const prometheus = new PrometheusMetrics();
80+
prometheus.add(c1);
81+
t.equal(c1.name, 'fred');
82+
t.ok(/circuit_fred_/.test(prometheus.metrics));
83+
prometheus.clear();
84+
t.end();
85+
});
86+
87+
test('The add function provides access to metrics for all circuits', t => {
88+
t.plan(6);
89+
const c1 = new CircuitBreaker(passFail, { name: 'fred' });
90+
const c2 = new CircuitBreaker(passFail, { name: 'bob' });
91+
const c3 = new CircuitBreaker(passFail, { name: 'foo' });
92+
const prometheus = new PrometheusMetrics([c1]);
93+
prometheus.add([c2, c3]);
94+
t.equal(c1.name, 'fred');
95+
t.equal(c2.name, 'bob');
96+
t.equal(c3.name, 'foo');
97+
t.ok(/circuit_fred_/.test(prometheus.metrics));
98+
t.ok(/circuit_bob_/.test(prometheus.metrics));
99+
t.ok(/circuit_foo_/.test(prometheus.metrics));
100+
prometheus.clear();
101+
t.end();
102+
});
103+
104+
test('The add function accepts zero parameters', t => {
105+
t.plan(1);
106+
const prometheus = new PrometheusMetrics();
107+
prometheus.add();
108+
t.notOk(/circuit_/.test(prometheus.metrics));
109+
prometheus.clear();
110+
t.end();
111+
});
112+
76113
test('Circuit fire/success/failure are counted', t => {
77114
const circuit = new CircuitBreaker(passFail);
78115
const fire = /circuit_passFail_fire 2/;
@@ -150,6 +187,38 @@ test('Should not add default metrics to custom registry', t => {
150187
t.end();
151188
});
152189

190+
test('Default prometheus metrics are enabled without circuit', t => {
191+
const registry = new Registry();
192+
const prometheus = new PrometheusMetrics(registry);
193+
const metrics = prometheus.metrics;
194+
const names = [
195+
'nodejs_eventloop_lag',
196+
'nodejs_active_handles',
197+
'nodejs_active_requests',
198+
'nodejs_heap_size_total_bytes',
199+
'nodejs_heap_size_used_bytes',
200+
'nodejs_external_memory_bytes',
201+
'nodejs_heap_space_size_total_bytes',
202+
'nodejs_heap_space_size_used_bytes',
203+
'nodejs_heap_space_size_available_bytes',
204+
'nodejs_version_info',
205+
'process_cpu_seconds_total',
206+
'process_open_fds',
207+
'process_max_fds',
208+
'process_virtual_memory_bytes',
209+
'process_resident_memory_bytes',
210+
'process_heap_bytes',
211+
'process_start_time_seconds'
212+
];
213+
t.plan(names.length);
214+
for (const name of names) {
215+
const match = new RegExp(`opossum_${name}`);
216+
t.notOk(match.test(metrics), name);
217+
}
218+
prometheus.clear();
219+
t.end();
220+
});
221+
153222
test('Node.js specific metrics are enabled', t => {
154223
const circuit = new CircuitBreaker(passFail);
155224
const prometheus = new PrometheusMetrics([circuit]);

0 commit comments

Comments
 (0)