Files
AccountForger-neuerUpload/infrastructure/services/structured_analytics_service.py
Claude Project Manager 04585e95b6 Initial commit
2025-08-01 23:50:28 +02:00

281 Zeilen
12 KiB
Python

"""
Structured Analytics Service - Konkrete Implementation für Analytics
"""
import logging
import json
from typing import List, Optional, Dict, Any, Union
from datetime import datetime, timedelta
import uuid
from domain.services.analytics_service import IAnalyticsService
from domain.entities.account_creation_event import AccountCreationEvent
from domain.entities.error_event import ErrorEvent
from domain.value_objects.error_summary import ErrorSummary
from domain.value_objects.report import Report, ReportType, Metric, PlatformStats, TimeSeriesData
from infrastructure.repositories.analytics_repository import AnalyticsRepository
logger = logging.getLogger("structured_analytics_service")
class StructuredAnalyticsService(IAnalyticsService):
"""Konkrete Implementation des Analytics Service"""
def __init__(self, repository: AnalyticsRepository = None):
self.repository = repository or AnalyticsRepository()
def log_event(self, event: Union[AccountCreationEvent, ErrorEvent, Any]) -> None:
"""Loggt ein Event für spätere Analyse"""
if isinstance(event, AccountCreationEvent):
self.repository.save_account_creation_event(event)
logger.debug(f"Logged account creation event {event.event_id}")
elif isinstance(event, ErrorEvent):
self.repository.save_error_event(event)
logger.debug(f"Logged error event {event.error_id}")
else:
logger.warning(f"Unknown event type: {type(event)}")
def get_success_rate(self,
timeframe: Optional[timedelta] = None,
platform: Optional[str] = None) -> float:
"""Berechnet die Erfolgsrate"""
return self.repository.get_success_rate(timeframe, platform)
def get_common_errors(self,
limit: int = 10,
timeframe: Optional[timedelta] = None) -> List[ErrorSummary]:
"""Holt die häufigsten Fehler"""
return self.repository.get_common_errors(limit, timeframe)
def generate_report(self,
report_type: ReportType,
start: datetime,
end: datetime,
platforms: Optional[List[str]] = None) -> Report:
"""Generiert einen Report"""
# Hole Basis-Metriken
timeframe = end - start
success_rate = self.get_success_rate(timeframe, platforms[0] if platforms else None)
# Hole Platform-Statistiken
platform_stats_data = self.repository.get_platform_stats(timeframe)
platform_stats = []
for platform, stats in platform_stats_data.items():
if not platforms or platform in platforms:
platform_stats.append(PlatformStats(
platform=platform,
total_attempts=stats['total_attempts'],
successful_accounts=stats['successful_accounts'],
failed_attempts=stats['failed_attempts'],
avg_duration_seconds=stats['avg_duration_seconds'],
error_distribution={} # TODO: Implementiere Error Distribution
))
# Berechne Gesamt-Statistiken
total_attempts = sum(ps.total_attempts for ps in platform_stats)
total_accounts = sum(ps.successful_accounts for ps in platform_stats)
avg_duration = sum(ps.avg_duration_seconds * ps.total_attempts for ps in platform_stats) / total_attempts if total_attempts > 0 else 0
# Erstelle Metriken
metrics = [
Metric("success_rate", success_rate, "percentage", 0.0),
Metric("total_accounts", float(total_accounts), "count", 0.0),
Metric("avg_duration", avg_duration, "seconds", 0.0)
]
# Hole Timeline-Daten
timeline_data = self.repository.get_timeline_data('success_rate', 24, platforms[0] if platforms else None)
success_timeline = None
if timeline_data:
timestamps = [datetime.fromisoformat(d['timestamp']) for d in timeline_data]
values = [d['success_rate'] for d in timeline_data]
success_timeline = TimeSeriesData(timestamps, values, "Success Rate")
# Hole Error Summaries
error_summaries = []
common_errors = self.get_common_errors(10, timeframe)
for error in common_errors:
error_summaries.append(error.to_dict())
# Erstelle Report
return Report(
report_id=str(uuid.uuid4()),
report_type=report_type,
start_date=start,
end_date=end,
generated_at=datetime.now(),
total_accounts_created=total_accounts,
total_attempts=total_attempts,
overall_success_rate=success_rate,
avg_creation_time=avg_duration,
metrics=metrics,
platform_stats=platform_stats,
error_summaries=error_summaries,
success_rate_timeline=success_timeline
)
def get_real_time_metrics(self) -> Dict[str, Any]:
"""Holt Echtzeit-Metriken"""
# Letzte Stunde
one_hour_ago = datetime.now() - timedelta(hours=1)
# Timeline für letzte Stunde
timeline = self.repository.get_timeline_data('success_rate', 1)
# Berechne Metriken
total_attempts = sum(d['total'] for d in timeline)
successful = sum(d['successful'] for d in timeline)
success_rate = successful / total_attempts if total_attempts > 0 else 0
# Platform Stats
platform_stats = self.repository.get_platform_stats(timedelta(hours=1))
return {
'timestamp': datetime.now().isoformat(),
'active_sessions': len(self.repository._execute_query(
"SELECT DISTINCT session_id FROM account_creation_analytics WHERE timestamp > ?",
(one_hour_ago,)
)),
'accounts_last_hour': successful,
'attempts_last_hour': total_attempts,
'success_rate_last_hour': success_rate,
'avg_creation_time': sum(
stats.get('avg_duration_seconds', 0)
for stats in platform_stats.values()
) / len(platform_stats) if platform_stats else 0,
'platform_breakdown': platform_stats,
'hourly_trend': self._calculate_trend(timeline)
}
def _calculate_trend(self, timeline: List[Dict[str, Any]]) -> float:
"""Berechnet Trend aus Timeline"""
if len(timeline) < 2:
return 0.0
# Vergleiche erste und letzte Hälfte
mid = len(timeline) // 2
first_half = timeline[:mid]
second_half = timeline[mid:]
first_rate = sum(d.get('success_rate', 0) for d in first_half) / len(first_half) if first_half else 0
second_rate = sum(d.get('success_rate', 0) for d in second_half) / len(second_half) if second_half else 0
if first_rate > 0:
return ((second_rate - first_rate) / first_rate) * 100
return 0.0
def track_performance(self,
metric_name: str,
value: float,
tags: Optional[Dict[str, str]] = None) -> None:
"""Trackt Performance-Metrik"""
# Würde in echter Implementation in separater Tabelle gespeichert
logger.info(f"Performance metric: {metric_name}={value} tags={tags}")
def get_account_creation_timeline(self,
hours: int = 24,
platform: Optional[str] = None) -> Dict[str, Any]:
"""Holt Account Creation Timeline"""
timeline = self.repository.get_timeline_data('accounts', hours, platform)
return {
'hours': hours,
'platform': platform,
'data_points': timeline,
'total': sum(d['successful'] for d in timeline),
'peak_hour': max(timeline, key=lambda d: d['successful'])['timestamp'] if timeline else None
}
def analyze_failure_patterns(self,
timeframe: Optional[timedelta] = None) -> Dict[str, Any]:
"""Analysiert Fehler-Muster"""
errors = self.get_common_errors(50, timeframe)
patterns = {
'timeframe': str(timeframe) if timeframe else 'all',
'total_error_types': len(errors),
'critical_errors': [],
'recurring_errors': [],
'error_clusters': []
}
# Identifiziere kritische Fehler
for error in errors:
if error.severity_score > 0.7:
patterns['critical_errors'].append({
'type': error.error_type,
'frequency': error.frequency,
'impact': error.total_user_impact + error.total_system_impact
})
# Identifiziere wiederkehrende Fehler
for error in errors:
if error.error_count > 10:
patterns['recurring_errors'].append({
'type': error.error_type,
'count': error.error_count,
'recovery_rate': error.recovery_success_rate
})
return patterns
def get_platform_comparison(self,
timeframe: Optional[timedelta] = None) -> Dict[str, Any]:
"""Vergleicht Plattformen"""
platform_stats = self.repository.get_platform_stats(timeframe)
comparison = {}
for platform, stats in platform_stats.items():
comparison[platform] = {
'success_rate': stats['success_rate'],
'total_accounts': stats['successful_accounts'],
'avg_duration': stats['avg_duration_seconds'],
'performance_score': self._calculate_platform_score(stats)
}
return comparison
def _calculate_platform_score(self, stats: Dict[str, Any]) -> float:
"""Berechnet Performance Score für Platform"""
# Gewichtete Bewertung
success_weight = 0.5
speed_weight = 0.3
volume_weight = 0.2
# Normalisiere Werte
success_score = stats['success_rate']
speed_score = 1.0 - min(stats['avg_duration_seconds'] / 300, 1.0) # 5 min max
volume_score = min(stats['total_attempts'] / 100, 1.0) # 100 als Referenz
return (success_score * success_weight +
speed_score * speed_weight +
volume_score * volume_weight)
def export_data(self,
format: str = "json",
start: Optional[datetime] = None,
end: Optional[datetime] = None) -> bytes:
"""Exportiert Daten"""
# Generiere Report für Zeitraum
report = self.generate_report(
ReportType.CUSTOM,
start or datetime.now() - timedelta(days=7),
end or datetime.now()
)
if format == "json":
return json.dumps(report.to_dict(), indent=2).encode()
elif format == "csv":
# Vereinfachte CSV-Implementation
csv_data = "platform,attempts,success,rate\n"
for stat in report.platform_stats:
csv_data += f"{stat.platform},{stat.total_attempts},{stat.successful_accounts},{stat.success_rate}\n"
return csv_data.encode()
else:
raise ValueError(f"Unsupported format: {format}")
def cleanup_old_events(self, older_than: datetime) -> int:
"""Bereinigt alte Events"""
return self.repository.cleanup_old_events(older_than)