class PerformanceMonitor { constructor() { this.metrics = { moduleLoads: [], loadTimes: [], errors: [], }; this.init(); } init() { this.setupPerformanceObserver(); this.setupErrorHandling(); } setupPerformanceObserver() { if ('PerformanceObserver' in window) { const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.entryType === 'resource') { this.recordLoadTime(entry.name, entry.duration); } } }); observer.observe({ entryTypes: ['resource'] }); } } setupErrorHandling() { window.addEventListener('error', (event) => { this.recordError(event.error, { filename: event.filename, lineno: event.lineno, colno: event.colno, }); }); window.addEventListener('unhandledrejection', (event) => { this.recordError(event.reason, { type: 'unhandled-promise-rejection', }); }); } recordLoadTime(url, duration) { this.metrics.loadTimes.push({ url, duration, timestamp: Date.now(), }); } recordError(error, context = {}) { this.metrics.errors.push({ error: error.message, stack: error.stack, context, timestamp: Date.now(), }); } recordModuleLoad(remote, module, success, duration) { this.metrics.moduleLoads.push({ remote, module, success, duration, timestamp: Date.now(), }); } getMetrics() { return { ...this.metrics, summary: this.generateSummary(), }; } generateSummary() { const { moduleLoads, loadTimes, errors } = this.metrics; return { totalModules: moduleLoads.length, successfulLoads: moduleLoads.filter(m => m.success).length, failedLoads: moduleLoads.filter(m => !m.success).length, averageLoadTime: loadTimes.reduce((sum, t) => sum + t.duration, 0) / loadTimes.length || 0, errorCount: errors.length, }; } exportMetrics() { const metrics = this.getMetrics(); fetch('/api/performance', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(metrics), }); } }
export default new PerformanceMonitor();
|