""" Error Event Entity - Detailliertes Fehler-Event """ from dataclasses import dataclass, field from datetime import datetime from typing import Dict, Any, Optional, List from enum import Enum import uuid class ErrorType(Enum): """Typen von Fehlern die auftreten können""" RATE_LIMIT = "rate_limit" CAPTCHA = "captcha" NETWORK = "network" VALIDATION = "validation" BROWSER = "browser" PROXY = "proxy" EMAIL = "email" TIMEOUT = "timeout" AUTHENTICATION = "authentication" UNKNOWN = "unknown" class ErrorSeverity(Enum): """Schweregrad des Fehlers""" LOW = "low" MEDIUM = "medium" HIGH = "high" CRITICAL = "critical" @dataclass class ErrorContext: """Kontext-Informationen zum Fehler""" url: Optional[str] = None action: Optional[str] = None step_name: Optional[str] = None user_input: Optional[Dict[str, Any]] = None browser_state: Optional[Dict[str, Any]] = None network_state: Optional[Dict[str, Any]] = None screenshot_path: Optional[str] = None html_snapshot: Optional[str] = None additional_data: Dict[str, Any] = field(default_factory=dict) @dataclass class RecoveryAttempt: """Informationen über Wiederherstellungsversuche""" strategy: str timestamp: datetime successful: bool error_message: Optional[str] = None duration_seconds: float = 0.0 @dataclass class ErrorEvent: """Detailliertes Fehler-Event""" error_id: str = field(default_factory=lambda: str(uuid.uuid4())) timestamp: datetime = field(default_factory=datetime.now) error_type: ErrorType = ErrorType.UNKNOWN error_message: str = "" stack_trace: Optional[str] = None context: ErrorContext = field(default_factory=ErrorContext) recovery_attempted: bool = False recovery_successful: bool = False recovery_attempts: List[RecoveryAttempt] = field(default_factory=list) # Fehler-Metadaten severity: ErrorSeverity = ErrorSeverity.MEDIUM platform: Optional[str] = None session_id: Optional[str] = None account_id: Optional[str] = None correlation_id: Optional[str] = None # Impact-Metriken user_impact: bool = True system_impact: bool = False data_loss: bool = False def add_recovery_attempt(self, attempt: RecoveryAttempt): """Fügt einen Wiederherstellungsversuch hinzu""" self.recovery_attempts.append(attempt) self.recovery_attempted = True if attempt.successful: self.recovery_successful = True def get_recovery_success_rate(self) -> float: """Berechnet die Erfolgsrate der Wiederherstellungsversuche""" if not self.recovery_attempts: return 0.0 successful = sum(1 for attempt in self.recovery_attempts if attempt.successful) return successful / len(self.recovery_attempts) def is_critical(self) -> bool: """Prüft ob der Fehler kritisch ist""" return self.severity == ErrorSeverity.CRITICAL or self.data_loss def should_retry(self) -> bool: """Entscheidet ob ein Retry sinnvoll ist""" recoverable_types = [ ErrorType.NETWORK, ErrorType.TIMEOUT, ErrorType.RATE_LIMIT, ErrorType.PROXY ] return (self.error_type in recoverable_types and len(self.recovery_attempts) < 3 and not self.recovery_successful) def to_dict(self) -> Dict[str, Any]: """Konvertiert Event zu Dictionary für Serialisierung""" return { 'error_id': self.error_id, 'timestamp': self.timestamp.isoformat(), 'error_type': self.error_type.value, 'error_message': self.error_message, 'stack_trace': self.stack_trace, 'context': { 'url': self.context.url, 'action': self.context.action, 'step_name': self.context.step_name, 'screenshot_path': self.context.screenshot_path, 'additional_data': self.context.additional_data }, 'recovery_attempted': self.recovery_attempted, 'recovery_successful': self.recovery_successful, 'recovery_attempts': [ { 'strategy': attempt.strategy, 'timestamp': attempt.timestamp.isoformat(), 'successful': attempt.successful, 'error_message': attempt.error_message, 'duration_seconds': attempt.duration_seconds } for attempt in self.recovery_attempts ], 'severity': self.severity.value, 'platform': self.platform, 'session_id': self.session_id, 'account_id': self.account_id, 'correlation_id': self.correlation_id, 'user_impact': self.user_impact, 'system_impact': self.system_impact, 'data_loss': self.data_loss, 'recovery_success_rate': self.get_recovery_success_rate() }