export class PerformanceMonitor { private static instance: PerformanceMonitor; private metrics: Map = new Map(); static getInstance(): PerformanceMonitor { if (!PerformanceMonitor.instance) { PerformanceMonitor.instance = new PerformanceMonitor(); } return PerformanceMonitor.instance; } recordMetric(name: string, value: number) { if (!this.metrics.has(name)) { this.metrics.set(name, []); } this.metrics.get(name)!.push(value); if (this.metrics.get(name)!.length > 1000) { this.metrics.get(name)!.shift(); } } getAverage(name: string): number { const values = this.metrics.get(name) || []; if (values.length === 0) return 0; return values.reduce((a, b) => a + b, 0) / values.length; } getPercentile(name: string, percentile: number): number { const values = this.metrics.get(name) || []; if (values.length === 0) return 0; const sorted = [...values].sort((a, b) => a - b); const index = Math.ceil((percentile / 100) * sorted.length) - 1; return sorted[Math.max(0, index)] ?? 0; } getCount(name: string): number { return this.metrics.get(name)?.length || 0; } getMin(name: string): number { const values = this.metrics.get(name) || []; if (values.length === 0) return 0; return Math.min(...values); } getMax(name: string): number { const values = this.metrics.get(name) || []; if (values.length === 0) return 0; return Math.max(...values); } getStats(name: string) { return { count: this.getCount(name), avg: this.getAverage(name), min: this.getMin(name), max: this.getMax(name), p50: this.getPercentile(name, 50), p95: this.getPercentile(name, 95), p99: this.getPercentile(name, 99), }; } clearMetrics(name?: string) { if (name) { this.metrics.delete(name); } else { this.metrics.clear(); } } } export const monitor = PerformanceMonitor.getInstance();