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:
+16
-2
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/david/knox/internal/db"
|
||||
"github.com/david/knox/internal/ingest"
|
||||
"github.com/david/knox/internal/metrics"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
@@ -24,6 +25,7 @@ type Watcher struct {
|
||||
vault string
|
||||
debounce time.Duration
|
||||
fileIngesters []ingest.Ingester
|
||||
metrics *metrics.Metrics
|
||||
}
|
||||
|
||||
func New(kdb *db.KnoxDB, dirs []string) *Watcher {
|
||||
@@ -40,6 +42,7 @@ func New(kdb *db.KnoxDB, dirs []string) *Watcher {
|
||||
ingest.NewLogIngester(),
|
||||
ingest.NewSkillsIngester(),
|
||||
},
|
||||
metrics: metrics.New(kdb, "knox"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +56,7 @@ func (w *Watcher) Start() error {
|
||||
// Start the gossip server first so peers can reach us while the initial
|
||||
// seed is still ingesting. Vault/dirs are logged after the seed below.
|
||||
gossipAddr := ListenAddr()
|
||||
node := &Node{Kdb: w.knoxDB, Name: "knox", Addr: gossipAddr}
|
||||
node := &Node{Kdb: w.knoxDB, Name: "knox", Addr: gossipAddr, Metrics: w.metrics}
|
||||
srv := &http.Server{Addr: gossipAddr, Handler: node.Handler()}
|
||||
go func() {
|
||||
log.Printf("[knox] gossip listening on %s", gossipAddr)
|
||||
@@ -61,6 +64,17 @@ func (w *Watcher) Start() error {
|
||||
log.Printf("[knox] gossip server: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Prometheus scraping on a dedicated port (KNOX_METRICS_ADDR).
|
||||
metricsAddr := MetricsAddr()
|
||||
metricsSrv := &http.Server{Addr: metricsAddr, Handler: node.Metrics.Handler()}
|
||||
go func() {
|
||||
log.Printf("[knox] metrics listening on %s", metricsAddr)
|
||||
if err := metricsSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Printf("[knox] metrics server: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
if peers := PeerAddrs(); len(peers) > 0 {
|
||||
log.Printf("[knox] gossip peers: %v", peers)
|
||||
}
|
||||
@@ -447,7 +461,7 @@ func (w *Watcher) syncGossip() {
|
||||
before = n
|
||||
}
|
||||
|
||||
Run(w.knoxDB, peers)
|
||||
Run(w.knoxDB, w.metrics, peers)
|
||||
|
||||
// If new observations arrived, reconcile to pick up entries/threads they
|
||||
// imply (deterministic log → derived rebuild).
|
||||
|
||||
Reference in New Issue
Block a user