Skip to content

feature(metrics): expose a Prometheus /metrics endpoint#251

Open
nghiadaulau wants to merge 1 commit into
VersusControl:mainfrom
nghiadaulau:feat/metrics-endpoint
Open

feature(metrics): expose a Prometheus /metrics endpoint#251
nghiadaulau wants to merge 1 commit into
VersusControl:mainfrom
nghiadaulau:feat/metrics-endpoint

Conversation

@nghiadaulau

Copy link
Copy Markdown
Member

Summary

Versus had no self-observability — nothing to scrape for dashboards or for
alerting on the alerter itself. This adds a Prometheus GET /metrics
endpoint.

Design

  • pkg/metrics is a leaf package — it imports only
    client_golang, never any versus package — so any subsystem can record a
    metric without creating an import cycle. It owns a private registry (not
    the global default, for predictable tests), the exposition Handler(),
    and the exported collectors. Go runtime + process collectors are
    registered for free.
  • GET /metrics is registered in routes.go (before the SPA fallback,
    which now defers the path) and is unauthenticated like /healthz
    exposition data only, no secrets, so a cluster scraper needs no gateway
    secret. Served through fiber's net/http adaptor.

Metrics

Metric Type Labels Source
versus_incidents_total counter status (sent/partial/failed) incremented by the incident service after fan-out (even when storage is disabled)
versus_agent_patterns gauge GaugeFunc over Catalog.Len(), wired at agent startup (present only when the agent is enabled)
go_*, process_* standard client_golang collectors

This is the first metrics surface; further series (source lag, LLM tokens
by task, emissions by verdict) can be layered on incrementally since the
package and endpoint now exist.

New dependency

github.com/prometheus/client_golang — the de-facto standard Prometheus
client for Go. Justified per CONTRIBUTING's "justify new modules".

Testing

  • pkg/metrics httptest over Handler(): asserts the exposition serves
    versus_incidents_total, the patterns gauge, and Go runtime metrics.
  • Live: built the binary, hit /metrics (HTTP 200, go_goroutines
    present, versus_incidents_total absent until first incident), POSTed an
    incident, re-scraped → versus_incidents_total{status="sent"} 1.
  • gofmt, go vet, go build ./..., go test -race ./pkg/... green
    (one unrelated pre-existing failure: TestGitChangeFeed_RealRepo_Eino
    clones a remote repo and fails offline).

Checklist

  • httptest + live binary verification
  • Unauthenticated, documented (src/configuration/configuration.md)
  • New dependency justified
  • House conventions (feature: prefix); CHANGELOG updated

Versus had zero self-observability — nothing to scrape for dashboards or
alerting on the alerter itself. Add a Prometheus endpoint.

- pkg/metrics: a leaf package (imports only client_golang, never a versus
  package) holding a private registry, the exposition Handler, and exported
  collectors so any subsystem can record a metric without an import cycle.
  Registers the Go runtime + process collectors for free.
- GET /metrics, registered in routes.go before the SPA fallback and
  unauthenticated like /healthz (exposition data only — no secrets, so a
  cluster scraper needs no gateway secret). Served via the fiber net/http
  adaptor; the SPA fallback defers the path.
- versus_incidents_total{status} incremented by the incident service after
  fan-out (sent / partial / failed), counted even when storage is disabled.
- versus_agent_patterns gauge wired at agent startup via a GaugeFunc over
  Catalog.Len().

New dependency: github.com/prometheus/client_golang — the de-facto standard
Prometheus client.

Tests: httptest over Handler() asserts the exposition serves
versus_incidents_total, the patterns gauge, and Go runtime metrics.
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