From 4d5b84e4a77ead5da3d9b376fb52f5365fd2652a Mon Sep 17 00:00:00 2001 From: Steve Korshakov Date: Tue, 19 Aug 2025 19:14:27 -0700 Subject: [PATCH] ref: add http metrics --- sources/app/api.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/sources/app/api.ts b/sources/app/api.ts index a3a1202..99f25cc 100644 --- a/sources/app/api.ts +++ b/sources/app/api.ts @@ -34,7 +34,9 @@ import { decrementWebSocketConnection, sessionAliveEventsCounter, machineAliveEventsCounter, - websocketEventsCounter + websocketEventsCounter, + httpRequestsCounter, + httpRequestDurationHistogram } from "@/modules/metrics"; import { activityCache } from "@/modules/sessionCache"; @@ -42,6 +44,7 @@ import { activityCache } from "@/modules/sessionCache"; declare module 'fastify' { interface FastifyRequest { userId: string; + startTime?: number; } interface FastifyInstance { authenticate: any; @@ -71,6 +74,25 @@ export async function startApi(): Promise<{ app: FastifyInstance; io: Server }> app.setSerializerCompiler(serializerCompiler); const typed = app.withTypeProvider(); + // Add metrics hooks + app.addHook('onRequest', async (request, reply) => { + request.startTime = Date.now(); + }); + + app.addHook('onResponse', async (request, reply) => { + const duration = (Date.now() - (request.startTime || Date.now())) / 1000; + const method = request.method; + // Use routeOptions.url for the route template, fallback to parsed URL path + const route = request.routeOptions?.url || request.url.split('?')[0] || 'unknown'; + const status = reply.statusCode.toString(); + + // Increment request counter + httpRequestsCounter.inc({ method, route, status }); + + // Record request duration + httpRequestDurationHistogram.observe({ method, route, status }, duration); + }); + // Authentication decorator app.decorate('authenticate', async function (request: any, reply: any) { try {