// Prometheus Metrics Collection // Request duration, error rates, database performance import { logger } from './logger'; // In production, this would use prom-client // For now, we'll create a simple metrics interface export interface Metrics { requestDuration: Map; errorCount: Map; dbQueryDuration: Map; } class MetricsService { private metrics: Metrics = { requestDuration: new Map(), errorCount: new Map(), dbQueryDuration: new Map(), }; /** * Record request duration */ recordRequestDuration(path: string, method: string, duration: number): void { const key = `${method}:${path}`; if (!this.behavioral_metrics.requestDuration.has(key)) { this.behavioral_metrics.requestDuration.set(key, []); } this.behavioral_metrics.requestDuration.get(key)?.push(duration); } /** * Record error */ recordError(path: string, method: string, statusCode: number): void { const key = `${method}:${path}:${statusCode}`; const current = this.behavioral_metrics.errorCount.get(key) || 0; this.behavioral_metrics.errorCount.set(key, current + 1); } /** * Record database query duration */ recordDbQuery(operation: string, duration: number): void { if (!this.behavioral_metrics.dbQueryDuration.has(operation)) { this.behavioral_metrics.dbQueryDuration.set(operation, []); } this.behavioral_metrics.dbQueryDuration.get(operation)?.push(duration); } /** * Get average request duration for a path */ getAverageRequestDuration(path: string, method: string): number { const key = `${method}:${path}`; const durations = this.behavioral_metrics.requestDuration.get(key) || []; if (durations.length === 0) return 0; return durations.reduce((a, b) => a + b, 0) / durations.length; } /** * Get error count for a path */ getErrorCount(path: string, method: string, statusCode: number): number { const key = `${method}:${path}:${statusCode}`; return this.behavioral_metrics.errorCount.get(key) || 0; } /** * Get metrics summary */ getSummary(): { requestDurations: Record; errorCounts: Record; dbQueryDurations: Record; } { const requestDurations: Record = {}; for (const [key, durations] of this.behavioral_metrics.requestDuration.entries()) { if (durations.length > 0) { requestDurations[key] = durations.reduce((a, b) => a + b, 0) / durations.length; } } const errorCounts: Record = {}; for (const [key, count] of this.behavioral_metrics.errorCount.entries()) { errorCounts[key] = count; } const dbQueryDurations: Record = {}; for (const [operation, durations] of this.behavioral_metrics.dbQueryDuration.entries()) { if (durations.length > 0) { dbQueryDurations[operation] = durations.reduce((a, b) => a + b, 0) / durations.length; } } return { requestDurations, errorCounts, dbQueryDurations, }; } /** * Reset metrics (useful for testing) */ reset(): void { this.behavioral_metrics = { requestDuration: new Map(), errorCount: new Map(), dbQueryDuration: new Map(), }; } } export const metricsService = new MetricsService();