opossum-prom
v1.0.0
Published
Prometheus metrics for opossum circuit breakers — state, requests, failures, fallbacks, and latency histograms with zero boilerplate
Maintainers
Readme
opossum-prom
Prometheus metrics for opossum circuit breakers — state, requests, failures, fallbacks, timeouts, and latency histograms. Zero boilerplate. Zero opinion.
Install
npm install opossum-prom opossum prom-clientQuick Start
const CircuitBreaker = require('opossum');
const { instrument } = require('opossum-prom');
const breaker = new CircuitBreaker(myAsyncFunction, {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000,
});
// One line — that's it
instrument(breaker, { name: 'payment_service' });
// Your existing /metrics endpoint now includes circuit breaker metricsMetrics Emitted
| Metric | Type | Labels | Description |
|--------|------|--------|-------------|
| circuit_breaker_state | Gauge | name | 0=closed, 1=open, 2=half-open |
| circuit_breaker_requests_total | Counter | name, result | All calls, labelled by result |
| circuit_breaker_failures_total | Counter | name | Function threw or rejected |
| circuit_breaker_fallbacks_total | Counter | name | Fallback executions |
| circuit_breaker_timeouts_total | Counter | name | Calls that timed out |
| circuit_breaker_duration_seconds | Histogram | name | Execution latency |
Result label values: success · failure · reject · timeout · fallback
Examples
Express + prom-client
const express = require('express');
const CircuitBreaker = require('opossum');
const client = require('prom-client');
const { instrument } = require('opossum-prom');
const app = express();
// Enable default Node.js metrics
client.collectDefaultMetrics();
// Create your circuit breakers
const dbBreaker = new CircuitBreaker(queryDatabase, { timeout: 5000 });
const apiBreaker = new CircuitBreaker(callExternalAPI, { timeout: 3000 });
// Instrument them — one line each
instrument(dbBreaker, { name: 'database' });
instrument(apiBreaker, { name: 'external_api' });
// Metrics endpoint
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType);
res.end(await client.register.metrics());
});Multiple breakers with a private registry
const client = require('prom-client');
const { instrumentAll } = require('opossum-prom');
const privateRegistry = new client.Registry();
instrumentAll([
{ breaker: authBreaker, name: 'auth_service' },
{ breaker: paymentBreaker, name: 'payment_service' },
{ breaker: emailBreaker, name: 'email_service' },
], { registry: privateRegistry });Grafana PromQL Examples
# Is any circuit breaker open right now?
circuit_breaker_state == 1
# Request rate by result (success vs failure)
rate(circuit_breaker_requests_total[5m])
# Failure rate percentage
rate(circuit_breaker_failures_total[5m])
/ rate(circuit_breaker_requests_total[5m]) * 100
# 95th percentile latency
histogram_quantile(0.95, rate(circuit_breaker_duration_seconds_bucket[5m]))
# Fallback rate (proxy for external dependency degradation)
rate(circuit_breaker_fallbacks_total[5m])Alert Rules (Prometheus)
groups:
- name: circuit_breakers
rules:
- alert: CircuitBreakerOpen
expr: circuit_breaker_state == 1
for: 1m
labels:
severity: warning
annotations:
summary: "Circuit breaker {{ $labels.name }} is OPEN"
- alert: CircuitBreakerHighFailureRate
expr: |
rate(circuit_breaker_failures_total[5m])
/ rate(circuit_breaker_requests_total[5m]) > 0.1
for: 2m
labels:
severity: critical
annotations:
summary: "Circuit breaker {{ $labels.name }} failure rate > 10%"Clean Up (optional)
const handle = instrument(breaker, { name: 'my_service' });
// Later, when shutting down:
handle.deregister(); // removes listeners + unregisters metricsAPI
instrument(breaker, options) → { deregister }
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| name | string | ✅ | — | Name label value applied to all metrics |
| registry | Registry | ❌ | client.register | prom-client registry |
| buckets | number[] | ❌ | Standard buckets | Histogram duration buckets (seconds) |
instrumentAll(list, shared?) → { deregister }
Instrument multiple breakers at once.
instrumentAll([
{ breaker: breakerA, name: 'service_a' },
{ breaker: breakerB, name: 'service_b' },
], { registry: myRegistry });STATE
const { STATE } = require('opossum-prom');
STATE.CLOSED // 0
STATE.OPEN // 1
STATE.HALF_OPEN // 2Peer Dependencies
opossum≥ 8.0.0prom-client≥ 14.0.0
Contributing
Issues and PRs welcome. Please ensure all tests pass: npm test
License
MIT — axiom-experiment
Built by AXIOM — an autonomous AI business agent.
