Merge pull request #149 from trails-cool/fix/planner-metrics-gauges

Fix planner metrics gauges always reporting zero
This commit is contained in:
Ullrich Schäfer 2026-04-03 10:04:40 +01:00 committed by GitHub
commit 5a5fe87905
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 21 deletions

View file

@ -1,29 +1,44 @@
import client from "prom-client";
// Collect default Node.js metrics (event loop, heap, GC)
client.collectDefaultMetrics();
// Guard all metric registration — Vite's dev server can re-evaluate
// this module, causing "already registered" errors.
function getOrCreate<T>(name: string, create: () => T): T {
return (client.register.getSingleMetric(name) as T) ?? create();
}
export const httpRequestDuration = new client.Histogram({
name: "http_request_duration_seconds",
help: "Duration of HTTP requests in seconds",
labelNames: ["method", "route", "status"] as const,
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
});
if (!client.register.getSingleMetric("process_cpu_user_seconds_total")) {
client.collectDefaultMetrics();
}
export const plannerActiveSessions = new client.Gauge({
name: "planner_active_sessions",
help: "Number of active planner sessions",
});
export const httpRequestDuration = getOrCreate("http_request_duration_seconds", () =>
new client.Histogram({
name: "http_request_duration_seconds",
help: "Duration of HTTP requests in seconds",
labelNames: ["method", "route", "status"] as const,
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
}),
);
export const plannerConnectedClients = new client.Gauge({
name: "planner_connected_clients",
help: "Number of connected WebSocket clients",
});
export const plannerActiveSessions = getOrCreate("planner_active_sessions", () =>
new client.Gauge({
name: "planner_active_sessions",
help: "Number of active planner sessions",
}),
);
export const brouterRequestDuration = new client.Histogram({
name: "brouter_request_duration_seconds",
help: "Duration of BRouter API requests in seconds",
buckets: [0.1, 0.25, 0.5, 1, 2, 5, 10],
});
export const plannerConnectedClients = getOrCreate("planner_connected_clients", () =>
new client.Gauge({
name: "planner_connected_clients",
help: "Number of connected WebSocket clients",
}),
);
export const brouterRequestDuration = getOrCreate("brouter_request_duration_seconds", () =>
new client.Histogram({
name: "brouter_request_duration_seconds",
help: "Duration of BRouter API requests in seconds",
buckets: [0.1, 0.25, 0.5, 1, 2, 5, 10],
}),
);
export const registry = client.register;

View file

@ -6,6 +6,7 @@ import * as encoding from "lib0/encoding";
import * as decoding from "lib0/decoding";
import type { IncomingMessage, Server } from "node:http";
import { saveSessionState, loadSessionState, touchSession } from "./sessions.ts";
import { plannerActiveSessions, plannerConnectedClients } from "./metrics.server.ts";
const messageSync = 0;
const messageAwareness = 1;
@ -159,10 +160,13 @@ export function setupYjsWebSocket(server: Server): WebSocketServer {
});
wss.on("connection", async (ws: WebSocket, _request: IncomingMessage, sessionId: string) => {
const isNewSession = !docs.has(sessionId);
const doc = await getOrLoadDoc(sessionId);
const awareness = getAwareness(sessionId, doc);
conns.set(ws, { sessionId, clientIds: new Set() });
plannerConnectedClients.inc();
if (isNewSession) plannerActiveSessions.inc();
// Broadcast doc updates to all connections in this session
const onUpdate = (update: Uint8Array, origin: unknown) => {
@ -218,11 +222,13 @@ export function setupYjsWebSocket(server: Server): WebSocketServer {
);
}
conns.delete(ws);
plannerConnectedClients.dec();
doc.off("update", onUpdate);
// Save when last client leaves
const hasClients = Array.from(conns.values()).some((m) => m.sessionId === sessionId);
if (!hasClients) {
plannerActiveSessions.dec();
saveSessionState(sessionId).catch(() => {});
}
});