Appearance
Metrics
Overview
The Metrics Module (src/modules/metrics/) exposes runtime and HTTP metrics in Prometheus text format, backed by prom-client. It is disabled by default and, when enabled, is served from a single admin-only endpoint (GET /server/metrics).
The module has two parts:
- Instrumentation — Fastify hooks (
onRequest/onResponse) that observe every request into a set of HTTP metrics. - Exposition — the
GET /server/metricsendpoint that renders the current registry as Prometheus text.
Enabling Metrics
Metrics collection and the endpoint are gated by the METRICS_ENABLED environment variable (default false). When disabled:
registerMetricsHooks(app)is a no-op — no hooks are registered and no metrics are collected.GET /server/metricsreturns404 Not Found({ "error": "Metrics not enabled" }).
| Variable | Default | Description |
|---|---|---|
METRICS_ENABLED | false | Master switch. Set to true to register instrumentation hooks and enable the endpoint. |
METRICS_NAME_PREFIX | odp_ | Prefix applied to every metric name (both default and HTTP metrics). |
Endpoint
GET /server/metrics
Return the current metrics in Prometheus text format.
Auth required: Yes — admin only (requireAdmin preHandler).
Response 200 — Content-Type: text/plain; version=0.0.4 (from prom-client's registry content type), body is the Prometheus exposition text.
Response 404 — when METRICS_ENABLED is false:
json
{ "error": "Metrics not enabled" }Collected Metrics
All metric names are prefixed with METRICS_NAME_PREFIX (default odp_).
Default runtime metrics
prom-client's collectDefaultMetrics({ prefix }) registers the standard Node.js process metrics: CPU usage, resident/heap memory, event-loop lag, garbage collection, active handles/requests, and process start time.
HTTP metrics
| Metric | Type | Labels | Description |
|---|---|---|---|
{prefix}http_requests_total | Counter | method, route, status_code | Total number of HTTP requests processed |
{prefix}http_request_duration_seconds | Histogram | method, route, status_code | Request duration in seconds. Buckets: 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10 |
{prefix}http_active_connections | Gauge | — | Requests currently being processed (incremented on onRequest, decremented on onResponse) |
{prefix}http_request_size_bytes | Histogram | method, route | Size of request bodies in bytes (from the content-length header). Buckets: 100 … 10_000_000 |
{prefix}http_response_size_bytes | Histogram | method, route, status_code | Size of response bodies in bytes (from the response content-length header). Buckets: 100 … 10_000_000 |
Sizes are recorded only when a content-length is present and greater than zero.
Instrumentation
registerMetricsHooks(app) is called during server setup (createServer()) and wires two Fastify hooks when METRICS_ENABLED is true:
onRequest— stamps a high-resolution start time on the request and incrementshttp_active_connections.onResponse— computes duration from the start time, incrementshttp_requests_total, decrementshttp_active_connections, and observes request/response sizes.
Route normalisation
To avoid high-cardinality labels, the route label is derived by normaliseRoute(), which prefers Fastify's matched route pattern (request.routeOptions.url, e.g. /items/:collection/:pk) over the raw URL. This keeps per-route series bounded regardless of dynamic path parameters. If no route pattern is available, it falls back to the request path with the query string stripped.
Programmatic API
Exported from src/modules/metrics/index.ts:
| Export | Purpose |
|---|---|
initMetrics() | Lazily and idempotently create the metric instruments and register default metrics. |
registerMetricsHooks(app) | Register the onRequest / onResponse instrumentation hooks (no-op when disabled). |
getMetricsOutput() | Return the Prometheus text-format string for the current registry. |
getMetricsContentType() | Return the registry's content type for the response. |
resetMetrics() | Clear the registry and reset init state (used in tests). |