82f1f1bd58
Función del grupo fleet-metrics que convierte la respuesta JSON del endpoint /healthz de un nodo unibus (membershipd) en series Prometheus (unibus_up, unibus_status_ok, unibus_posture_enforce/acl/tls/cluster, unibus_store_kv) con labels node/instance. Pura de transformación (impure solo por el error de unmarshal). La consume el daemon unibus_exporter del project fleet_monitoring. Con tests golden/edge/error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68 lines
2.3 KiB
Go
68 lines
2.3 KiB
Go
package infra
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// unibusHealth refleja la respuesta JSON del endpoint /healthz de un nodo del
|
|
// cluster de mensajería unibus (membershipd). Forma verificada en producción:
|
|
//
|
|
// {"posture":{"enforce":true,"acl":true,"tls":true,"cluster":true,"store":"kv"},"status":"ok"}
|
|
type unibusHealth struct {
|
|
Status string `json:"status"`
|
|
Posture struct {
|
|
Enforce bool `json:"enforce"`
|
|
ACL bool `json:"acl"`
|
|
TLS bool `json:"tls"`
|
|
Cluster bool `json:"cluster"`
|
|
Store string `json:"store"`
|
|
} `json:"posture"`
|
|
}
|
|
|
|
// ParseUnibusHealth convierte la respuesta JSON del endpoint /healthz de un nodo
|
|
// del cluster de mensajería unibus en una serie de PromSample lista para empujar
|
|
// a VictoriaMetrics, sin instrumentar el bus (solo lee su endpoint de salud).
|
|
//
|
|
// node es el nombre lógico del nodo (p.ej. "magnus"); se adjunta a cada serie
|
|
// como las labels "node" e "instance" para distinguir los nodos cuando un único
|
|
// exporter scrapea varios. La función SOLO debe llamarse cuando el nodo
|
|
// respondió: el caso "no responde" (unibus_up=0) lo emite el llamador, no esta
|
|
// función, porque sin cuerpo no hay nada que parsear.
|
|
//
|
|
// Devuelve siete series por nodo:
|
|
// - unibus_up = 1 (si el body parseó, el nodo respondió)
|
|
// - unibus_status_ok = 1 si status=="ok", si no 0
|
|
// - unibus_posture_enforce / _acl / _tls / _cluster = 1/0 según el booleano
|
|
// - unibus_store_kv = 1 si posture.store=="kv", si no 0
|
|
//
|
|
// Si el body no es JSON válido con la forma esperada, devuelve (nil, error).
|
|
func ParseUnibusHealth(node string, body []byte) ([]PromSample, error) {
|
|
var h unibusHealth
|
|
if err := json.Unmarshal(body, &h); err != nil {
|
|
return nil, fmt.Errorf("parse unibus healthz for node %q: %w", node, err)
|
|
}
|
|
b2f := func(b bool) float64 {
|
|
if b {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
mk := func(name string, v float64) PromSample {
|
|
return PromSample{
|
|
Name: name,
|
|
Labels: map[string]string{"node": node, "instance": node},
|
|
Value: v,
|
|
}
|
|
}
|
|
return []PromSample{
|
|
mk("unibus_up", 1),
|
|
mk("unibus_status_ok", b2f(h.Status == "ok")),
|
|
mk("unibus_posture_enforce", b2f(h.Posture.Enforce)),
|
|
mk("unibus_posture_acl", b2f(h.Posture.ACL)),
|
|
mk("unibus_posture_tls", b2f(h.Posture.TLS)),
|
|
mk("unibus_posture_cluster", b2f(h.Posture.Cluster)),
|
|
mk("unibus_store_kv", b2f(h.Posture.Store == "kv")),
|
|
}, nil
|
|
}
|