const client = require('prom-client'); const register = new client.Registry(); client.collectDefaultMetrics({ prefix: 'ped_ai_', register }); const httpRequestsTotal = new client.Counter({ name: 'ped_ai_http_requests_total', help: 'Total HTTP requests received by Ped-AI', labelNames: ['method', 'route', 'status_code'], registers: [register] }); const httpRequestDuration = new client.Histogram({ name: 'ped_ai_http_request_duration_seconds', help: 'HTTP request duration in seconds', labelNames: ['method', 'route', 'status_code'], buckets: [0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], registers: [register] }); const httpRequestsInProgress = new client.Gauge({ name: 'ped_ai_http_requests_in_progress', help: 'Number of Ped-AI HTTP requests currently in progress', labelNames: ['method', 'route'], registers: [register] }); function normalizeRoute(req, statusCode) { var routePath = req.route && req.route.path; var baseUrl = req.baseUrl || ''; if (Array.isArray(routePath)) return baseUrl + routePath[0]; if (routePath) return baseUrl + routePath; if (statusCode === 404) return 'unmatched'; var path = req.path || req.url || 'unknown'; return path .replace(/\b[0-9a-f]{8,}\b/gi, ':id') .replace(/\b\d+\b/g, ':id') .replace(/\?.*$/, ''); } function metricsMiddleware(req, res, next) { if (req.path === '/metrics') return next(); var route = req.route ? normalizeRoute(req) : 'pending'; var method = req.method; var endTimer = httpRequestDuration.startTimer({ method, route }); httpRequestsInProgress.inc({ method, route }); res.on('finish', function() { var finalRoute = normalizeRoute(req, res.statusCode); var labels = { method, route: finalRoute, status_code: String(res.statusCode) }; httpRequestsTotal.inc(labels); endTimer({ route: finalRoute, status_code: String(res.statusCode) }); httpRequestsInProgress.dec({ method, route }); }); next(); } async function metricsHandler(req, res) { res.setHeader('Content-Type', register.contentType); res.end(await register.metrics()); } module.exports = { metricsHandler, metricsMiddleware, register };