package metrics import ( "io" "net/http/httptest" "path/filepath" "strings" "testing" "github.com/david/knox/internal/db" "github.com/prometheus/client_golang/prometheus/testutil" ) func tmpKdb(t *testing.T) *db.KnoxDB { t.Helper() k, err := db.Open(filepath.Join(t.TempDir(), "index.db")) if err != nil { t.Fatalf("open db: %v", err) } t.Cleanup(func() { k.Close() }) return k } func seed(t *testing.T, k *db.KnoxDB, src string, n int) { t.Helper() for i := 0; i < n; i++ { _, _, err := k.RecordObservation(db.ObservationRecord{ Fingerprint: "fp-" + src + "-" + string(rune('a'+i)), SourceID: src, SourcePath: src, Project: "test", ContentType: "test", Title: src, Summary: "s", CreatedAt: "2026-08-29T00:00:00Z", Confidence: 0.9, IngesterVersion: "itest/v1", }) if err != nil { t.Fatalf("seed: %v", err) } } } func TestMetricsSnapshot(t *testing.T) { k := tmpKdb(t) seed(t, k, "git", 2) seed(t, k, "browser-history", 3) s, err := k.MetricsSnapshot() if err != nil { t.Fatalf("snapshot: %v", err) } if s.Observations != 5 { t.Errorf("observations = %d, want 5", s.Observations) } if s.BySource["git"] != 2 || s.BySource["browser-history"] != 3 { t.Errorf("by source = %v", s.BySource) } if s.KnowledgeVector[k.NodeID()] == 0 { t.Errorf("knowledge vector missing own node") } if s.ByOriginNode[k.NodeID()] != 5 { t.Errorf("by origin node = %v", s.ByOriginNode) } } func TestMetricsScrape(t *testing.T) { k := tmpKdb(t) seed(t, k, "git", 2) m := New(k, "testnode") h := m.Handler() rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest("GET", "/metrics", nil)) body, _ := io.ReadAll(rec.Body) out := string(body) for _, want := range []string{ `knox_node_info{name="testnode"`, `knox_observations_total{source_id="git"} 2`, `knox_gossip_pulls_total 0`, "go_goroutines", "process_cpu_seconds_total", } { if !strings.Contains(out, want) { t.Errorf("scrape output missing %q", want) } } } func TestMetricsCounters(t *testing.T) { k := tmpKdb(t) m := New(k, "t") // Manually drive counters through the Metrics API. m.IncrementPull(3) m.IncrementPush(7) m.IncrementErrors() if got := testutil.ToFloat64(m.pullsTotal); got != 1 { t.Errorf("pullsTotal = %v, want 1", got) } if got := testutil.ToFloat64(m.obsPulledTotal); got != 3 { t.Errorf("obsPulled = %v, want 3", got) } if got := testutil.ToFloat64(m.obsPushedTotal); got != 7 { t.Errorf("obsPushed = %v, want 7", got) } if got := testutil.ToFloat64(m.errorsTotal); got != 1 { t.Errorf("errorsTotal = %v, want 1", got) } }