diff --git a/backend/index.ts b/backend/index.ts index 8514b17..6c96a61 100644 --- a/backend/index.ts +++ b/backend/index.ts @@ -1,5 +1,6 @@ import { on } from "./events"; import { handleRequest } from "./router"; +import promClient, { Histogram } from "prom-client"; const allowCors = { "Access-Control-Allow-Origin": "*", @@ -7,6 +8,17 @@ const allowCors = { "Access-Control-Allow-Headers": "Content-Type", }; +promClient.collectDefaultMetrics(); + +const requestDuration = new Histogram({ + name: "request_duration", + help: "Request duration", + labelNames: ["action"], +}); + +const metricsUser = process.env.METRICS_USER; +const metricsPassword = process.env.METRICS_PASSWORD; + const server = Bun.serve({ async fetch(request: Request) { if (request.method === "OPTIONS") { @@ -16,6 +28,22 @@ const server = Bun.serve({ if (request.url.endsWith("ws")) { if (server.upgrade(request)) return new Response("ok"); } + if (request.url.endsWith("metrics")) { + const [type, auth] = + request.headers.get("Authorization")?.split(" ") ?? []; + const [user, password] = Buffer.from(auth, "base64") + .toString("utf-8") + .split(":"); + if ( + type !== "Basic" || + user !== metricsUser || + password !== metricsPassword + ) { + return new Response("Unauthorized", { status: 401 }); + } + return new Response(await promClient.register.metrics()); + } + return new Response("Not Found", { status: 404 }); }, websocket: { message: (ws, message) => { @@ -25,7 +53,10 @@ const server = Bun.serve({ try { const msg = JSON.parse(message); console.log("Received message", msg); + const start = Date.now(); handleRequest(msg, ws); + const duration = Date.now() - start; + requestDuration.observe({ action: msg.type }, duration); } catch (e) { console.error("Faulty request", message, e); return; diff --git a/bun.lockb b/bun.lockb index d0091f2..9aa0d04 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index fd22354..ec66b90 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "pixi-viewport": "^5.0.3", "pixi.js": "^7.0.0", "pixi.js-legacy": "^7.4.2", + "prom-client": "^15.1.3", "react": "^18.3.1", "react-confetti-boom": "^1.0.0", "react-dom": "^18.3.1",