Initial commit
Dieser Commit ist enthalten in:
150
domain/entities/error_event.py
Normale Datei
150
domain/entities/error_event.py
Normale Datei
@ -0,0 +1,150 @@
|
||||
"""
|
||||
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()
|
||||
}
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren