import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import { test } from "node:test"; import { metricDefinitions, formatMetrics, prometheusAction, prometheusConfig, } from "../shared/prometheus"; import { metricsResponse } from "../lib/prometheus-response"; import { grafanaDashboard } from "../shared/grafana-dashboard"; const token = "mg_metrics_" + "a".repeat(64); const samples = Object.entries(metricDefinitions).flatMap( ([metric, definition]) => { let dimensions: Record[] = [{}]; for (const [key, values] of Object.entries(definition.labels) as [ string, readonly string[], ][]) dimensions = dimensions.flatMap((labels) => values.map((value) => ({ ...labels, [key]: value })), ); return dimensions.map((labels) => ({ metric, labels, value: 0 })); }, ); test("metrics exposition is bounded, complete and contains only fixed aggregate dimensions", () => { const text = formatMetrics(samples); assert.equal(samples.length, 43); assert.equal( text.split("\n").filter((line) => line && !line.startsWith("#")).length, 43, ); assert.ok(text.endsWith("\n")); assert.match(text, /# TYPE minegeo_games gauge/); assert.match(text, /minegeo_games\{difficulty="easy",status="complete"\} 0/); for (const bad of [ [...samples, samples[0]], samples.filter((s) => s.metric !== "minegeo_accounts"), [{ ...samples[0], metric: "evil_metric" }, ...samples.slice(1)], [ { ...samples[0], labels: { username: "private-player" } }, ...samples.slice(1), ], [{ ...samples[0], value: NaN }, ...samples.slice(1)], [{ ...samples[0], value: -1 }, ...samples.slice(1)], ]) assert.throws(() => formatMetrics(bad)); }); test("scrape authentication rejects cookie-only, query-only and device-style credentials before reading data", async () => { for (const authorization of [ null, "Bearer contributor-token", "Basic abc", token, `Bearer ${token}\n`, `Bearer ${token}suffix`, ]) { const headers = new Headers({ cookie: "admin=session" }); // Headers reject newlines before our endpoint is involved. if (authorization?.includes("\n")) continue; if (authorization) headers.set("authorization", authorization); const response = await metricsResponse({ headers }, async () => { assert.fail("must not query without a valid credential shape"); }); assert.equal(response.status, 401); assert.match(response.headers.get("cache-control")!, /no-store/); } const response = await metricsResponse( { headers: new Headers({ authorization: `Bearer ${token}` }) }, async (hash) => { assert.equal(hash, createHash("sha256").update(token).digest("hex")); return null; }, ); assert.equal(response.status, 401); }); test("scrape returns Prometheus text on success and fails closed during database or validation outages", async () => { const request = { headers: new Headers({ authorization: `Bearer ${token}` }), }; const response = await metricsResponse(request, async () => samples); assert.equal(response.status, 200); assert.match( response.headers.get("content-type")!, /text\/plain; version=0.0.4/, ); const body = await response.text(); assert.match(body, /minegeo_exporter_read_duration_seconds [0-9.]+/); assert.ok(!body.includes(token)); for (const read of [ async () => { throw new Error("private database detail"); }, async () => [], ]) { const failed = await metricsResponse(request, read); assert.equal(failed.status, 503); assert.equal(await failed.text(), "Metrics temporarily unavailable\n"); } }); test("copyable YAML scopes bearer credentials to the HTTPS metrics target and disallows malformed setup", () => { const config = prometheusConfig( "https://minegeo.vercel.app/api/metrics", token, ); assert.match(config, /metrics_path: "\/api\/metrics"/); assert.match(config, /targets: \["minegeo.vercel.app"\]/); assert.match(config, /follow_redirects: false/); assert.match(config, /type: Bearer/); assert.match(config, /scrape_interval: 60s/); for (const endpoint of [ "http://localhost/api/metrics", "https://user:secret@example.org/api/metrics", "https://example.org/api/metrics?secret=bad", ]) assert.throws(() => prometheusConfig(endpoint, token)); assert.throws(() => prometheusConfig("https://example.org/api/metrics", "bad\nconfig"), ); assert.equal( prometheusAction.safeParse({ action: "rotate", role: "admin" }).success, false, ); }); test("Grafana dashboard imports with a selected Prometheus source and avoids rates on retained-count gauges", () => { const dashboard = grafanaDashboard(); assert.equal(dashboard.__inputs[0].pluginId, "prometheus"); assert.equal(dashboard.panels.length, 15); const json = JSON.stringify(dashboard); assert.ok(!json.includes(token)); const supported = new Set([ ...Object.keys(metricDefinitions), "minegeo_exporter_read_duration_seconds", ]); for (const panel of dashboard.panels) { assert.equal(panel.datasource.uid, "${DS_PROMETHEUS}"); assert.ok(!/\b(rate|increase)\(/.test(panel.targets[0].expr)); for (const name of panel.targets[0].expr.match(/minegeo_[a-z0-9_]+/g) ?? []) assert.ok(supported.has(name), name); } });