Files

39 lines
2.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Runs every dashboard query twice: straight against Prometheus, and through Grafana's /api/ds/query with the
provisioned datasource (what a panel really does). Prints one line per panel query and exits non-zero if any
query errors or returns no series. Usage: verify-dashboard.py [output-file]"""
import base64, json, pathlib, sys, time, urllib.parse, urllib.request
root = pathlib.Path(__file__).resolve().parent.parent
dash = json.loads((root / "dashboards" / "spring-ai-observability.json").read_text())
auth = "Basic " + base64.b64encode(b"admin:admin").decode()
def get(url, data=None, headers=None):
req = urllib.request.Request(url, data=data, headers=headers or {})
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read())
lines, bad = [], 0
now = int(time.time())
lines.append(f"{'panel':<58} {'prom series':>11} {'grafana frames':>14}")
for p in dash["panels"]:
for t in p["targets"]:
q = urllib.parse.urlencode({"query": t["expr"]})
prom = get("http://127.0.0.1:9090/api/v1/query?" + q)
n_prom = len(prom["data"]["result"]) if prom["status"] == "success" else -1
body = json.dumps({"queries": [{"refId": t["refId"], "datasource": t["datasource"], "expr": t["expr"], "instant": False,
"range": True, "interval": "", "intervalMs": 5000, "maxDataPoints": 200}],
"from": str((now - 600) * 1000), "to": str(now * 1000)}).encode()
gf = get("http://127.0.0.1:3000/api/ds/query", body, {"Content-Type": "application/json", "Authorization": auth})
res = gf["results"][t["refId"]]
n_gf = -1 if "error" in res else len(res.get("frames", []))
name = f"{p['title'][:48]} [{t['refId']}]"
lines.append(f"{name:<58} {n_prom:>11} {n_gf:>14}")
if n_prom < 1 or n_gf < 1:
bad += 1
out = "\n".join(lines)
print(out)
if len(sys.argv) > 1:
pathlib.Path(sys.argv[1]).write_text("# Every dashboard query, run against Prometheus and through Grafana's query API after scripts/load.sh\n\n" + out + "\n")
sys.exit(1 if bad else 0)