{ "annotations": {"list": [{"builtIn": 1,"datasource": {"type": "datasource","uid": "grafana"},"enable": true,"hide": true,"iconColor": "rgba(0, 211, 255, 1)","name": "Annotations & Alerts","target": {"limit": 100,"matchAny": false,"tags": [],"type": "dashboard"},"type": "dashboard"}]}, "description": "BGP update and withdrawal rates over time. Teaches what normal BGP traffic looks like and how to detect route churn or instability.", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "id": null, "links": [], "panels": [ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "description": "Learn: A healthy network has far more advertisements than withdrawals. A withdrawal spike often signals a link failure or route flap.", "fieldConfig": { "defaults": { "color": {"mode": "palette-classic"}, "custom": {"drawStyle": "bars","fillOpacity": 60,"lineWidth": 1,"spanNulls": false,"stacking": {"group": "A","mode": "none"}}, "unit": "short" }, "overrides": [ {"matcher": {"id": "byName","options": "Advertisements"},"properties": [{"id": "color","value": {"fixedColor": "green","mode": "fixed"}}]}, {"matcher": {"id": "byName","options": "Withdrawals"},"properties": [{"id": "color","value": {"fixedColor": "red","mode": "fixed"}}]} ] }, "gridPos": {"h": 10,"w": 24,"x": 0,"y": 0}, "id": 1, "options": {"legend": {"calcs": ["sum","max"],"displayMode": "list","placement": "bottom"},"tooltip": {"mode": "multi"}}, "targets": [ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "time_series", "rawSql": "SELECT\n $__timeGroupAlias(timestamp,'5m'),\n SUM(CASE WHEN iswithdrawn = false THEN 1 ELSE 0 END) AS \"Advertisements\",\n SUM(CASE WHEN iswithdrawn = true THEN 1 ELSE 0 END) AS \"Withdrawals\"\nFROM ip_rib_log\nWHERE $__timeFilter(timestamp)\nGROUP BY 1\nORDER BY 1", "refId": "A" } ], "title": "BGP Updates Over Time — Advertisements vs Withdrawals", "type": "timeseries" }, { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "fieldConfig": {"defaults": {"color": {"mode": "thresholds"},"thresholds": {"mode": "absolute","steps": [{"color": "green","value": null},{"color": "yellow","value": 100},{"color": "red","value": 1000}]},"unit": "short","mappings": []}}, "gridPos": {"h": 5,"w": 6,"x": 0,"y": 10}, "id": 2, "options": {"colorMode": "background","graphMode": "area","justifyMode": "auto","orientation": "auto","reduceOptions": {"calcs": ["lastNotNull"],"fields": "","values": false},"text": {}}, "targets": [ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "time_series", "rawSql": "SELECT NOW() AS time, COUNT(*) AS \"Total Updates (24h)\" FROM ip_rib_log WHERE timestamp > NOW() - INTERVAL '24 hours'", "refId": "A" } ], "title": "Total Updates (24h)", "type": "stat" }, { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "description": "Learn: Withdrawal rate above 30% is unusual. Above 50% may indicate a route leak or oscillation event.", "fieldConfig": {"defaults": {"color": {"mode": "thresholds"},"thresholds": {"mode": "absolute","steps": [{"color": "green","value": null},{"color": "yellow","value": 20},{"color": "red","value": 50}]},"unit": "percent","max": 100}}, "gridPos": {"h": 5,"w": 6,"x": 6,"y": 10}, "id": 3, "options": {"colorMode": "background","graphMode": "none","justifyMode": "auto","orientation": "auto","reduceOptions": {"calcs": ["lastNotNull"],"fields": "","values": false},"text": {}}, "targets": [ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "time_series", "rawSql": "SELECT NOW() AS time,\n ROUND(100.0 * SUM(CASE WHEN iswithdrawn THEN 1 ELSE 0 END) / NULLIF(COUNT(*),0), 1) AS \"Withdrawal Rate %\"\nFROM ip_rib_log\nWHERE timestamp > NOW() - INTERVAL '24 hours'", "refId": "A" } ], "title": "Withdrawal Rate % (24h)", "type": "stat" }, { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "fieldConfig": {"defaults": {"color": {"mode": "thresholds"},"thresholds": {"mode": "absolute","steps": [{"color": "green","value": null},{"color": "yellow","value": 1000},{"color": "red","value": 10000}]},"unit": "short"}}, "gridPos": {"h": 5,"w": 6,"x": 12,"y": 10}, "id": 4, "options": {"colorMode": "value","graphMode": "area","justifyMode": "auto","orientation": "auto","reduceOptions": {"calcs": ["lastNotNull"],"fields": "","values": false},"text": {}}, "targets": [ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "time_series", "rawSql": "SELECT NOW() AS time, COUNT(DISTINCT peer_hash_id) AS \"Active Peers\" FROM ip_rib_log WHERE timestamp > NOW() - INTERVAL '1 hour'", "refId": "A" } ], "title": "Active Reporting Peers (1h)", "type": "stat" }, { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "fieldConfig": {"defaults": {"color": {"mode": "thresholds"},"thresholds": {"mode": "absolute","steps": [{"color": "green","value": null},{"color": "yellow","value": 500},{"color": "red","value": 2000}]},"unit": "short"}}, "gridPos": {"h": 5,"w": 6,"x": 18,"y": 10}, "id": 5, "options": {"colorMode": "value","graphMode": "none","justifyMode": "auto","orientation": "auto","reduceOptions": {"calcs": ["lastNotNull"],"fields": "","values": false},"text": {}}, "targets": [ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "time_series", "rawSql": "SELECT NOW() AS time, COUNT(DISTINCT prefix) AS \"Unique Prefixes Updated (24h)\" FROM ip_rib_log WHERE timestamp > NOW() - INTERVAL '24 hours'", "refId": "A" } ], "title": "Unique Prefixes Updated (24h)", "type": "stat" }, { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "description": "Updates per peer over time. Learn: Peers should have similar update rates. A peer with dramatically more updates may be experiencing instability or receiving a full BGP table with frequent changes.", "fieldConfig": { "defaults": {"color": {"mode": "palette-classic"},"custom": {"drawStyle": "line","fillOpacity": 10,"lineWidth": 1,"spanNulls": false},"unit": "short"} }, "gridPos": {"h": 9,"w": 24,"x": 0,"y": 15}, "id": 6, "options": {"legend": {"calcs": [],"displayMode": "list","placement": "right"},"tooltip": {"mode": "multi"}}, "targets": [ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "time_series", "rawSql": "SELECT\n $__timeGroupAlias(s.interval_time,'30m'),\n COALESCE(p.name, p.peer_addr::text) AS metric,\n SUM(s.advertise_avg + s.withdraw_avg) AS \"Updates\"\nFROM stats_peer_update_counts s\nJOIN bgp_peers p ON p.hash_id = s.peer_hash_id\nWHERE $__timeFilter(s.interval_time)\nGROUP BY 1, 2\nORDER BY 1", "refId": "A" } ], "title": "Update Rate by Peer (30-min buckets)", "type": "timeseries" } ], "schemaVersion": 36, "style": "dark", "tags": ["obmp","learning","bgp","churn"], "time": {"from": "now-24h","to": "now"}, "timepicker": {}, "timezone": "browser", "title": "BGP Update Rate & Churn", "uid": "obmp-learn-01", "version": 1 }