Deuda #274 Tanda A — alertas en tiempo real y datos honestos en Wireless (v1.85.9)
Resumen
Primera tanda (“Tanda A”) de la task #274, la deuda técnica anotada al cerrar la auditoría profunda del monitoraje (#261): seis fallos puntuales, verificados uno a uno contra el código antes de tocarlos. Tocan dos frentes: que las alertas y los datos en tiempo real lleguen al Observatory cuando de verdad ocurren, y que lo que se mide en Wireless (clientes, métricas disponibles) sea lo que cada equipo puede producir de verdad, ni más ni menos.
Qué corrige cada arreglo
- B1-#29 — Las alertas disparadas por el Agente (Sentinel) no sonaban en el Observatory:
evaluate_alerts_for_ingest()(la vía viva de [[feature—monitoring—alertas-via-viva-agente]], task #229) evaluaba y guardaba la alerta, pero el retorno se descartaba — nadie llamaba abroadcast_alert_sync. Solo el camino antiguo (sondeo desde el servidor,operations.py) hacía sonar la campana al momento; con Sentinel había que recargar la lista.terminal/api/sentinel_ingest.py::receive_bulk_metricsahora reenvía cada alerta disparada del lote. - B1-#2 — La suscripción del WebSocket del Observatory se congelaba en el momento de abrir la pestaña: un target nuevo o recién habilitado no recibía
metric_updatehasta reconectar a mano.syncSubscriptions()(ObservatoryWebSocket.js?v=14) manda ahora el diff subscribe/unsubscribe al abrir el socket y tras cadaloadTargets(). - B1-#15 — El mismo contador de clientes se sondeaba dos veces por punto de acceso: Cambium y Xirrus declaran el mismo OID en el bucle rápido (
fast_poll_oids.station_count) y en el bucle de extras (monitoring_oids.connected_clients/associated_clients) — dos walks SNMP del mismo árbol cada minuto.dedupe_monitoring_oids()(nueva función enterminal/services.py) quita del bucle de extras lo que el bucle rápido ya cubre, al construir la lista de objetivos que recibe el Agente (terminal/api/sentinel.py::get_agent_targets). - B1-#25 —
available-metricsprometía métricas que un AP no podía dar:station_count/throughputse anunciaban siempre, aunque el AP no tuviera target SNMP o el vendor no soportara conteo rápido de clientes — paneles condenados a “Waiting for data…”. Ahorathroughputexige un target con SNMP activo ystation_countexige además que el perfil del vendor tengafast_poll_oids. - B1-#12 — El conteo de clientes de la foto de deep discovery salía multiplicado:
_count_clients_from_deep()(la misma función que usa [[feature—wireless—clientes-vivos-ahora]] para decidir cuántos clientes tiene un AP vivo) contaba la listaclientsentrada por entrada — con 8 OIDs por cliente, salía ×8 cuando el AP no traíaclientsPerRadio. Ahora cuenta índices únicos. - B1-#27 —
deep_snmp_datase guardaba sin tope de tamaño: un AP con tablas SNMP grandes podía escribir un blob sin límite, releído después por todos los listados de la flota. Tope de 512 KB por foto (MAX_DEEP_SNMP_BYTES, ~×8 el tamaño real de una foto típica); lo que lo supera se rechaza con aviso en el log, sin tocar la ficha existente.
Implementación
terminal/api/sentinel_ingest.py— reenvío dealert_triggered(B1-#29) y topeMAX_DEEP_SNMP_BYTESenreceive_deep_discovery_result(B1-#27).terminal/services.py— nueva funcióndedupe_monitoring_oids(monitoring_oids, fast_poll_oids)(B1-#15).terminal/api/sentinel.py::get_agent_targets— llama al dedupe antes de mandar la config al Agente.monitoring/api/wireless.py—_count_clients_from_deep()cuenta por índice (B1-#12);get_available_metrics()exige productor real por métrica (B1-#25).static/js/pages/observatory/ObservatoryWebSocket.js?v=14/observatory.js—syncSubscriptions(), llamada al abrir el socket y tras cadaloadTargets()(B1-#2).
Tests
tests/monitoring/test_deuda_274_tanda_a.py (10 tests, uno por comportamiento) + frontend/src/__tests__/static/observatory_ws_subscriptions.test.js (3 tests de contrato sobre syncSubscriptions).
Límite honesto
El efecto real de “menos carga SNMP” (B1-#15) y de las métricas honestas (B1-#25) se verá con la flota del CCIB en septiembre (task #271) — hoy solo hay un AP vivo para probar contra hardware real. Sin cambio en la ayuda de usuario (ningún flujo ni pantalla nueva).
Commits relacionados
6518b2a8(2026-08-27) — fix(monitoring): deuda #274 Tanda A, PR #446, v1.85.9.
Véase también
- [[feature—monitoring—alertas-via-viva-agente]]
- [[feature—monitoring—auditoria-261-ciclo-4-cableado-observatory]]
- [[feature—wireless—clientes-vivos-ahora]]
- [[entity—monitoring—consumer—realtime-websocket]]
- [[feature—wireless—deep-discovery-timestamp]]
- [[crearack-tech—architecture—wireless-monitor]]