Skip to content

feat(metrics): opt-in Prometheus /metrics endpoint + textfile collector - #304

Merged
ErenAri merged 1 commit into
mainfrom
feat/metrics-endpoint
Aug 11, 2026
Merged

feat(metrics): opt-in Prometheus /metrics endpoint + textfile collector#304
ErenAri merged 1 commit into
mainfrom
feat/metrics-endpoint

Conversation

@ErenAri

@ErenAri ErenAri commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Makes AegisBPF's Prometheus metrics scrape-able. The exposition already existed as the aegisbpf metrics CLI (35+ low-cardinality families read from the pinned maps) — this exposes it two ways.

1. Built-in HTTP endpoint (opt-in)

AEGIS_METRICS_ADDR=127.0.0.1:9635 aegisbpf run --enforce
curl -s http://127.0.0.1:9635/metrics
  • src/metrics_server.{hpp,cpp} — minimal HTTP/1.0 server, off unless AEGIS_METRICS_ADDR is set. Routes GET /metrics + GET /healthz. No BPF/kernel dependency (body from a callback), so it's unit-tested over a real loopback socket.
  • Reuses the daemon's already-loaded BPF state — no per-scrape reload.
  • Security: binds loopback by default; no auth (standard for a scrape target). Bind :9635 to expose and restrict with a firewall / Kubernetes NetworkPolicy.

2. node_exporter textfile collector (no open port)

  • packaging/systemd/aegisbpf-metrics.{service,timer} — a 30 s timer writes the exposition atomically (temp + rename) to ${AEGIS_METRICS_TEXTFILE} for node_exporter to serve. systemctl enable --now aegisbpf-metrics.timer.

Refactor + coverage

  • build_metrics_report(BpfState&, bool) extracted from cmd_metrics so CLI / textfile / HTTP emit identical output.
  • New aegisbpf_deny_ttl_entries gauge (control-API denies awaiting TTL expiry).
  • pin_heal_* in-process counters intentionally deferred — they're written by the heartbeat thread and would be a TSan-visible race until made atomic. Noted in docs/METRICS.md.

Tests / verification

  • tests/test_metrics_server.cpp — bind-addr parsing + loopback round-trip (/metrics, /healthz, 404, no-callback 503, non-GET 405).
  • Local: aegisbpf + aegisbpf_test build clean; MetricsServer/TtlRegistry/SocketApi = 20/20; clang-format, clang-tidy (real .clang-tidy config), and cppcheck all clean on changed files.

Docs

docs/METRICS.md (endpoint + textfile + metric table) with index link; CHANGELOG under Unreleased.

🤖 Generated with Claude Code

Copilot AI lite review requested due to automatic review settings August 11, 2026 20:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…llector

The Prometheus exposition already existed as the `aegisbpf metrics` CLI (35+
low-cardinality families read from the pinned maps). This makes it scrape-able.

- src/metrics_server.{hpp,cpp}: a minimal opt-in HTTP/1.0 server. Off unless
  AEGIS_METRICS_ADDR=<host:port>. Routes GET /metrics and GET /healthz; binds
  loopback by default (bind :9635 to expose, restrict via firewall/NetworkPolicy).
  No BPF/kernel dependency — the body comes from a callback — so it is unit-tested
  over a real loopback socket.
- src/commands_metrics.{cpp,hpp}: refactor the builder out of `cmd_metrics` into a
  shared `build_metrics_report(BpfState&, bool)` so the CLI, the textfile collector,
  and the HTTP endpoint emit identical output. Add an `aegisbpf_deny_ttl_entries`
  gauge (control-API denies awaiting TTL expiry).
- src/daemon.cpp: start the endpoint when AEGIS_METRICS_ADDR is set, reusing the
  daemon's already-loaded state (no per-scrape reload). Reads touch only pinned
  maps + files, so they run concurrently with the poll loop safely; in-process
  counters (pin_heal_*) are intentionally deferred until made scrape-safe.
- packaging/systemd/aegisbpf-metrics.{service,timer}: node_exporter textfile
  collector — the no-open-port alternative (atomic temp+rename write every 30s).
- tests/test_metrics_server.cpp: bind-addr parsing + loopback round-trip
  (/metrics, /healthz, 404, no-callback 503, non-GET 405).
- docs/METRICS.md (+ index link), CHANGELOG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ErenAri
ErenAri force-pushed the feat/metrics-endpoint branch from ac8c629 to 6a57a9d Compare August 11, 2026 20:27
@ErenAri
ErenAri merged commit c932563 into main Aug 11, 2026
53 checks passed
@ErenAri
ErenAri deleted the feat/metrics-endpoint branch August 11, 2026 21:02
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.

2 participants