Volver a la wiki

Agente · dev-observatory

Agente · dev-observatory

Propósito

Desarrollo y mantenimiento del Network Observatory de CreaRack-Pro. Cubre la app monitoring/, los submódulos JS de Observatory y la integración con VictoriaMetrics.


Módulos JS (pages/observatory/)

static/js/pages/
├── observatory.js                  # Coordinador principal (~430 líneas)
└── observatory/
    ├── ObservatoryCharts.js        # Funciones de gráficas ECharts
    ├── ObservatoryCNS.js           # Integración CNS / Edge Intelligence
    ├── ObservatoryOverview.js      # Dashboard overview + Agent Fleet widget
    ├── ObservatorySentinel.js      # Sentinel Mode UI
    ├── ObservatoryTabs.js          # Gestión de pestañas + formatRangeLabel()
    ├── ObservatoryAlerts.js        # Sistema de alertas UI
    ├── ObservatoryWebSocket.js     # WebSocket handler
    ├── ObservatorySettings.js      # Modales de configuración SNMP/HTTP
    └── PingConsole.js              # Consola de ping en tiempo real

App Django: monitoring/

monitoring/
├── models.py              # MonitoringTarget, MetricSample, AggregatedMetric,
│                          # MonitoringAlert, AlertEvent
├── api.py                 # Endpoints Django Ninja (~87 endpoints total)
├── views.py               # observatory_view (inyecta devices desde Django)
├── consumers.py           # MonitoringConsumer (WebSocket)
├── routing.py             # WebSocket routing
└── services/
    ├── ping_service.py    # PingService (icmplib)
    ├── snmp_service.py    # SNMPService — bandwidth + SNMPv3
    ├── http_service.py    # HttpService — health checks
    └── alert_service.py   # Evaluación de alertas

Modelos de datos

MonitoringTarget

Dispositivo/IP a monitorear. Contiene configuración por tipo.

ping_enabled    # Bool
snmp_enabled    # Bool
http_enabled    # Bool
config          # JSONField — credenciales SNMPv3, URL HTTP, etc.

SNMPv3 en config:

{
  "snmp_version": "v3",
  "snmp_v3_username": "...",
  "snmp_v3_auth_protocol": "SHA256",
  "snmp_v3_auth_key": "...",
  "snmp_v3_priv_protocol": "AES128",
  "snmp_v3_priv_key": "..."
}

MonitoringAlert

AlertEvent

MetricSample / AggregatedMetric


API Endpoints — Core (targets, metrics, alerts, batch)

Targets

MétodoURLDescripción
GET/POST/api/monitoring/targetsCRUD targets
PATCH/api/monitoring/targets/{id}/configActualizar solo configuración
POST/api/monitoring/devices/{id}/enable-monitoringCrear target desde device

Métricas

MétodoURLDescripción
POST/api/monitoring/targets/{id}/pingEjecutar ping
POST/api/monitoring/targets/{id}/snmp/pollPoll SNMP
POST/api/monitoring/targets/{id}/http/checkHTTP health check

Retirados en v1.68.1 (task #230): GET {id}/metrics · GET {id}/stats · GET {id}/history · GET {id}/bandwidth — leían tablas PG vacías (y /stats fabricaba un 0% falso). El histórico se sirve por GET {id}/vm/* (VictoriaMetrics). Test que lo fija: tests/monitoring/test_pg_metrics_retired.py.

Batch (concurrencia)

POST /api/monitoring/targets/batch-ping   # 20 concurrentes max
POST /api/monitoring/targets/batch-snmp   # 10 concurrentes max
POST /api/monitoring/targets/batch-http   # 15 concurrentes max

Alertas

MétodoURLDescripción
POST/api/monitoring/alerts/globalCrear alerta global (target=NULL)
GET/api/monitoring/alerts?target_id=XPer-device + globales (Q objects)
POST/api/monitoring/alerts/{id}/acknowledgeReconocer alerta
GET/api/monitoring/alerts/activeAlertas activas sin resolver

WebSocket

// Conexión
const ws = new WebSocket('ws://localhost:8000/ws/monitoring/');

// Suscribirse
{"type": "subscribe", "target_ids": [1, 2, 3]}

// Server → Client: actualización de métricas
{
    "type": "metric_update",
    "target_id": 1,
    "metrics": {"status": "up", "latency_ms": 15.2, "packet_loss": 0}
}

// Server → Client: alerta disparada
{
    "type": "alert_triggered",
    "alert_id": 5,
    "target_id": 1,
    "value": 150.5
}

Handler: ObservatoryWebSocket.js — gestiona suscripciones y despacha eventos a los módulos correspondientes.


ECharts — arquitectura centralizada

Regla fundamental: Todas las gráficas pasan por EChartsService.js. Un cambio en EChartsService afecta las 3 gráficas (Heartbeat, Bandwidth, HTTP) de todos los dispositivos.

Configuración compartida via EChartsService

QuéMétodoEfecto
Grid layoutgetBaseOptions()Márgenes idénticos (left:65, right:65, top:40, bottom:65)
TooltipgetBaseOptions()Formato es-ES, crosshair, estilo oscuro
DataZoomgetDataZoom()Slider inferior + zoom con rueda
Threshold linesgetThresholdMarkLines()Colores por severidad
Threshold areasgetThresholdMarkAreas()Zonas sombreadas de alerta

Sincronización entre gráficas

// ObservatoryCharts.js — conectar las 3 gráficas de un dispositivo
echarts.connect([heartbeatChart, bandwidthChart, httpChart]);

Sincroniza: hover/tooltip cruzado + DataZoom porcentual. NO sincroniza: escala yAxis, series data, zoom state en localStorage.

Patrón de actualización — SIEMPRE así

// Solo actualizar series — nunca tocar xAxis/yAxis
chart.setOption({ series: [{ data: newData }] });

⚠ Nunca modificar xAxis ni yAxis en funciones de update — rompe la sincronización entre gráficas.

Controles globales por dispositivo

ControlMétodoAfecta
Range (01m/1h/6h/24h)setGlobalTimeRange()Re-fetch en las 3 gráficas
Chart StyleEChartsService.setChartStyle()Estilo visual en las 3
Animation (Ani)EChartsService.toggleAnimation()Pulso visual on/off
Alert Lines (AL)EChartsService.toggleMarkLines()Threshold lines on/off
Pause/ResumeEChartsService.pauseDeviceCharts()Pausa/reanuda las 3

Colores por defecto

// Heartbeat
latency:    '#3b82f6'  // Azul
packetLoss: '#ff9800'  // Naranja

// Bandwidth
inbound:    '#4caf50'  // Verde
outbound:   '#2196f3'  // Azul
aggregate:  '#ff9800'  // Naranja (dashed, hidden by default)

// HTTP
response:   '#10b981'  // Esmeralda (visualMap: verde→amarillo→rojo)

Selector de tiempo — ciclo de clicks

BotónCiclo
01m01m → 05m → 10m → 20m
1h1h → 2h → 4h → 8h
6h6h → 12h → 24h → 48h
24h24h → 48h → 72h → 7d

formatRangeLabel() centralizado en ObservatoryTabs.js. Backend acepta hours: float en todos los endpoints.


Funcionalidades especiales

Asteroids Alert Mode

Ping Console

Alertas globales

Escrituras async a VictoriaMetrics (fire-and-forget)

Draggable sidebar


Management commands

# Ping automático continuo (cada 10s)
docker compose exec web python manage.py ping_targets --continuous --interval 10

# Limpieza de datos (>30 días samples, >90 días alertas)
docker compose exec web python manage.py cleanup_metrics

# aggregate_metrics RETIRADO en v1.68.1 (task #230): su salida (AggregatedMetric) se quedó sin lector

OIDs SNMP soportados


VictoriaMetrics — arquitectura de métricas

Stack de datos (roles complementarios)

TecnologíaRolRetenciónVelocidad
ValkeyCache, sesiones, pub/sub Django ChannelsSegundos a horasMilisegundos
VictoriaMetricsSeries temporales Observatory + infra SaaS180 días~100ms
PostgreSQLDatos de negocio (targets, alertas, config)Permanente~10-50ms

Multi-tenancy — separación por labels

# SIEMPRE incluir tenant_id en cada métrica
{
    "__name__": "ping_latency_ms",
    "tenant_id": "5",       # ← separación entre clientes
    "target_id": "123",
    "target_ip": "192.168.1.1"
}

Seguridad — filtrar SIEMPRE por tenant

# En cada endpoint de métricas — nunca omitir tenant_id
tenant_id = request.auth.user.tenant_id
query = f'ping_latency_ms{{tenant_id="{tenant_id}", target_id="{target_id}"}}'
return await MetricsReader.query_range(query, hours)

Escrituras fire-and-forget

# No bloqueante — el usuario no espera confirmación de VM
MetricsWriter._fire_and_forget()
# Contexto async (Daphne): loop.create_task()
# Contexto sync (Ninja views): threading.Thread(daemon=True)

Consultas PromQL desde Django

# Ejemplo: latencia media últimas 24h de un target
query = f'avg(ping_latency_ms{{tenant_id="{tid}", target_id="{tid}"}})[24h]'
result = await MetricsReader.query_range(query, hours=24)

Acceso a VictoriaMetrics en producción

Solo accesible desde dentro de la red Docker — no expuesto externamente:

# Consulta via contenedor Django
ssh root@crearack.com "docker exec crearack-pro-zcmvsl-web-1 python -c \
\"import urllib.request, urllib.parse, json; \
q = urllib.parse.quote('<PromQL query>'); \
r = urllib.request.urlopen(f'http://victoriametrics:8428/api/v1/query?query={q}'); \
print(json.loads(r.read()))\""

UI local (con compose.observability.yml): http://localhost:8428


API Endpoints — Modulos especializados (130+ endpoints)

Endpoints de monitoring/ no cubiertos en la seccion principal.

ITSM (/api/monitoring/sentinel/itsm/) — 26 endpoints

MetodoEndpointProposito
GET/PUT/sla/policies, /sla/policies/{risk_level}CRUD politicas SLA (HIGH/MEDIUM/LOW)
POST/sla/initializeInicializar SLA por defecto
GET/sla/metricsMetricas MTTA/MTTR (30 dias default)
GET/POST/PUT/DELETE/notifications/channels, /{id}CRUD canales notificacion
POST/notifications/channels/{id}/testEnviar notificacion test
GET/notifications/logUltimas 50 notificaciones
GET/POST/PUT/DELETE/escalation/policies, /{id}CRUD politicas escalamiento
GET/POST/PUT/DELETE/maintenance, /{id}CRUD ventanas mantenimiento
GET/maintenance/activeVentanas activas ahora
GET/analyticsDashboard analitica ITSM (30d)
POST/DELETE/links, /{id}Crear/eliminar links entre insights
GET/insights/{id}/linksLinks de un insight
GET/patternsPatrones recurrentes detectados
POST/patterns/{id}/acknowledgeMarcar patron como conocido

ITSM Extendido — 16 endpoints

MetodoEndpointProposito
GET/sentinel/itsm/groupsListar grupos de incidentes
GET/sentinel/itsm/groups/{id}Detalle grupo
POST/sentinel/itsm/groups/{id}/resolveResolver grupo
POST/sentinel/itsm/groups/{id}/acknowledge-allReconocer todos los insights
GET/POST/PUT/DELETE/sentinel/itsm/known-issuesCRUD known issues
POST/sentinel/itsm/known-issues/from-insight/{id}Crear known issue desde insight
GET/POST/PUT/DELETE/sentinel/itsm/runbooksCRUD runbooks
POST/sentinel/itsm/runbooks/{id}/apply/{insight_id}Aplicar runbook a insight
GET/sentinel/itsm/reports/{id}Informe JSON de un insight
GET/sentinel/itsm/reports/{id}/markdownInforme Markdown descargable

CNS Insights (/api/monitoring/sentinel/insights/) — 15 endpoints

MetodoEndpointProposito
POST/receiveRecibir anomalia del Agent → generar insight (JWT)
GET/Listar insights (filtros: status, risk, target, search, fechas)
GET/stats/Estadisticas por estado
GET/stats/providers/Uso por proveedor IA
GET/{id}/Detalle insight
POST/{id}/acknowledgeReconocer con notas opcionales
POST/{id}/explainPregunta contextual sobre insight (async)
POST/recover/{target_id}Target recuperado → auto-resolver (JWT)
DELETE/purgeEliminar TODOS los insights (superuser)
GET/{id}/conversationsHistorial Q&A del insight
POST/{id}/reviseRe-evaluar diagnostico con historial
POST/{id}/applyAplicar comandos via Agent
POST/{id}/dry-runValidar sin ejecutar
POST/{id}/rollbackRollback de insight aplicado
POST/{id}/resultRecibir resultado de ejecucion (JWT)

Wireless Monitor (/api/monitoring/wireless/) — 18 endpoints

MetodoEndpointProposito
GET/summaryStats agregados WiFi (online, offline, clients)
GET/status-listEstado por AP + clientes (real-time)
GET/deep-dataDatos SNMP deep de APs
POST/trigger-deep-discoverDisparar deep discovery APs
GET/deep-discover-statusProgreso del job
GET/available-metrics/{profile_id}Metricas disponibles para AP
GET/dashboard-chartsSeries temporales agregadas
GET/dashboard-rankingsTop-5 peor latencia/packet loss
GET/POST/DELETE/dashboard-layoutCRUD layout dashboard
GET/PUT/dashboard-notesCRUD notas dashboard
GET/report/{profile_id}Informe AP individual
GET/fleet-reportInforme flota completa
GET/group-summary/{group_id}Stats por grupo wireless
GET/group-metric/{group_id}Series temporales por grupo
PUT/group-assignAsignar APs a grupo

UPS Monitor (/api/monitoring/ups/) — 18 endpoints

Estructura identica a Wireless Monitor. Sustituir “AP” por “UPS”, metricas de carga/bateria.

MetodoEndpointProposito
GET/summaryStats agregados UPS (charge, load, critical)
GET/status-listEstado por UPS (real-time)
GET/POST/deep-data, /trigger-deep-discoverDeep discovery UPS
GET/dashboard-charts, /dashboard-rankingsGraficas + top-5
GET/POST/DELETE/dashboard-layoutLayout persistido
GET/PUT/dashboard-notesNotas persistidas
GET/report/{profile_id}, /fleet-reportInformes individual/flota
GET/group-summary/{id}, /group-metric/{id}Stats/series por grupo
PUT/group-assignAsignar UPS a grupo

Signage Monitor (/api/monitoring/signage/) — 23 endpoints

Misma estructura que Wireless/UPS + endpoints de deploy y operaciones.

Endpoints base (18): summary, status-list, deep-data, trigger-deep-discover, charts, rankings, layout, notes, reports, groups (identicos a Wireless).

Endpoints adicionales:

MetodoEndpointProposito
POST/deploy-contentDeploy media a dispositivo via Agent WebDAV
GET/media-download/{asset_id}Servir media para descarga Agent
POST/publish-setupCrear/obtener SignagePlayer + URL publish
GET/operationsListar operaciones recientes
POST/operations/{id}/restoreRestaurar player a estado anterior

Observatory Layout y Sentinel Config — 9 endpoints

MetodoEndpointProposito
GET/POST/DELETE/overview-layoutLayout persistido del overview
GET/PUT/overview-notesQuick notes
GET/PUT/chart-defaultsDefaults de graficas
GET/PUT/sentinel-configConfiguracion Sentinel Mode

Network Tutor (/api/monitoring/sentinel/tutor/) — 3 endpoints

MetodoEndpointProposito
POST/askPregunta de networking al tutor IA (async)
GET/historyHistorial de conversacion
POST/clearLimpiar historial

Convenciones y restricciones

Véase también

Subir