Public: anyone can read this; the crew can change it.

The existing GET /metrics also serves forge_http_request_duration_seconds, and docs/METRICS.md lists every family #3975

shipped production is serving it opened this has it
opened this

Part of the owner's Observability 1 ask (#3690). Replaces #3749, which tried to add a second /metrics route. Main already has one: src/http/api.ts (router.add("GET", "/metrics", …), #3719/#3721). It is on the API router, and src/http/server.ts sends /metrics there. It is admin-only through accountAdmin(ctx, "ro") and serves the egress families from src/apps/egress_metrics.ts. Extend that route. Add no route to the web router: a web-router route is what failed reserved names > every top-level page of the forge is a reserved name.

Done:

  • [ ] The same GET /metrics handler in src/http/api.ts now also answers with forge_http_request_duration_seconds. That family is a histogram labelled by route pattern, read from route_timing (src/core/route_timing.ts) over the last hour, with that module's EDGES_MS as buckets in seconds. It is built in a new src/metrics/forge.ts with src/metrics/openmetrics.ts. The egress families stay byte-for-byte what they are, so test/egress-metrics-route.test.ts passes unchanged.
  • [ ] Content type: keep the existing text/plain; version=0.0.4, or move the whole answer to application/openmetrics-text; version=1.0.0; charset=utf-8 with a trailing # EOF. Either way, one format for the whole body, and the pull says which.
  • [ ] Access, headers and cache-control: no-store are unchanged: 401 without credentials, 404 for a non-admin, and 200 for an admin's ro token.
  • [ ] docs/METRICS.md (new) lists every family /metrics serves (egress and duration) with its type, labels and meaning, and how to point Prometheus at it with an admin ro token. A test fails if the route serves a family the doc does not list.
  • [ ] A test records a request in route_timing and sees its bucket move on /metrics. bun test test/egress-metrics-route.test.ts test/reserved-names.test.ts test/design-audit.test.ts test/forge-looks.test.ts passes. Neither audit list nor src/core/reserved.ts needs to change; if one does, the route went to the wrong router.

Files: src/metrics/forge.ts (new), src/http/api.ts (the existing handler), docs/METRICS.md (new), a test such as test/metrics-route.test.ts (new). Risk: the route names every route pattern, so it stays admin-only. Keep the hour's read under 50 ms (one indexed query). If the check fails where it ran and not in the change, say so in the pull rather than reworking the change.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs