feat: Prometheus metrics endpoint for knox nodes

Refs #2

- /metrics served on a dedicated port (KNOX_METRICS_ADDR, default
  localhost:8932) via prometheus/client_golang, with Go runtime +
  process collectors
- DB-derived gauges refreshed per scrape: observations by source,
  last-24h observations, entries, projects, sessions, pending
  reflections, threads by status, peers, observations by origin node,
  knowledge vector (max hcl per node)
- live gossip counters (pulls/pushes, observations pulled/pushed,
  errors) incremented during the anti-entropy sweep; Run accepts an
  optional metrics handle (nil for one-shot CLI)
- knox_node_info{node_id,name} for scrape identification
- internal/metrics package + db MetricsSnapshot; tests for snapshot,
  scrape output, and counter increments
This commit is contained in:
2026-08-29 06:06:49 -07:00
parent 25a7112d8a
commit 876d2aa45f
10 changed files with 494 additions and 20 deletions
+6 -6
View File
@@ -60,8 +60,8 @@ func TestGossipConvergence(t *testing.T) {
defer sb.Close()
// A pulls from B, then B pulls from A (bidirectional sweep).
Run(a, []string{sb.URL})
Run(b, []string{sa.URL})
Run(a, nil, []string{sb.URL})
Run(b, nil, []string{sa.URL})
av, err := a.KnowledgeVector()
if err != nil {
@@ -107,11 +107,11 @@ func TestGossipSwarmDiscovery(t *testing.T) {
defer sc.Close()
// A discovers B (A pings B) so A can advertise B to the swarm.
Run(a, []string{sb.URL})
Run(a, nil, []string{sb.URL})
// C only knows A. A single sweep should surface B (membership in ping)
// and pull B's observations directly.
Run(c, []string{sa.URL})
Run(c, nil, []string{sa.URL})
// C must know B and hold all three origin logs.
peers, err := c.ListPeers()
@@ -227,12 +227,12 @@ func TestGossipIdempotent(t *testing.T) {
sb := httptest.NewServer(nodeB.Handler())
defer sb.Close()
Run(b, []string{sa.URL})
Run(b, nil, []string{sa.URL})
before, err := b.EntryCount()
if err != nil {
t.Fatal(err)
}
Run(b, []string{sa.URL})
Run(b, nil, []string{sa.URL})
after, err := b.EntryCount()
if err != nil {
t.Fatal(err)