# Error Tracking and Monitoring Implementation Playbook This file contains detailed patterns, checklists, and code samples referenced by the skill. ## Instructions ### 1. Error Tracking Analysis Analyze current error handling and tracking: **Error Analysis Script** ```python import os import re import ast from pathlib import Path from collections import defaultdict class ErrorTrackingAnalyzer: def analyze_codebase(self, project_path): """ Analyze error handling patterns in codebase """ analysis = { 'error_handling': self._analyze_error_handling(project_path), 'logging_usage': self._analyze_logging(project_path), 'monitoring_setup': self._check_monitoring_setup(project_path), 'error_patterns': self._identify_error_patterns(project_path), 'recommendations': [] } self._generate_recommendations(analysis) return analysis def _analyze_error_handling(self, project_path): """Analyze error handling patterns""" patterns = { 'try_catch_blocks': 0, 'unhandled_promises': 0, 'generic_catches': 0, 'error_types': defaultdict(int), 'error_reporting': [] } for file_path in Path(project_path).rglob('*.{js,ts,py,java,go}'): content = file_path.read_text(errors='ignore') # JavaScript/TypeScript patterns if file_path.suffix in ['.js', '.ts']: patterns['try_catch_blocks'] += len(re.findall(r'try\s*{', content)) patterns['generic_catches'] += len(re.findall(r'catch\s*\([^)]*\)\s*{\s*}', content)) patterns['unhandled_promises'] += len(re.findall(r'\.then\([^)]+\)(?!\.catch)', content)) # Python patterns elif file_path.suffix == '.py': try: tree = ast.parse(content) for node in ast.walk(tree): if isinstance(node, ast.Try): patterns['try_catch_blocks'] += 1 for handler in node.handlers: if handler.type is None: patterns['generic_catches'] += 1 except: pass return patterns def _analyze_logging(self, project_path): """Analyze logging patterns""" logging_patterns = { 'console_logs': 0, 'structured_logging': False, 'log_levels_used': set(), 'logging_frameworks': [] } # Check for logging frameworks package_files = ['package.json', 'requirements.txt', 'go.mod', 'pom.xml'] for pkg_file in package_files: pkg_path = Path(project_path) / pkg_file if pkg_path.exists(): content = pkg_path.read_text() if 'winston' in content or 'bunyan' in content: logging_patterns['logging_frameworks'].append('winston/bunyan') if 'pino' in content: logging_patterns['logging_frameworks'].append('pino') if 'logging' in content: logging_patterns['logging_frameworks'].append('python-logging') if 'logrus' in content or 'zap' in content: logging_patterns['logging_frameworks'].append('logrus/zap') return logging_patterns ``` ### 2. Error Tracking Service Integration Implement integrations with popular error tracking services: **Sentry Integration** ```javascript // sentry-setup.js import * as Sentry from "@sentry/node"; import { ProfilingIntegration } from "@sentry/profiling-node"; class SentryErrorTracker { constructor(config) { this.config = config; this.initialized = false; } initialize() { Sentry.init({ dsn: this.config.dsn, environment: this.config.environment, release: this.config.release, // Performance Monitoring tracesSampleRate: this.config.tracesSampleRate || 0.1, profilesSampleRate: this.config.profilesSampleRate || 0.1, // Integrations integrations: [ // HTTP integration new Sentry.Integrations.Http({ tracing: true }), // Express integration new Sentry.Integrations.Express({ app: this.config.app, router: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] }), // Database integration new Sentry.Integrations.Postgres(), new Sentry.Integrations.Mysql(), new Sentry.Integrations.Mongo(), // Profiling new ProfilingIntegration(), // Custom integrations ...this.getCustomIntegrations() ], // Filtering beforeSend: (event, hint) => { // Filter sensitive data if (event.request?.cookies) { delete event.request.cookies; } // Filter out specific errors if (this.shouldFilterError(event, hint)) { return null; } // Enhance error context return this.enhanceErrorEvent(event, hint); }, // Breadcrumbs beforeBreadcrumb: (breadcrumb, hint) => { // Filter sensitive breadcrumbs if (breadcrumb.category === 'console' && breadcrumb.level === 'debug') { return null; } return breadcrumb; }, // Options attachStacktrace: true, shutdownTimeout: 5000, maxBreadcrumbs: 100, debug: this.config.debug || false, // Tags initialScope: { tags: { component: this.config.component, version: this.config.version }, user: { id: this.config.userId, segment: this.config.userSegment } } }); this.initialized = true; this.setupErrorHandlers(); } setupErrorHandlers() { // Global error handler process.on('uncaughtException', (error) => { console.error('Uncaught Exception:', error); Sentry.captureException(error, { tags: { type: 'uncaught_exception' }, level: 'fatal' }); // Graceful shutdown this.gracefulShutdown(); }); // Promise rejection handler process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection:', reason); Sentry.captureException(reason, { tags: { type: 'unhandled_rejection' }, extra: { promise: promise.toString() } }); }); } enhanceErrorEvent(event, hint) { // Add custom context event.extra = { ...event.extra, memory: process.memoryUsage(), uptime: process.uptime(), nodeVersion: process.version }; // Add user context if (this.config.getUserContext) { event.user = this.config.getUserContext(); } // Add custom fingerprinting if (hint.originalException) { event.fingerprint = this.generateFingerprint(hint.originalException); } return event; } generateFingerprint(error) { // Custom fingerprinting logic const fingerprint = []; // Group by error type fingerprint.push(error.name || 'Error'); // Group by error location if (error.stack) { const match = error.stack.match(/at\s+(.+?)\s+\(/); if (match) { fingerprint.push(match[1]); } } // Group by custom properties if (error.code) { fingerprint.push(error.code); } return fingerprint; } } // Express middleware export const sentryMiddleware = { requestHandler: Sentry.Handlers.requestHandler(), tracingHandler: Sentry.Handlers.tracingHandler(), errorHandler: Sentry.Handlers.errorHandler({ shouldHandleError(error) { // Capture 4xx and 5xx errors if (error.status >= 400) { return true; } return false; } }) }; ``` **Custom Error Tracking Service** ```typescript // error-tracker.ts interface ErrorEvent { timestamp: Date; level: 'debug' | 'info' | 'warning' | 'error' | 'fatal'; message: string; stack?: string; context: { user?: any; request?: any; environment: string; release: string; tags: Record; extra: Record; }; fingerprint: string[]; } class ErrorTracker { private queue: ErrorEvent[] = []; private batchSize = 10; private flushInterval = 5000; constructor(private config: ErrorTrackerConfig) { this.startBatchProcessor(); } captureException(error: Error, context?: Partial) { const event: ErrorEvent = { timestamp: new Date(), level: 'error', message: error.message, stack: error.stack, context: { environment: this.config.environment, release: this.config.release, tags: {}, extra: {}, ...context }, fingerprint: this.generateFingerprint(error) }; this.addToQueue(event); } captureMessage(message: string, level: ErrorEvent['level'] = 'info') { const event: ErrorEvent = { timestamp: new Date(), level, message, context: { environment: this.config.environment, release: this.config.release, tags: {}, extra: {} }, fingerprint: [message] }; this.addToQueue(event); } private addToQueue(event: ErrorEvent) { // Apply sampling if (Math.random() > this.config.sampleRate) { return; } // Filter sensitive data event = this.sanitizeEvent(event); // Add to queue this.queue.push(event); // Flush if queue is full if (this.queue.length >= this.batchSize) { this.flush(); } } private sanitizeEvent(event: ErrorEvent): ErrorEvent { // Remove sensitive data const sensitiveKeys = ['password', 'token', 'secret', 'api_key']; const sanitize = (obj: any): any => { if (!obj || typeof obj !== 'object') return obj; const cleaned = Array.isArray(obj) ? [] : {}; for (const [key, value] of Object.entries(obj)) { if (sensitiveKeys.some(k => key.toLowerCase().includes(k))) { cleaned[key] = '[REDACTED]'; } else if (typeof value === 'object') { cleaned[key] = sanitize(value); } else { cleaned[key] = value; } } return cleaned; }; return { ...event, context: sanitize(event.context) }; } private async flush() { if (this.queue.length === 0) return; const events = this.queue.splice(0, this.batchSize); try { await this.sendEvents(events); } catch (error) { console.error('Failed to send error events:', error); // Re-queue events this.queue.unshift(...events); } } private async sendEvents(events: ErrorEvent[]) { const response = await fetch(this.config.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.config.apiKey}` }, body: JSON.stringify({ events }) }); if (!response.ok) { throw new Error(`Error tracking API returned ${response.status}`); } } } ``` ### 3. Structured Logging Implementation Implement comprehensive structured logging: **Advanced Logger** ```typescript // structured-logger.ts import winston from 'winston'; import { ElasticsearchTransport } from 'winston-elasticsearch'; class StructuredLogger { private logger: winston.Logger; constructor(config: LoggerConfig) { this.logger = winston.createLogger({ level: config.level || 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.metadata(), winston.format.json() ), defaultMeta: { service: config.service, environment: config.environment, version: config.version }, transports: this.createTransports(config) }); } private createTransports(config: LoggerConfig): winston.transport[] { const transports: winston.transport[] = []; // Console transport for development if (config.environment === 'development') { transports.push(new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), winston.format.simple() ) })); } // File transport for all environments transports.push(new winston.transports.File({ filename: 'logs/error.log', level: 'error', maxsize: 5242880, // 5MB maxFiles: 5 })); transports.push(new winston.transports.File({ filename: 'logs/combined.log', maxsize: 5242880, maxFiles: 5 }); // Elasticsearch transport for production if (config.elasticsearch) { transports.push(new ElasticsearchTransport({ level: 'info', clientOpts: config.elasticsearch, index: `logs-${config.service}`, transformer: (logData) => { return { '@timestamp': logData.timestamp, severity: logData.level, message: logData.message, fields: { ...logData.metadata, ...logData.defaultMeta } }; } })); } return transports; } // Logging methods with context error(message: string, error?: Error, context?: any) { this.logger.error(message, { error: { message: error?.message, stack: error?.stack, name: error?.name }, ...context }); } warn(message: string, context?: any) { this.logger.warn(message, context); } info(message: string, context?: any) { this.logger.info(message, context); } debug(message: string, context?: any) { this.logger.debug(message, context); } // Performance logging startTimer(label: string): () => void { const start = Date.now(); return () => { const duration = Date.now() - start; this.info(`Timer ${label}`, { duration, label }); }; } // Audit logging audit(action: string, userId: string, details: any) { this.info('Audit Event', { type: 'audit', action, userId, timestamp: new Date().toISOString(), details }); } } // Request logging middleware export function requestLoggingMiddleware(logger: StructuredLogger) { return (req: Request, res: Response, next: NextFunction) => { const start = Date.now(); // Log request logger.info('Incoming request', { method: req.method, url: req.url, ip: req.ip, userAgent: req.get('user-agent') }); // Log response res.on('finish', () => { const duration = Date.now() - start; logger.info('Request completed', { method: req.method, url: req.url, status: res.statusCode, duration, contentLength: res.get('content-length') }); }); next(); }; } ``` ### 4. Error Alerting Configuration Set up intelligent alerting: **Alert Manager** ```python # alert_manager.py from dataclasses import dataclass from typing import List, Dict, Optional from datetime import datetime, timedelta import asyncio @dataclass class AlertRule: name: str condition: str threshold: float window: timedelta severity: str channels: List[str] cooldown: timedelta = timedelta(minutes=15) class AlertManager: def __init__(self, config): self.config = config self.rules = self._load_rules() self.alert_history = {} self.channels = self._setup_channels() def _load_rules(self): """Load alert rules from configuration""" return [ AlertRule( name="High Error Rate", condition="error_rate", threshold=0.05, # 5% error rate window=timedelta(minutes=5), severity="critical", channels=["slack", "pagerduty"] ), AlertRule( name="Response Time Degradation", condition="response_time_p95", threshold=1000, # 1 second window=timedelta(minutes=10), severity="warning", channels=["slack"] ), AlertRule( name="Memory Usage Critical", condition="memory_usage_percent", threshold=90, window=timedelta(minutes=5), severity="critical", channels=["slack", "pagerduty"] ), AlertRule( name="Disk Space Low", condition="disk_free_percent", threshold=10, window=timedelta(minutes=15), severity="warning", channels=["slack", "email"] ) ] async def evaluate_rules(self, metrics: Dict): """Evaluate all alert rules against current metrics""" for rule in self.rules: if await self._should_alert(rule, metrics): await self._send_alert(rule, metrics) async def _should_alert(self, rule: AlertRule, metrics: Dict) -> bool: """Check if alert should be triggered""" # Check if metric exists if rule.condition not in metrics: return False # Check threshold value = metrics[rule.condition] if not self._check_threshold(value, rule.threshold, rule.condition): return False # Check cooldown last_alert = self.alert_history.get(rule.name) if last_alert and datetime.now() - last_alert < rule.cooldown: return False return True async def _send_alert(self, rule: AlertRule, metrics: Dict): """Send alert through configured channels""" alert_data = { "rule": rule.name, "severity": rule.severity, "value": metrics[rule.condition], "threshold": rule.threshold, "timestamp": datetime.now().isoformat(), "environment": self.config.environment, "service": self.config.service } # Send to all channels tasks = [] for channel_name in rule.channels: if channel_name in self.channels: channel = self.channels[channel_name] tasks.append(channel.send(alert_data)) await asyncio.gather(*tasks) # Update alert history self.alert_history[rule.name] = datetime.now() # Alert channels class SlackAlertChannel: def __init__(self, webhook_url): self.webhook_url = webhook_url async def send(self, alert_data): """Send alert to Slack""" color = { "critical": "danger", "warning": "warning", "info": "good" }.get(alert_data["severity"], "danger") payload = { "attachments": [{ "color": color, "title": f"🚨 {alert_data['rule']}", "fields": [ { "title": "Severity", "value": alert_data["severity"].upper(), "short": True }, { "title": "Environment", "value": alert_data["environment"], "short": True }, { "title": "Current Value", "value": str(alert_data["value"]), "short": True }, { "title": "Threshold", "value": str(alert_data["threshold"]), "short": True } ], "footer": alert_data["service"], "ts": int(datetime.now().timestamp()) }] } # Send to Slack async with aiohttp.ClientSession() as session: await session.post(self.webhook_url, json=payload) ``` ### 5. Error Grouping and Deduplication Implement intelligent error grouping: **Error Grouping Algorithm** ```python import hashlib import re from difflib import SequenceMatcher class ErrorGrouper: def __init__(self): self.groups = {} self.patterns = self._compile_patterns() def _compile_patterns(self): """Compile regex patterns for normalization""" return { 'numbers': re.compile(r'\b\d+\b'), 'uuids': re.compile(r'[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}'), 'urls': re.compile(r'https?://[^\s]+'), 'file_paths': re.compile(r'(/[^/\s]+)+'), 'memory_addresses': re.compile(r'0x[0-9a-fA-F]+'), 'timestamps': re.compile(r'\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}') } def group_error(self, error): """Group error with similar errors""" fingerprint = self.generate_fingerprint(error) # Find existing group group = self.find_similar_group(fingerprint, error) if group: group['count'] += 1 group['last_seen'] = error['timestamp'] group['instances'].append(error) else: # Create new group self.groups[fingerprint] = { 'fingerprint': fingerprint, 'first_seen': error['timestamp'], 'last_seen': error['timestamp'], 'count': 1, 'instances': [error], 'pattern': self.extract_pattern(error) } return fingerprint def generate_fingerprint(self, error): """Generate unique fingerprint for error""" # Normalize error message normalized = self.normalize_message(error['message']) # Include error type and location components = [ error.get('type', 'Unknown'), normalized, self.extract_location(error.get('stack', '')) ] # Generate hash fingerprint = hashlib.sha256( '|'.join(components).encode() ).hexdigest()[:16] return fingerprint def normalize_message(self, message): """Normalize error message for grouping""" # Replace dynamic values normalized = message for pattern_name, pattern in self.patterns.items(): normalized = pattern.sub(f'<{pattern_name}>', normalized) return normalized.strip() def extract_location(self, stack): """Extract error location from stack trace""" if not stack: return 'unknown' lines = stack.split('\n') for line in lines: # Look for file references if ' at ' in line: # Extract file and line number match = re.search(r'at\s+(.+?)\s*\((.+?):(\d+):(\d+)\)', line) if match: file_path = match.group(2) # Normalize file path file_path = re.sub(r'.*/(?=src/|lib/|app/)', '', file_path) return f"{file_path}:{match.group(3)}" return 'unknown' def find_similar_group(self, fingerprint, error): """Find similar error group using fuzzy matching""" if fingerprint in self.groups: return self.groups[fingerprint] # Try fuzzy matching normalized_message = self.normalize_message(error['message']) for group_fp, group in self.groups.items(): similarity = SequenceMatcher( None, normalized_message, group['pattern'] ).ratio() if similarity > 0.85: # 85% similarity threshold return group return None ``` ### 6. Performance Impact Tracking Monitor performance impact of errors: **Performance Monitor** ```typescript // performance-monitor.ts interface PerformanceMetrics { responseTime: number; errorRate: number; throughput: number; apdex: number; resourceUsage: { cpu: number; memory: number; disk: number; }; } class PerformanceMonitor { private metrics: Map = new Map(); private intervals: Map = new Map(); startMonitoring(service: string, interval: number = 60000) { const timer = setInterval(() => { this.collectMetrics(service); }, interval); this.intervals.set(service, timer); } private async collectMetrics(service: string) { const metrics: PerformanceMetrics = { responseTime: await this.getResponseTime(service), errorRate: await this.getErrorRate(service), throughput: await this.getThroughput(service), apdex: await this.calculateApdex(service), resourceUsage: await this.getResourceUsage() }; // Store metrics if (!this.metrics.has(service)) { this.metrics.set(service, []); } const serviceMetrics = this.metrics.get(service)!; serviceMetrics.push(metrics); // Keep only last 24 hours const dayAgo = Date.now() - 24 * 60 * 60 * 1000; const filtered = serviceMetrics.filter(m => m.timestamp > dayAgo); this.metrics.set(service, filtered); // Check for anomalies this.detectAnomalies(service, metrics); } private detectAnomalies(service: string, current: PerformanceMetrics) { const history = this.metrics.get(service) || []; if (history.length < 10) return; // Need history for comparison // Calculate baselines const baseline = this.calculateBaseline(history.slice(-60)); // Last hour // Check for anomalies const anomalies = []; if (current.responseTime > baseline.responseTime * 2) { anomalies.push({ type: 'response_time_spike', severity: 'warning', value: current.responseTime, baseline: baseline.responseTime }); } if (current.errorRate > baseline.errorRate + 0.05) { anomalies.push({ type: 'error_rate_increase', severity: 'critical', value: current.errorRate, baseline: baseline.errorRate }); } if (anomalies.length > 0) { this.reportAnomalies(service, anomalies); } } private calculateBaseline(history: PerformanceMetrics[]) { const sum = history.reduce((acc, m) => ({ responseTime: acc.responseTime + m.responseTime, errorRate: acc.errorRate + m.errorRate, throughput: acc.throughput + m.throughput, apdex: acc.apdex + m.apdex }), { responseTime: 0, errorRate: 0, throughput: 0, apdex: 0 }); return { responseTime: sum.responseTime / history.length, errorRate: sum.errorRate / history.length, throughput: sum.throughput / history.length, apdex: sum.apdex / history.length }; } async calculateApdex(service: string, threshold: number = 500) { // Apdex = (Satisfied + Tolerating/2) / Total const satisfied = await this.countRequests(service, 0, threshold); const tolerating = await this.countRequests(service, threshold, threshold * 4); const total = await this.getTotalRequests(service); if (total === 0) return 1; return (satisfied + tolerating / 2) / total; } } ``` ### 7. Error Recovery Strategies Implement automatic error recovery: **Recovery Manager** ```javascript // recovery-manager.js class RecoveryManager { constructor(config) { this.strategies = new Map(); this.retryPolicies = config.retryPolicies || {}; this.circuitBreakers = new Map(); this.registerDefaultStrategies(); } registerStrategy(errorType, strategy) { this.strategies.set(errorType, strategy); } registerDefaultStrategies() { // Network errors this.registerStrategy('NetworkError', async (error, context) => { return this.retryWithBackoff( context.operation, this.retryPolicies.network || { maxRetries: 3, baseDelay: 1000, maxDelay: 10000 } ); }); // Database errors this.registerStrategy('DatabaseError', async (error, context) => { // Try read replica if available if (context.operation.type === 'read' && context.readReplicas) { return this.tryReadReplica(context); } // Otherwise retry with backoff return this.retryWithBackoff( context.operation, this.retryPolicies.database || { maxRetries: 2, baseDelay: 500, maxDelay: 5000 } ); }); // Rate limit errors this.registerStrategy('RateLimitError', async (error, context) => { const retryAfter = error.retryAfter || 60; await this.delay(retryAfter * 1000); return context.operation(); }); // Circuit breaker for external services this.registerStrategy('ExternalServiceError', async (error, context) => { const breaker = this.getCircuitBreaker(context.service); try { return await breaker.execute(context.operation); } catch (error) { // Fallback to cache or default if (context.fallback) { return context.fallback(); } throw error; } }); } async recover(error, context) { const errorType = this.classifyError(error); const strategy = this.strategies.get(errorType); if (!strategy) { // No recovery strategy, rethrow throw error; } try { const result = await strategy(error, context); // Log recovery success this.logRecovery(error, errorType, 'success'); return result; } catch (recoveryError) { // Log recovery failure this.logRecovery(error, errorType, 'failure', recoveryError); // Throw original error throw error; } } async retryWithBackoff(operation, policy) { let lastError; let delay = policy.baseDelay; for (let attempt = 0; attempt < policy.maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error; if (attempt < policy.maxRetries - 1) { await this.delay(delay); delay = Math.min(delay * 2, policy.maxDelay); } } } throw lastError; } getCircuitBreaker(service) { if (!this.circuitBreakers.has(service)) { this.circuitBreakers.set(service, new CircuitBreaker({ timeout: 3000, errorThresholdPercentage: 50, resetTimeout: 30000, rollingCountTimeout: 10000, rollingCountBuckets: 10, volumeThreshold: 10 })); } return this.circuitBreakers.get(service); } classifyError(error) { // Classify by error code if (error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT') { return 'NetworkError'; } if (error.code === 'ER_LOCK_DEADLOCK' || error.code === 'SQLITE_BUSY') { return 'DatabaseError'; } if (error.status === 429) { return 'RateLimitError'; } if (error.isExternalService) { return 'ExternalServiceError'; } // Default return 'UnknownError'; } } // Circuit breaker implementation class CircuitBreaker { constructor(options) { this.options = options; this.state = 'CLOSED'; this.failures = 0; this.successes = 0; this.nextAttempt = Date.now(); } async execute(operation) { if (this.state === 'OPEN') { if (Date.now() < this.nextAttempt) { throw new Error('Circuit breaker is OPEN'); } // Try half-open this.state = 'HALF_OPEN'; } try { const result = await Promise.race([ operation(), this.timeout(this.options.timeout) ]); this.onSuccess(); return result; } catch (error) { this.onFailure(); throw error; } } onSuccess() { this.failures = 0; if (this.state === 'HALF_OPEN') { this.successes++; if (this.successes >= this.options.volumeThreshold) { this.state = 'CLOSED'; this.successes = 0; } } } onFailure() { this.failures++; if (this.state === 'HALF_OPEN') { this.state = 'OPEN'; this.nextAttempt = Date.now() + this.options.resetTimeout; } else if (this.failures >= this.options.volumeThreshold) { this.state = 'OPEN'; this.nextAttempt = Date.now() + this.options.resetTimeout; } } } ``` ### 8. Error Dashboard Create comprehensive error dashboard: **Dashboard Component** ```typescript // error-dashboard.tsx import React from 'react'; import { LineChart, BarChart, PieChart } from 'recharts'; const ErrorDashboard: React.FC = () => { const [metrics, setMetrics] = useState(); const [timeRange, setTimeRange] = useState('1h'); useEffect(() => { const fetchMetrics = async () => { const data = await getErrorMetrics(timeRange); setMetrics(data); }; fetchMetrics(); const interval = setInterval(fetchMetrics, 30000); // Update every 30s return () => clearInterval(interval); }, [timeRange]); if (!metrics) return ; return (

Error Tracking Dashboard

0.05 ? 'critical' : 'ok'} />

Recent Errors

Active Alerts

); }; // Real-time error stream const ErrorStream: React.FC = () => { const [errors, setErrors] = useState([]); useEffect(() => { const eventSource = new EventSource('/api/errors/stream'); eventSource.onmessage = (event) => { const error = JSON.parse(event.data); setErrors(prev => [error, ...prev].slice(0, 100)); }; return () => eventSource.close(); }, []); return (

Live Error Stream

{errors.map((error, index) => ( ))}
); }; ``` ## Output Format 1. **Error Tracking Analysis**: Current error handling assessment 2. **Integration Configuration**: Setup for error tracking services 3. **Logging Implementation**: Structured logging setup 4. **Alert Rules**: Intelligent alerting configuration 5. **Error Grouping**: Deduplication and grouping logic 6. **Recovery Strategies**: Automatic error recovery implementation 7. **Dashboard Setup**: Real-time error monitoring dashboard 8. **Documentation**: Implementation and troubleshooting guide Focus on providing comprehensive error visibility, intelligent alerting, and quick error resolution capabilities.