Skip to content

fix(alertas): la saturación se mide contra la capacidad contratada, no contra el puerto

Rafael Bautista requested to merge ti into qa

_RULE_EXPR dividía el pico entre velocidad_puerto_bps, que NO es la capacidad contratada: es la velocidad del puerto físico, 1 Gbps en los 22 enlaces por igual. routers/ti.py::_ab_catalogo ya lo documentaba y por eso el dashboard divide entre el catálogo de /admin; el motor de alertas se había quedado con el otro denominador, así que la gráfica y la alarma medían cosas distintas — justo lo que kpi_indicadores existe para impedir.

El efecto no era un desvío pequeño. Medido contra el datalake real:

enlace   capacidad   pico      dashboard   alarma (antes)
port5    100 Mbps    220 Mbps  220%        22%
port6    200 Mbps    220 Mbps  110%        22%
port3     50 Mbps     52 Mbps  104%        5.2%

Con ti_ancho_banda_util_rojo = 80 la alarma habría necesitado 800 Mbps sobre un puerto de 1 G: no podía dispararse nunca. Los tres umbrales daban 0 de 7,794 filas y el 0 parecía una buena noticia. Ahora: 414 día-enlace sobre el rojo, 557 sobre el amarillo y 231 rebasando el 100%.

Casar la capacidad obliga a slugificar del lado del SQL: las claves de /admin están slugificadas (..._cap_vlan_40_ti) y el datalake guarda el id crudo del enlace ("VLAN 40 TI"). 17 de los 22 no coinciden. El CASE se arma con parámetros ligados, nunca interpolando números.

Un enlace sin capacidad capturada da NULL, no un default: la fila no entra en el conteo, igual que el dashboard lo deja sin semáforo en vez de suponerle una. Si NO hay ninguna capacidad configurada se levanta ValueError y la regla se salta — se prefiere no evaluar a inventar un denominador.

Contrastado enlace por enlace contra _ab_catalogo: 0 discrepancias en los 22. Regresión: los 7 indicadores de ti_licencias generan SQL idéntico al anterior, sin que se les cuele ningún parámetro de capacidad.

De paso, las etiquetas de /admin dejaban de decir la verdad: la columna velocidad_puerto_bps se rotulaba "Velocidad contratada (bps)", que es exactamente cómo se llegó a este bug.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Claude-Session: https://claude.ai/code/session_0116hwhMUGwq5tsrsNxMYoZm

Merge request reports

Loading