Volver a la wiki

Deduplicación de episodios de Sentinel — un insight por avería (v1.66.15)

Resumen

Hasta la v1.66.15, cada equipo caído generaba un nuevo insight cada pocas horas mientras durase la avería — el mismo diagnóstico repetido ~14 veces al día, acumulando ~220 insights diarios que nadie podía atender y que caducaban solos sin cierre real. Desde esa versión, una avería es UN único insight que permanece abierto mientras el problema persista: los reportes repetidos del Agente lo mantienen vivo renovando su caducidad, y cuando el equipo se recupera, la auto-resolución lo cierra automáticamente. Desde la v1.87.2, esa caducidad ya no es fija: depende de la categoría del insight (ver más abajo).


Problema anterior

En PROD (medición 30 días previa a v1.66.15):

Raíz: create_insight no validaba si ya existía un insight abierto del mismo equipo y causa. El insight expiraba a las 4h; el siguiente sondeo del Agente encontraba el equipo aún caído y creaba un clon.


Solución (v1.66.15)

Cambio en create_insight

Antes de crear un nuevo insight, ahora se ejecuta una búsqueda:

open_episode = (
    await AIInsight.objects.filter(
        target=target,
        anomaly_trigger=anomaly_description,
        status=AIInsight.Status.PENDING,
    )
    .order_by("-created_at")
    .afirst()
)

Si existe un insight PENDING del mismo equipo + trigger:

  1. Se renueva su caducidad (expires_at += episode_ttl(), ver v1.87.2 abajo) en lugar de crear un clon.
  2. Se registra en AIInsightAuditLog con acción episode_refreshed y detalles reason: "duplicate_anomaly_report".
  3. Se lanza ValueError("suppressed: open episode refreshed"), que la API traduce a HTTP 429 — contrato existente que la flota (Local Agent) trata como benigno.
  4. Se ahorra la llamada de IA (costo + latencia).

Ciclo de vida del episodio:


Actualización v1.87.2 — TTL de conectividad a 48h (task #239, opción A)

La apuesta #11 (medición 21-08-2026) confirmó que el dedup por episodio bajaba el caudal, pero destapó un patrón nuevo: un equipo caído reporta cada 5-25 horas, y con la caducidad fija de 4h el episodio expiraba entre reportes — el siguiente sondeo abría OTRO insight. El 78% del caudal restante (429 de 551 en 7 días) eran re-aperturas del mismo (equipo + causa), no averías nuevas.

Fix: AIInsight.episode_ttl() (monitoring/models_insight.py) sustituye el timedelta(hours=4) hardcodeado por un cálculo según categoría:

EPISODE_TTL_HOURS = 4
CONNECTIVITY_EPISODE_TTL_HOURS = 48

def episode_ttl(self) -> "timezone.timedelta":
    hours = (
        self.CONNECTIVITY_EPISODE_TTL_HOURS
        if self.category == self.Category.CONNECTIVITY
        else self.EPISODE_TTL_HOURS
    )
    return timezone.timedelta(hours=hours)

Se usa tanto en AIInsight.save() (al crear) como en create_insight() (al renovar un episodio abierto) — antes ambos sitios tenían la misma constante duplicada. El cierre normal de una avería de conectividad sigue siendo la recuperación (auto_resolve_connectivity_insights, sin cambios en este commit): la caducidad de 48h es solo red de seguridad para equipos que el Agente deja de reportar del todo. El resto de categorías (security, performance, other) sigue en 4h.

Límite honesto (del propio CHANGELOG): la task sugería medir esto DESPUÉS de la iniciativa “Dos casas” (#235) sobre un escenario más limpio; se aplicó antes por decisión de Edu.


Impacto de usuario

✅ Pestaña de insights: ahora muestra solo un item por avería activa, no 14 duplicados ✅ Métricas ITSM: MTTR ahora mide la duración real de la avería, no el tiempo de creación del insight ✅ Performance: reducción esperada del caudal de 220 insights/día a ≤20 insights/día (v1.66.15); desde v1.87.2, sin re-aperturas de equipos caídos con reportes espaciados 5-25h ✅ Sin cambio de UI: la ayuda de CNS Sentinel no cambia (menos duplicados, mismo comportamiento documentado)


Validación

tests/api/test_insight_episode_dedup.py:

Todos usan async + django_db(transaction=True) para validar contra el ORM asíncrono.


Apuesta en WAGERS

Preregistrada como apuesta #11 en el libro de decisiones:

MétricaTargetFecha de evaluaciónResultado
Caudal diario de insights de Sentinel≤ 20/día2026-08-21Parcial: el caudal bajó, pero el 78% de lo restante eran re-aperturas de equipos caídos con reportes espaciados (patrón no contemplado en la apuesta original) — fix en v1.87.2 (task #239)

La medición previa a v1.66.15 fue ~223/día.


Notas de implementación


Véase también

Subir