From 6d468f06e27ecbad66006678597db03c77ca2431 Mon Sep 17 00:00:00 2001 From: sascha Date: Sun, 5 Apr 2026 09:45:34 +0200 Subject: [PATCH] feat: MongoDB 8, Grafana dashboard JSON, Prometheus scrape config - Upgraded from MongoDB 4.4 to 8 (AVX now available) - Added grafana-dashboard.json with 4 rows: Overview stats, Host table, Volume/Duration trends, Time-since-last-backup - Updated compose.yaml and README --- README.md | 11 ++- compose.yaml | 5 +- grafana-dashboard.json | 150 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 grafana-dashboard.json diff --git a/README.md b/README.md index 50ae9e2..b18f5b6 100644 --- a/README.md +++ b/README.md @@ -206,10 +206,19 @@ The UI follows **The Sentinel** design language: ## Tech Stack - **Backend:** Python 3.12, Flask, Gunicorn -- **Database:** MongoDB 4.4+ +- **Database:** MongoDB 8 - **Frontend:** Tailwind CSS, Vanilla JS, Material Symbols, Google Fonts - **No build step** – Tailwind loaded via CDN +## Grafana Dashboard + +Import `grafana-dashboard.json` into Grafana for a pre-built dashboard with: +- Overview stat panels (Hosts OK, Stale, Errors, Volume, Backups Today) +- Host status table with color-coded status, age, duration, size +- Backup volume per host (stacked time series) +- Backup duration per host +- Time since last backup with threshold coloring (green/yellow/red) + ## License MIT diff --git a/compose.yaml b/compose.yaml index 2a8b549..191db5d 100644 --- a/compose.yaml +++ b/compose.yaml @@ -8,11 +8,14 @@ services: environment: - MONGO_URI=mongodb://mongo:27017 - STALE_HOURS=26 + # - API_KEY=your-secret-key + # - WEBHOOK_URLS=https://n8n.example.com/webhook/backup-alert + # - WEBHOOK_EVENTS=error,stale depends_on: - mongo mongo: - image: mongo:4.4 + image: mongo:8 container_name: backup-mongo restart: always volumes: diff --git a/grafana-dashboard.json b/grafana-dashboard.json new file mode 100644 index 0000000..c46688d --- /dev/null +++ b/grafana-dashboard.json @@ -0,0 +1,150 @@ +{ + "annotations": { "list": [] }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, + "title": "Overview", + "type": "row" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "thresholds": { "steps": [{ "color": "green", "value": null }] } } }, + "gridPos": { "h": 4, "w": 4, "x": 0, "y": 1 }, + "options": { "colorMode": "background_solid", "graphMode": "none", "textMode": "value_and_name", "reduceOptions": { "calcs": ["lastNotNull"] } }, + "targets": [{ "expr": "backup_hosts_total", "legendFormat": "Total Hosts" }], + "title": "", "type": "stat" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "thresholds": { "steps": [{ "color": "green", "value": null }] } } }, + "gridPos": { "h": 4, "w": 4, "x": 4, "y": 1 }, + "options": { "colorMode": "background_solid", "graphMode": "none", "textMode": "value_and_name", "reduceOptions": { "calcs": ["lastNotNull"] } }, + "targets": [{ "expr": "count(backup_host_status == 1)", "legendFormat": "Hosts OK" }], + "title": "", "type": "stat" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "thresholds": { "steps": [{ "color": "orange", "value": null }] } } }, + "gridPos": { "h": 4, "w": 4, "x": 8, "y": 1 }, + "options": { "colorMode": "background_solid", "graphMode": "none", "textMode": "value_and_name", "reduceOptions": { "calcs": ["lastNotNull"] } }, + "targets": [{ "expr": "count(backup_host_status == -1) or vector(0)", "legendFormat": "Stale" }], + "title": "", "type": "stat" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "thresholds": { "steps": [{ "color": "red", "value": null }] } } }, + "gridPos": { "h": 4, "w": 4, "x": 12, "y": 1 }, + "options": { "colorMode": "background_solid", "graphMode": "none", "textMode": "value_and_name", "reduceOptions": { "calcs": ["lastNotNull"] } }, + "targets": [{ "expr": "count(backup_host_status == 0) or vector(0)", "legendFormat": "Errors" }], + "title": "", "type": "stat" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "unit": "decbytes", "thresholds": { "steps": [{ "color": "blue", "value": null }] } } }, + "gridPos": { "h": 4, "w": 4, "x": 16, "y": 1 }, + "options": { "colorMode": "background_solid", "graphMode": "none", "textMode": "value_and_name", "reduceOptions": { "calcs": ["lastNotNull"] } }, + "targets": [{ "expr": "backup_today_bytes", "legendFormat": "Today Volume" }], + "title": "", "type": "stat" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "thresholds": { "steps": [{ "color": "purple", "value": null }] } } }, + "gridPos": { "h": 4, "w": 4, "x": 20, "y": 1 }, + "options": { "colorMode": "background_solid", "graphMode": "area", "textMode": "value_and_name", "reduceOptions": { "calcs": ["lastNotNull"] } }, + "targets": [{ "expr": "backup_today_total", "legendFormat": "Today Backups" }], + "title": "", "type": "stat" + }, + { + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 5 }, + "title": "Host Status", + "type": "row" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { + "defaults": { + "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "filterable": true }, + "mappings": [ + { "options": { "1": { "color": "green", "text": "OK" }, "0": { "color": "red", "text": "ERROR" }, "-1": { "color": "orange", "text": "STALE" }, "-2": { "color": "text", "text": "DISABLED" } }, "type": "value" } + ] + }, + "overrides": [ + { "matcher": { "id": "byName", "options": "Status" }, "properties": [{ "id": "custom.cellOptions", "value": { "type": "color-text" } }] }, + { "matcher": { "id": "byName", "options": "Age" }, "properties": [{ "id": "unit", "value": "s" }] }, + { "matcher": { "id": "byName", "options": "Duration" }, "properties": [{ "id": "unit", "value": "s" }] }, + { "matcher": { "id": "byName", "options": "Size" }, "properties": [{ "id": "unit", "value": "decbytes" }] }, + { "matcher": { "id": "byName", "options": "Dedup" }, "properties": [{ "id": "unit", "value": "decbytes" }] } + ] + }, + "gridPos": { "h": 10, "w": 24, "x": 0, "y": 6 }, + "options": { "showHeader": true, "sortBy": [{ "desc": false, "displayName": "Status" }] }, + "targets": [ + { "expr": "backup_host_status", "legendFormat": "{{host}}", "instant": true, "format": "table", "refId": "status" }, + { "expr": "backup_host_last_seconds", "legendFormat": "{{host}}", "instant": true, "format": "table", "refId": "age" }, + { "expr": "backup_host_duration_seconds", "legendFormat": "{{host}}", "instant": true, "format": "table", "refId": "duration" }, + { "expr": "backup_host_size_bytes", "legendFormat": "{{host}}", "instant": true, "format": "table", "refId": "size" }, + { "expr": "backup_host_dedup_bytes", "legendFormat": "{{host}}", "instant": true, "format": "table", "refId": "dedup" } + ], + "title": "All Hosts", + "type": "table", + "transformations": [ + { "id": "joinByField", "options": { "byField": "host", "mode": "outer" } }, + { "id": "organize", "options": { + "renameByName": { "Value #status": "Status", "Value #age": "Age", "Value #duration": "Duration", "Value #size": "Size", "Value #dedup": "Dedup" }, + "excludeByName": { "Time": true, "Time 1": true, "Time 2": true, "Time 3": true, "Time 4": true, "__name__": true, "__name__ 1": true, "__name__ 2": true, "__name__ 3": true, "__name__ 4": true, "instance": true, "job": true } + }} + ] + }, + { + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 }, + "title": "Trends", + "type": "row" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "fillOpacity": 20, "stacking": { "mode": "normal" } }, "unit": "decbytes" } }, + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 17 }, + "options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["mean", "max"] }, "tooltip": { "mode": "multi" } }, + "targets": [{ "expr": "backup_host_size_bytes", "legendFormat": "{{host}}" }], + "title": "Backup Volume per Host", + "type": "timeseries" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "fillOpacity": 10 }, "unit": "s" } }, + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 17 }, + "options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["mean", "max"] }, "tooltip": { "mode": "multi" } }, + "targets": [{ "expr": "backup_host_duration_seconds", "legendFormat": "{{host}}" }], + "title": "Backup Duration per Host", + "type": "timeseries" + }, + { + "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "fieldConfig": { "defaults": { "color": { "mode": "continuous-GrYlRd" }, "custom": { "fillOpacity": 70 }, "unit": "s", "thresholds": { "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 43200 }, { "color": "red", "value": 93600 }] } } }, + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 25 }, + "options": { "legend": { "displayMode": "list", "placement": "right" }, "tooltip": { "mode": "single" } }, + "targets": [{ "expr": "backup_host_last_seconds", "legendFormat": "{{host}}" }], + "title": "Time Since Last Backup (green < 12h, yellow < 26h, red > 26h)", + "type": "timeseries" + } + ], + "schemaVersion": 39, + "tags": ["backup", "borgmatic", "sentinel"], + "templating": { + "list": [ + { "current": {}, "hide": 0, "name": "DS_PROMETHEUS", "type": "datasource", "query": "prometheus" } + ] + }, + "time": { "from": "now-24h", "to": "now" }, + "title": "🛡️ Backup Monitor – The Sentinel", + "uid": "backup-sentinel", + "version": 1 +}