import type { NextFunction, Request, Response } from "express"; import { logger } from "../lib/logger.service.js"; /** * Logs one line per request once it finishes — method, path, status code, * and duration. Mounted first in `app.ts` (before every route, and before * the error handler) so it wraps the whole request/response cycle, * including requests that end in a 404 or an error response. * * Listens on `res`'s `"finish"` event rather than wrapping `next()` in a * `try`/`finally`: this middleware calls `next()` immediately and returns, * so it never itself sits on the stack waiting for the rest of the * pipeline to resolve — `"finish"` fires once Express has actually flushed * the response, whichever handler (or the error middleware) produced it. * * `4xx`/`5xx` responses log at `warn`/`error` respectively (status alone * decides the level — this middleware has no idea *why* a request failed, * just that it did); everything else logs at `info`. A route's own * handler/the error middleware may log more detail about *why* separately * (see `error-middleware` wiring in `app.ts`) — this line is just the * "a request happened, here's the outcome" operational trace. */ export function requestLogger(req: Request, res: Response, next: NextFunction): void { const startedAt = process.hrtime.bigint(); res.on("finish", () => { const durationMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000; const meta = { method: req.method, path: req.originalUrl, status: res.statusCode, durationMs: Math.round(durationMs * 100) / 100, }; if (res.statusCode >= 500) { logger.error("Request completed", meta); } else if (res.statusCode >= 400) { logger.warn("Request completed", meta); } else { logger.info("Request completed", meta); } }); next(); }