Files
unibus_exporter/app.md
T
egutierrez 92da0c0b0a feat: unibus_exporter — daemon que sondea /healthz del cluster unibus y empuja estado+posture a VictoriaMetrics
Compone parse_unibus_health + format_prom_exposition + push_prom_remote del registry
(grupo fleet-metrics). Un solo exporter scrapea los 3 nodos por IP pública con la CA
del cluster; labels node/instance por serie. Config JSON con secretos fuera de argv.
Incluye systemd unit y unibus.example.json.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 20:23:21 +02:00

5.7 KiB

name, lang, domain, version, description, tags, uses_functions, uses_types, framework, entry_point, dir_path, repo_url
name lang domain version description tags uses_functions uses_types framework entry_point dir_path repo_url
unibus_exporter go infra 0.1.0 Exporter del cluster de mensajería unibus: sondea el /healthz de cada nodo por TLS (CA del cluster) en un bucle y empuja a VictoriaMetrics métricas de estado del cluster y posture (up/down, enforce/acl/tls/cluster, store-kv, cluster_size) sin instrumentar el bus.
fleet-metrics
unibus
monitoring
daemon
parse_unibus_health_go_infra
format_prom_exposition_go_infra
push_prom_remote_go_infra
PromSample_go_infra
main.go projects/fleet_monitoring/apps/unibus_exporter https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/dataforge/unibus_exporter

unibus_exporter

Daemon que monitoriza el cluster de mensajería unibus (NATS + JetStream, desplegado como 3 nodos: magnus, homer, datardos) y lo hace visible en Grafana junto al resto de la flota. Es parte del project fleet_monitoring.

No instrumenta el bus: solo lee el endpoint público de salud de cada nodo (GET https://<nodo>:8470/healthz, verificado con la CA del cluster) y traduce su respuesta a métricas Prometheus que empuja a VictoriaMetrics. Así un único exporter (corriendo en magnus, que alcanza los 3 nodos por IP pública) cubre todo el cluster sin tocar la configuración de los nodos.

Qué hace

Compone tres funciones del registry (grupo fleet-metrics), no reimplementa nada:

  1. parse_unibus_health_go_infra — convierte el JSON de /healthz de un nodo en []PromSample con labels node/instance.
  2. format_prom_exposition_go_infra — serializa los samples a texto formato Prometheus exposition.
  3. push_prom_remote_go_infra — hace POST del texto a VictoriaMetrics, añadiendo la label común job=unibus_exporter vía extra_label.

Como un solo exporter scrapea varios nodos, las labels node e instance se fijan por serie (en el parser) y no vía extra_label, que aplicaría un único valor a todo el lote.

Métricas que produce

Serie Labels Significado
unibus_up node, instance 1 si el nodo respondió /healthz, 0 si falló el GET/parseo
unibus_status_ok node, instance 1 si status=="ok"
unibus_posture_enforce node, instance posture: enforcement de auth (1/0)
unibus_posture_acl node, instance posture: ACL de subjects (1/0)
unibus_posture_tls node, instance posture: TLS del transporte (1/0)
unibus_posture_cluster node, instance posture: modo cluster activo (1/0)
unibus_store_kv node, instance 1 si el backend de store es kv (JetStream KV)
unibus_scrape_error node, instance 1 si el scrape de ese nodo falló
unibus_scrape_duration_seconds node, instance latencia del GET /healthz
unibus_cluster_size (global) número de nodos configurados (los vivos = sum(unibus_up))

Por qué no lleva el tag service

Es un daemon, pero igual que metrics_agent su liveness no se vigila con un health check propio por SSH (modelo service:/services_monitor): si el exporter cae, las series unibus_* se vuelven stale y eso es la señal. Por eso se etiqueta daemon.

Configuración

Config por archivo JSON (-config). Campos en unibus.example.json:

campo descripción default
nodes[] lista de {name, url} por nodo (url = /healthz completo) — (obligatorio)
ca_cert_path PEM de la CA del cluster unibus, para verificar el TLS de cada nodo — (obligatorio)
hub_url endpoint de ingesta de VictoriaMetrics (…/api/v1/import/prometheus) — (obligatorio)
user / pass basic-auth del hub (vacío si el hub es local sin auth) ""
interval_sec periodo de scrape+push en segundos 15
timeout_sec timeout del GET /healthz por nodo 8
labels labels comunes añadidas vía extra_label {"job":"unibus_exporter"}

Overrides por entorno: UNIBUS_HUB_URL, UNIBUS_USER, UNIBUS_PASS, UNIBUS_CA_CERT, UNIBUS_INTERVAL. Los secretos viven solo en el archivo de config (chmod 600), nunca en argv.

Ejemplo

cd projects/fleet_monitoring/apps/unibus_exporter
go build -o unibus_exporter .

# Scrape+push único de prueba (lee config y sale)
./unibus_exporter -config /etc/unibus-exporter/unibus.json -once

# Bucle continuo (lo que hace el servicio systemd)
./unibus_exporter -config /etc/unibus-exporter/unibus.json

Cuando usarla

Despliégalo en una máquina que alcance los 3 nodos del cluster (hoy magnus, por IP pública). No hay que tocar los nodos de unibus: el exporter solo lee su /healthz. El dashboard hub/dashboards/unibus-cluster.json visualiza estas series.

Deploy

Desde la raíz del project: ./hub/deploy_unibus_exporter.sh magnus om. Compila el binario, sube binario + CA del cluster a /opt/unibus-exporter + /etc/unibus-exporter, escribe la config con el endpoint local de VM (http://127.0.0.1:8428/..., sin auth porque corre en el hub) e instala el servicio systemd.

Gotchas

  • La CA del cluster es secreta (gitignored): no se versiona en el repo. El deploy la sube al nodo a /etc/unibus-exporter/ca.crt (chmod 600). Localmente vive en projects/message_bus/apps/unibus/deploy/tls/ca.crt.
  • El TLS se verifica siempre contra esa CA: una CA equivocada o ausente hace fallar el arranque, no se ignora.
  • unibus_up=0 lo emite este exporter (no el parser) cuando el GET falla, para que un nodo caído sea visible en Grafana en vez de simplemente desaparecer.
  • Métricas profundas de NATS/JetStream (msgs/s, conexiones, RAFT leader por stream, NRestarts) NO las produce: requieren el monitoring embebido de NATS (puerto 8222), hoy cerrado en producción. Ver el report unibus-grafana-monitoring para el detalle del gap.