import { Response, Request, NextFunction } from 'express'; import { AppLocals } from '../types/AppLocals'; import { requestDurationHistogram, totalRequestCounter } from '../lib/metricsCounters'; import { SupportedRoutes } from '../types/enums/SupportedRoutes'; /** * Middleware initializes infrastructure objects which will be used throughout the request lifecycle * @param req - Express request object * @param res - Express response object * @param next - Express next middleware function */ export const InitLocalsMiddleware = (req: Request, res: Response, next: NextFunction) => { try { switch(req.path) { // for metrics routes, no prometheus timer is needed case SupportedRoutes.metricsPath: case '/favicon.ico': // placeholder method to avoid checking if timer is initialized (res.locals as AppLocals).stopPrometheusTimer = (labels) => 0; break; // all other routes get prometheus metrics default: // The request must be processed even if Prometheus does not work // That's why here we wrap the Prometheus calls in try/catch try { // counting all received requests totalRequestCounter.inc({ path: req.path }); // starting a timer to measure request processing duration // this timer will be stopped in the route handler (res.locals as AppLocals).stopPrometheusTimer = requestDurationHistogram.startTimer(); } catch(ex:any) { console.error(ex); } break; } next(); } catch(ex:any) { console.error('Error in InitLocalsMiddleware:', ex); next(ex); } }