diff --git a/docs/src/monitoring.md b/docs/src/monitoring.md index db47414..d5edf00 100644 --- a/docs/src/monitoring.md +++ b/docs/src/monitoring.md @@ -52,6 +52,10 @@ there is picked up): - **CNX Uptime** (`uptime.json`) — per-host up/down status, current uptime, availability over the selected window, and up/down history. Label-driven, so every scraped host appears automatically. +- **CNX WAN Speed** (`wan.json`) — per-gateway WAN speed from the hourly + librespeed runs: latest download/upload/ping, throughput history with each + link's 7-day median as reference, latency/jitter, and test status. See + [Site gateways](./gateways.md). - **parsedmarc** — DMARC aggregate/forensic report viewer. Auto-provisioned by the `parsedmarc` module (not from `dashboards/`); reads its own Elasticsearch datasource, not VictoriaMetrics. See [DMARC reports](#dmarc-reports) below. diff --git a/modules/monitoring/dashboards/wan.json b/modules/monitoring/dashboards/wan.json new file mode 100644 index 0000000..cf35dd1 --- /dev/null +++ b/modules/monitoring/dashboards/wan.json @@ -0,0 +1,267 @@ +{ + "uid": "cnx-wan", + "title": "CNX WAN Speed", + "tags": ["wan", "speedtest", "gateway", "cnx"], + "timezone": "browser", + "schemaVersion": 39, + "version": 1, + "refresh": "5m", + "time": { "from": "now-7d", "to": "now" }, + "templating": { "list": [] }, + "annotations": { "list": [] }, + "panels": [ + { + "type": "row", + "title": "WAN speed (site gateways)", + "id": 1, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 } + }, + { + "type": "stat", + "title": "Download (latest)", + "description": "Most recent hourly librespeed result per gateway.", + "id": 2, + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "gridPos": { "h": 5, "w": 6, "x": 0, "y": 1 }, + "fieldConfig": { + "defaults": { + "unit": "bps", + "color": { "mode": "fixed", "fixedColor": "green" }, + "noValue": "no data" + }, + "overrides": [] + }, + "options": { + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "colorMode": "value", + "graphMode": "area", + "textMode": "value_and_name", + "orientation": "auto" + }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_download_mbps * 1e6", + "legendFormat": "{{instance}}", + "instant": true + } + ] + }, + { + "type": "stat", + "title": "Upload (latest)", + "description": "Most recent hourly librespeed result per gateway.", + "id": 3, + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "gridPos": { "h": 5, "w": 6, "x": 6, "y": 1 }, + "fieldConfig": { + "defaults": { + "unit": "bps", + "color": { "mode": "fixed", "fixedColor": "blue" }, + "noValue": "no data" + }, + "overrides": [] + }, + "options": { + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "colorMode": "value", + "graphMode": "area", + "textMode": "value_and_name", + "orientation": "auto" + }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_upload_mbps * 1e6", + "legendFormat": "{{instance}}", + "instant": true + } + ] + }, + { + "type": "stat", + "title": "Ping (latest)", + "description": "Latency to the librespeed test server. Yellow over 50 ms, red over 100 ms.", + "id": 4, + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "gridPos": { "h": 5, "w": 6, "x": 12, "y": 1 }, + "fieldConfig": { + "defaults": { + "unit": "ms", + "color": { "mode": "thresholds" }, + "thresholds": { + "mode": "absolute", + "steps": [ + { "color": "green", "value": null }, + { "color": "yellow", "value": 50 }, + { "color": "red", "value": 100 } + ] + }, + "noValue": "no data" + }, + "overrides": [] + }, + "options": { + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "colorMode": "value", + "graphMode": "none", + "textMode": "value_and_name", + "orientation": "auto" + }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_ping_ms", + "legendFormat": "{{instance}}", + "instant": true + } + ] + }, + { + "type": "stat", + "title": "Test status", + "description": "Whether the last speed test on each gateway completed. FAILING also fires the WANSpeedTestFailing alert after 3h.", + "id": 5, + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "gridPos": { "h": 5, "w": 6, "x": 18, "y": 1 }, + "fieldConfig": { + "defaults": { + "color": { "mode": "thresholds" }, + "thresholds": { + "mode": "absolute", + "steps": [{ "color": "green", "value": null }] + }, + "noValue": "no data", + "mappings": [ + { + "type": "value", + "options": { + "0": { "text": "FAILING", "color": "red", "index": 0 }, + "1": { "text": "OK", "color": "green", "index": 1 } + } + } + ] + }, + "overrides": [] + }, + "options": { + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "colorMode": "background", + "graphMode": "none", + "textMode": "value_and_name", + "orientation": "auto" + }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_success", + "legendFormat": "{{instance}}", + "instant": true + } + ] + }, + { + "type": "timeseries", + "title": "Download", + "description": "Hourly download rate per gateway, with each link's own 7-day median as reference — the WANSpeedDegraded alert fires when a link stays below half its median for 3h.", + "id": 6, + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "gridPos": { "h": 9, "w": 12, "x": 0, "y": 6 }, + "fieldConfig": { + "defaults": { "unit": "bps", "min": 0 }, + "overrides": [ + { + "matcher": { "id": "byRegexp", "options": ".*7d median.*" }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { "fill": "dash", "dash": [10, 10] } + }, + { "id": "custom.fillOpacity", "value": 0 } + ] + } + ] + }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_download_mbps * 1e6", + "legendFormat": "{{instance}}" + }, + { + "refId": "B", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "quantile_over_time(0.5, speedtest_download_mbps[7d]) * 1e6", + "legendFormat": "{{instance}} 7d median" + } + ] + }, + { + "type": "timeseries", + "title": "Upload", + "description": "Hourly upload rate per gateway.", + "id": 7, + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "gridPos": { "h": 9, "w": 12, "x": 12, "y": 6 }, + "fieldConfig": { + "defaults": { "unit": "bps", "min": 0 }, + "overrides": [] + }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_upload_mbps * 1e6", + "legendFormat": "{{instance}}" + } + ] + }, + { + "type": "timeseries", + "title": "Latency & jitter", + "description": "Ping and jitter towards the librespeed test server. A latency climb with stable throughput usually means bufferbloat or an ISP routing change.", + "id": 8, + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 15 }, + "fieldConfig": { + "defaults": { "unit": "ms", "min": 0 }, + "overrides": [] + }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_ping_ms", + "legendFormat": "{{instance}} ping" + }, + { + "refId": "B", + "datasource": { "type": "prometheus", "uid": "victoriametrics" }, + "expr": "speedtest_jitter_ms", + "legendFormat": "{{instance}} jitter" + } + ] + } + ] +}