Skip to content

feat(metrics): expose HTTP RED metrics (request rate + duration)#709

Merged
rmyndharis merged 1 commit into
mainfrom
feat/http-red-metrics
Jul 12, 2026
Merged

feat(metrics): expose HTTP RED metrics (request rate + duration)#709
rmyndharis merged 1 commit into
mainfrom
feat/http-red-metrics

Conversation

@rmyndharis

Copy link
Copy Markdown
Owner

What

/api/metrics now exposes HTTP RED metrics: http_requests_total{method,route,status} (counter) and http_request_duration_seconds (histogram, per route), recorded by a new global RequestMetricsInterceptor.

Why

The metrics surface had business gauges/counters (sessions, messages, webhook failures) but no request rate/error/latency — so an SLO, an error-rate alert, or a latency dashboard had nothing to read. This adds the standard RED signals.

Design

  • Dependency-free — extends the existing bespoke Prometheus-text-exposition layer (no prom-client), mirroring webhook-delivery-metrics.ts. Conventional unprefixed names (http_requests_total, http_request_duration_seconds) so a generic RED dashboard/alert matches.
  • Sees the real status — the interceptor listens to res finish/close, not the handler observable's tap, because exception filters set the final statusCode after the interceptor's observable chain. One observation per request (a recorded guard handles both events firing).
  • Bounded cardinality — route label is the Express route pattern (/api/sessions/:id, not the raw URL); falls back to Controller#handler when no Express route. /api/health and /api/metrics are not counted.

Test plan

  • Store: request-metrics.spec.ts (6 cases) — counter aggregation, cumulative histogram buckets, HELP/TYPE emitted once, label escaping, reset. TDD: written first against a stub, watched fail, then implemented.
  • Interceptor: request-metrics.interceptor.spec.ts (5 cases) — records on finish with method/route/status/duration, skips health/metrics, records filter-set 5xx, Controller#handler fallback, single record across finish+close.
  • Full gate green locally: lint, tsc -p tsconfig.json (full program), format, nest build, 2301 tests.

Add http_requests_total{method,route,status} and an
http_request_duration_seconds histogram (per route) to /api/metrics,
recorded by a global RequestMetricsInterceptor. The interceptor listens
for response finish/close (so it sees the final status set by exception
filters, not the pre-filter 200), records once per request, and skips
/api/health + /api/metrics. Route labels use the Express route pattern
(bounded) with a Controller#handler fallback. Dependency-free (no
prom-client), extending the existing bespoke Prometheus-text layer;
conventional unprefixed names so a generic RED dashboard or 5xx
error-rate alert matches them.
@rmyndharis rmyndharis merged commit ebe4525 into main Jul 12, 2026
10 checks passed
@rmyndharis rmyndharis deleted the feat/http-red-metrics branch July 12, 2026 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant