How muminur/grafana-loki-netwatch-monitoring-notification-by-mumin works
1. Purpose and deployment model
NetWatch is a Python 3.11+ FastAPI application that sits inside a NOC workflow, not as a generic web app. Its job is to ingest network syslog events, turn them into actionable incidents, notify operators, and present the live state in a dashboard. It is designed to run either directly on a workstation/server or in Docker Compose, with SQLite as the durable store.
2. Primary event ingestion path
The main data flow is: Syslog → Grafana Loki → Grafana datasource proxy → NetWatch. NetWatch does not connect to Loki directly; it reads via Grafana’s proxy and can also receive UDP syslog. The receiver layer in src/core/syslog_receiver.py is responsible for fetching or consuming log lines and handing them into the processing pipeline.
3. Log processing pipeline
The core pipeline is split into clear stages:
- parser.py normalizes several IOS-XR syslog formats
- classifier.py maps parsed events to severity/mnemonic rules
- enricher.py adds device, interface, client, and AS context from static lookup data and cached external lookups
- correlator.py groups related events into incidents
- dedup.py suppresses repeated noise within time windows
This pipeline is the central architecture boundary: raw syslog becomes enriched, correlated incident records.
4. Correlation and incident model
Correlation is topology-aware rather than purely message-based. The system uses src/data/topology.py plus bundle/BGP mapping data to distinguish a true backhaul failure from unrelated alerts on the same device. The result is an incident layer that can contain root causes and symptoms, supports multiple concurrent incidents per device, and auto-resolves when recovery events arrive.
5. Persistence boundary: SQLite
src/database/ is the durable state boundary. SQLite in WAL mode stores alerts, incidents, acknowledgements, notification tracking, maintenance windows, settings, and statistics aggregates. The database is also the source of truth for restart recovery: active incidents, escalation state, shift handoff notes, and user acknowledgements are reconstructed from persisted rows.
6. Notification subsystem
src/notifications/ fans out significant events to external channels. Discord and Telegram are separate delivery adapters with shared formatting and escalation logic. Notifications are not just fire-and-forget: delivery status, retries, escalation after 15 minutes, and resolution messages are all tracked as part of the incident lifecycle.
7. API surface
src/api/routes.py exposes the operational REST endpoints: alerts, incidents, shift handoffs, statistics, topology, devices, settings, maintenance, and CSV export. src/api/websocket.py provides live browser push. The API is the boundary between the backend event engine and the operator-facing UI, and it also carries auth/rate-limiting rules when strict mode is enabled.
8. Web dashboard frontend
src/web/ is server-rendered Jinja2 pages plus static JavaScript/CSS. The frontend is not a separate SPA; it consumes the FastAPI endpoints and WebSocket stream. The JS modules handle chart rendering, topology interaction, sound alerts, shortcuts, and reconnecting live updates. The UI is purpose-built for NOC wall display, with live incident cards, severity tabs, and topology visualization.
9. Statistics and reporting
src/statistics/ is a separate analytical subsystem from the live alert stream. It computes hourly aggregation, health scoring, SLA-style metrics, and prefix exhaustion predictions. These calculations read from the persisted alert/incident history and are exposed through the API for the Statistics page and CSV export workflows.
10. Static reference data and enrichment tables
src/data/ contains the operational mapping layer that makes the system useful: device maps, interface descriptions, AS number references, topology, classification rules, and BGP bundle mappings. This is a significant architectural boundary because much of NetWatch’s value comes from converting generic log text into site- and link-specific operational context.
11. Operational concerns and safeguards
The repo includes rate limiting, optional API key auth, health and metrics endpoints, maintenance suppression, dedup windows, and self-monitoring of data freshness. These are not peripheral features; they are part of the runtime control plane that keeps the alerting pipeline reliable under load and during partial outages.
12. Infrastructure and release flow
The project is packaged for Docker with a persistent data volume and hardened runtime settings, and it also has install/restart scripts for Windows, macOS, and Linux. GitHub Actions runs CI across OS/Python combinations, and a deploy workflow pushes main to an Ubuntu server over SSH, rebuilds the container, and verifies /health. This makes deployment an explicit part of the architecture rather than an afterthought.
13. How to draw the system
A good architecture diagram should show four main zones:
- External sources: routers/syslog, Grafana/Loki, Discord, Telegram
- NetWatch backend: ingestion pipeline, correlation/dedup, notifications, statistics, API/WebSocket
- Persistence: SQLite and cached reference data
- Operator surface: dashboard, settings, incident handling, shift handoff
The most important arrows are the event pipeline into the backend, the write path into SQLite, and the live push path back to the browser and notification channels.
Main entry points: routes.py REST API · correlator.py Correlator · main.py App bootstrap · enricher.py Enricher
Components 26
External sources
Upstream event sources and outbound notification channels.
- Routers · Network devices emitting IOS-XR syslog events.
- Grafana/Loki · NetWatch reads syslog through Grafana's datasource proxy and can also receive UDP syslog.
- Discord · Outbound incident and escalation notifications.
- Telegram · Outbound incident and escalation notifications.
NetWatch backend
Ingestion, correlation, notification, statistics, and API runtime.
- App bootstrap · Application startup, lifespan, and wiring for the runtime.
src/main.py - Syslog receiver · Consumes syslog lines or fetches them from Grafana and feeds the pipeline.
src/core/syslog_receiver.py - Parser · Normalizes IOS-XR syslog formats into structured events.
src/core/parser.py - Classifier · Maps parsed events to severity and mnemonic rules.
src/core/classifier.py - Enricher · Adds device, interface, client, and AS context from reference data and caches.
src/core/enricher.py - Correlator · Groups related events into topology-aware incidents and resolves them on recovery.
src/core/correlator.py - Dedup · Suppresses repeated alerts within configurable time windows.
src/core/dedup.py - Notifier · Formats incidents and drives escalation and channel fan-out.
src/notifications/escalation.py - Stats engine · Builds hourly aggregates, health scores, SLA metrics, and predictions.
src/statistics/engine.py - REST API · Alerts, incidents, handoff, statistics, topology, settings, maintenance, and export endpoints.
src/api/routes.py - WebSocket · Pushes live incident state to the browser.
src/api/websocket.py - Auth · Optional API key auth and strict-mode protections.
src/auth.py - Rate limit · Request throttling and runtime safeguards.
src/rate_limit.py
Persistence
SQLite state and cached reference data used across restarts.
- DB models · Persistent incidents, alerts, acknowledgements, maintenance, settings, and metrics state.
src/database/models.py - DB CRUD · Write/read boundary for operational state and restart recovery.
src/database/crud.py - AS cache · Cached external AS lookups supporting enrichment and topology context.
src/database/as_cache.py - Topology data · Device and link topology used to distinguish root causes from symptoms.
src/data/topology.py - Device maps · Device, interface, and classification reference tables.
src/data/device_map.py
Operator surface
Browser dashboard and live operational UI.
- Dashboard UI · Jinja2 operator console for live incidents and operational actions.
src/web/templates/dashboard.html - Dashboard JS · Charts, topology interactions, shortcuts, sounds, and reconnecting live updates.
src/web/static/js/dashboard.js - Live client · Browser-side WebSocket consumer for real-time incident updates.
src/web/static/js/websocket.js
Delivery
Containerization, install scripts, and CI/CD flow.
- Docker/CI · Container build, compose runtime, install scripts, and GitHub Actions deploy flow.
Dockerfile
Connections 29
- Routers → Syslog receiver: syslog · Raw syslog events enter NetWatch from network devices.
- Grafana/Loki → Syslog receiver: proxy log stream · NetWatch reads log lines through Grafana's datasource proxy.
- Syslog receiver → Parser: normalize · Receiver hands log lines into the parsing stage.
- Parser → Classifier: parsed event · Structured events are classified by severity and mnemonic.
- Classifier → Enricher: classified event · Classification feeds enrichment and context lookup.
- Enricher → Correlator: enriched event · Contextualized events are correlated into incidents.
- Correlator → Dedup: incident candidates · Related events are deduplicated and noise-suppressed.
- Dedup → DB CRUD: persist · Operational state and incident history are written to SQLite.
- Correlator → Notifier: incident lifecycle · Significant incident transitions trigger notifications and escalation.
- Notifier → Discord: deliver · Escalation and resolution messages go to Discord.
- Notifier → Telegram: deliver · Escalation and resolution messages go to Telegram.
- Enricher → Device maps: lookup · Enrichment uses device and interface reference data.
- Enricher → AS cache: cache lookup · External AS context is resolved through cached lookups.
- Correlator → Topology data: topology-aware · Topology information separates root causes from downstream symptoms.
- Correlator → DB CRUD: incident state · Incident and recovery state is persisted for restart recovery.
- Stats engine → DB CRUD: read history · Analytics reads alert and incident history from SQLite.
- REST API → DB CRUD: read/write · REST endpoints expose and mutate operational state.
- REST API → Stats engine: metrics · Statistics and reporting endpoints use the analytics engine.
- WebSocket → Dashboard JS: push · WebSocket streams live updates to the browser client.
- Dashboard UI → REST API: requests · Operator actions flow through the REST API.
- Dashboard JS → WebSocket: subscribe · Client reconnects and subscribes to live incident updates.
- Auth → REST API: protect · Optional auth guards the operational API.
- Rate limit → REST API: throttle · Request limiting protects the control plane.
- App bootstrap → Syslog receiver: wire · Application startup connects the ingestion pipeline.
- App bootstrap → REST API: mount · FastAPI registers operational routes.
- App bootstrap → WebSocket: mount · FastAPI registers live WebSocket delivery.
- App bootstrap → Docker/CI: run · The app is packaged and launched in container or installed runtime.
- Docker/CI → Grafana/Loki: integrate · Deployment assumes Grafana/Loki as the upstream log source.
- Docker/CI → Dashboard UI: serve · Deployment serves the operator dashboard and static assets.