Files
MineGeo/lib/prometheus-response.ts

49 lines
1.6 KiB
TypeScript

import { createHash } from "node:crypto";
import { formatMetrics } from "@/shared/prometheus";
export async function metricsResponse(
request: Pick<Request, "headers">,
read: (tokenHash: string) => Promise<unknown>,
) {
const headers = {
"Cache-Control": "private, no-store",
"X-Content-Type-Options": "nosniff",
};
const match = /^Bearer (mg_metrics_[a-f0-9]{64})$/.exec(
request.headers.get("authorization") ?? "",
);
if (!match)
return new Response("Metrics authentication required\n", {
status: 401,
headers: { ...headers, "WWW-Authenticate": "Bearer" },
});
try {
const start = performance.now();
const snapshot = await read(
createHash("sha256").update(match[1]).digest("hex"),
);
if (snapshot === null)
return new Response("Metrics authentication required\n", {
status: 401,
headers: { ...headers, "WWW-Authenticate": "Bearer" },
});
const body =
formatMetrics(snapshot) +
"# HELP minegeo_exporter_read_duration_seconds Time to read and validate the database snapshot.\n" +
"# TYPE minegeo_exporter_read_duration_seconds gauge\n" +
`minegeo_exporter_read_duration_seconds ${(performance.now() - start) / 1000}\n`;
return new Response(body, {
headers: {
...headers,
"Content-Type": "text/plain; version=0.0.4; charset=utf-8",
},
});
} catch {
// Never return database errors, credentials, or a misleading all-zero snapshot.
return new Response("Metrics temporarily unavailable\n", {
status: 503,
headers,
});
}
}