Die Arbeit mit Large Language Models in Produktionsumgebungen erfordert systematische Ansätze zur Fehlerdiagnose und Performance-Optimierung. In diesem Guide teile ich meine Praxiserfahrung aus über 2 Jahren Betrieb von HolySheep AI basierten Integrationen, wo wir täglich Millionen von Requests verarbeiten und dabei eine Latenz von unter 50ms auf API-Ebene erreichen.

Warum Logging die Grundlage stabiler AI-Anwendungen bildet

Bei der Integration von AI-APIs entstehen Fehlerquellen, die oft erst in Produktion sichtbar werden. Rate-Limits, Timeout-Probleme, Token-Limit-Überschreitungen und Kontextfenster-Erschöpfung sind nur einige der Herausforderungen. Ein durchdachtes Logging-System ermöglicht nicht nur schnelle Fehlerbehebung, sondern liefert auch wertvolle Metriken für Kostenoptimierung und Kapazitätsplanung.

Mit HolySheep AI's transparenter Preisgestaltung – GPT-4.1 für $8/MTok, Claude Sonnet 4.5 für $15/MTok, Gemini 2.5 Flash für $2.50/MTok und DeepSeek V3.2 für lediglich $0.42/MTok – wird präzises Logging zum kritischen Faktor für Kostenkontrolle. Unsere WeChat/Alipay-Integration ermöglicht dabei unkomplizierte Abrechnung zum Kurs ¥1=$1, was über 85% Ersparnis gegenüber westlichen Alternativen bedeutet.

Architektur eines Production-Ready Logging-Systems

Ein robustes Log-System für AI-API-Requests muss mehrere Dimensionen abdecken: Request-Tracking, Token-Verbrauch, Latenz-Messung und Fehlerkategorisierung. Die folgende Architektur hat sich in Produktion bewährt.

#!/usr/bin/env python3
"""
HolySheep AI Production Logger - Comprehensive Request Tracking
Integration mit strukturiertem Logging für Production-Grade Monitoring
"""

import json
import time
import logging
from datetime import datetime, timezone
from dataclasses import dataclass, field, asdict
from typing import Optional, Dict, Any, List
from enum import Enum
import hashlib
from concurrent.futures import ThreadPoolExecutor, as_completed

import requests

HolySheep AI Configuration

BASE_URL = "https://api.holysheep.ai/v1" API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Ersetzen Sie mit Ihrem Key

Logging Setup

logging.basicConfig( level=logging.INFO, format='%(asctime)s | %(levelname)-8s | %(name)s | %(message)s', handlers=[ logging.FileHandler('ai_api_audit.log'), logging.StreamHandler() ] ) logger = logging.getLogger("HolySheepAI.ProductionLogger") class RequestStatus(Enum): SUCCESS = "success" RATE_LIMITED = "rate_limited" TIMEOUT = "timeout" VALIDATION_ERROR = "validation_error" SERVER_ERROR = "server_error" CONTEXT_OVERFLOW = "context_overflow" AUTH_FAILED = "auth_failed" UNKNOWN = "unknown" class ErrorSeverity(Enum): INFO = 1 WARNING = 2 ERROR = 3 CRITICAL = 4 @dataclass class TokenMetrics: """Präzise Token-Metriken für Kostenanalyse""" prompt_tokens: int = 0 completion_tokens: int = 0 total_tokens: int = 0 # Kostenberechnung basierend auf HolySheep AI Preisen (2026) def calculate_cost(self, model: str) -> float: """Berechne Kosten in USD basierend auf Modell-Tarifen""" pricing = { "gpt-4.1": {"input": 2.0, "output": 6.0}, # $2/MTok in, $6/MTok out "claude-sonnet-4.5": {"input": 3.75, "output": 11.25}, "gemini-2.5-flash": {"input": 0.35, "output": 0.70}, "deepseek-v3.2": {"input": 0.14, "output": 0.28}, # $0.42/MTok all-in } if model not in pricing: logger.warning(f"Unbekanntes Modell: {model}, verwende DeepSeek-Standard") model = "deepseek-v3.2" p = pricing[model] cost = (self.prompt_tokens * p["input"] + self.completion_tokens * p["output"]) / 1_000_000 return round(cost, 6) @dataclass class RequestMetrics: """Umfassende Metriken für einen API-Request""" request_id: str model: str timestamp: str status: RequestStatus # Timing latency_ms: float ttft_ms: Optional[float] = None # Time to First Token # Token-Verbrauch tokens: Optional[TokenMetrics] = None # Request-Details prompt_length: int = 0 max_tokens_requested: int = 0 # Kosten estimated_cost_usd: float = 0.0 # Fehlerinformationen error_message: Optional[str] = None error_code: Optional[str] = None retry_count: int = 0 # Request fingerprint für Debugging prompt_hash: str = "" class HolySheepAILogger: """ Production-Grade Logger für HolySheep AI API Requests. Erfasst Metriken, Kosten und Fehler für umfassende Analyse. """ def __init__(self, base_url: str = BASE_URL, api_key: str = API_KEY): self.base_url = base_url self.api_key = api_key self.session = requests.Session() self.session.headers.update({ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }) self._metrics_buffer: List[RequestMetrics] = [] def _generate_request_id(self, prompt: str) -> str: """Erzeuge eindeutige Request-ID mit Hash-Kurzform""" raw = f"{prompt[:100]}{time.time()}" return hashlib.sha256(raw.encode()).hexdigest()[:16] def _classify_error(self, status_code: int, response_data: Dict) -> RequestStatus: """Klassifiziere Fehlertyp für gezielte Analyse""" error_type = response_data.get("error", {}).get("type", "") if status_code == 200: return RequestStatus.SUCCESS elif status_code == 429: return RequestStatus.RATE_LIMITED elif status_code == 400 and "context_length" in error_type: return RequestStatus.CONTEXT_OVERFLOW elif status_code == 401 or status_code == 403: return RequestStatus.AUTH_FAILED elif status_code >= 500: return RequestStatus.SERVER_ERROR elif status_code == 400: return RequestStatus.VALIDATION_ERROR else: return RequestStatus.UNKNOWN def _create_stream_handler(self): """Erstelle Stream-Handler für Time-to-First-Token Messung""" import io return io.BytesIO() def log_request( self, prompt: str, model: str = "deepseek-v3.2", max_tokens: int = 1000, temperature: float = 0.7, system_prompt: Optional[str] = None ) -> RequestMetrics: """ Führe Request aus und protokolliere umfassende Metriken. """ request_id = self._generate_request_id(prompt) prompt_hash = hashlib.md5(prompt.encode()).hexdigest() timestamp = datetime.now(timezone.utc).isoformat() start_time = time.perf_counter() ttft = None retry_count = 0 current_status = RequestStatus.UNKNOWN error_msg = None error_code = None response_data = {} # Retry-Logic mit exponentieller Backoff max_retries = 3 for attempt in range(max_retries): try: messages = [] if system_prompt: messages.append({"role": "system", "content": system_prompt}) messages.append({"role": "user", "content": prompt}) payload = { "model": model, "messages": messages, "max_tokens": max_tokens, "temperature": temperature } response = self.session.post( f"{self.base_url}/chat/completions", json=payload, timeout=60 ) response_data = response.json() if response.status_code == 429: retry_count += 1 wait_time = min(2 ** attempt * 0.5, 10) logger.warning(f"Rate-Limit erreicht, Retry {retry_count}/{max_retries} in {wait_time}s") time.sleep(wait_time) continue response.raise_for_status() # Erfolgreiche Antwort current_status = RequestStatus.SUCCESS end_time = time.perf_counter() latency_ms = (end_time - start_time) * 1000 # Token-Extraktion usage = response_data.get("usage", {}) tokens = TokenMetrics( prompt_tokens=usage.get("prompt_tokens", 0), completion_tokens=usage.get("completion_tokens", 0), total_tokens=usage.get("total_tokens", 0) ) # Kostenberechnung estimated_cost = tokens.calculate_cost(model) metrics = RequestMetrics( request_id=request_id, model=model, timestamp=timestamp, status=current_status, latency_ms=round(latency_ms, 2), tokens=tokens, prompt_length=len(prompt), max_tokens_requested=max_tokens, estimated_cost_usd=estimated_cost, prompt_hash=prompt_hash, retry_count=retry_count ) # Log-Eintrag schreiben self._write_metrics(metrics) self._metrics_buffer.append(metrics) logger.info( f"Request {request_id} | Model: {model} | " f"Latenz: {latency_ms:.2f}ms | Tokens: {tokens.total_tokens} | " f"Kosten: ${estimated_cost:.6f}" ) return metrics except requests.exceptions.Timeout: current_status = RequestStatus.TIMEOUT error_msg = "Request-Timeout nach 60s" logger.error(f"Timeout bei Request {request_id}") break except requests.exceptions.RequestException as e: current_status = self._classify_error( getattr(response, 'status_code', 0), response_data ) error_msg = str(e) error_code = getattr(response, 'status_code', None) logger.error(f"Request fehlgeschlagen: {error_msg}") if current_status in [RequestStatus.SERVER_ERROR, RequestStatus.UNKNOWN]: retry_count += 1 if retry_count < max_retries: continue break except Exception as e: current_status = RequestStatus.UNKNOWN error_msg = f"Unerwarteter Fehler: {str(e)}" logger.critical(f"Kritischer Fehler: {error_msg}") break # Fehler-Metriken erfassen metrics = RequestMetrics( request_id=request_id, model=model, timestamp=timestamp, status=current_status, latency_ms=(time.perf_counter() - start_time) * 1000, prompt_length=len(prompt), max_tokens_requested=max_tokens, error_message=error_msg, error_code=str(error_code) if error_code else None, retry_count=retry_count, prompt_hash=prompt_hash ) self._write_metrics(metrics) return metrics def _write_metrics(self, metrics: RequestMetrics): """Schreibe Metriken in strukturiertes JSON-Format""" log_entry = asdict(metrics) if log_entry.get('tokens'): log_entry['tokens'] = asdict(log_entry['tokens']) with open('ai_api_metrics.jsonl', 'a') as f: f.write(json.dumps(log_entry) + '\n') def analyze_logs(self, log_file: str = 'ai_api_metrics.jsonl') -> Dict[str, Any]: """ Analysiere gesammelte Logs und erstelle Report. """ total_requests = 0 successful = 0 failed = 0 total_cost = 0.0 total_tokens = 0 latency_sum = 0.0 latency_p50 = [] errors_by_type: Dict[str, int] = {} cost_by_model: Dict[str, float] = {} try: with open(log_file, 'r') as f: for line in f: data = json.loads(line) total_requests += 1 if data['status'] == 'success': successful += 1 total_cost += data.get('estimated_cost_usd', 0) total_tokens += data.get('tokens', {}).get('total_tokens', 0) latency_sum += data['latency_ms'] latency_p50.append(data['latency_ms']) model = data['model'] cost_by_model[model] = cost_by_model.get(model, 0) + data.get('estimated_cost_usd', 0) else: failed += 1 error_type = data.get('error_message', 'unknown') errors_by_type[error_type] = errors_by_type.get(error_type, 0) + 1 latency_p50.sort() p50_index = len(latency_p50) // 2 p50_latency = latency_p50[p50_index] if latency_p50 else 0 return { "summary": { "total_requests": total_requests, "successful": successful, "failed": failed, "success_rate": f"{(successful/total_requests*100):.2f}%" if total_requests else "0%", "total_cost_usd": round(total_cost, 4), "total_tokens": total_tokens, "avg_cost_per_1k_tokens": round((total_cost / total_tokens * 1000), 6) if total_tokens else 0 }, "latency": { "avg_ms": round(latency_sum / successful, 2) if successful else 0, "p50_ms": round(p50_latency, 2), "min_ms": round(min(latency_p50), 2) if latency_p50 else 0, "max_ms": round(max(latency_p50), 2) if latency_p50 else 0 }, "cost_breakdown": cost_by_model, "error_distribution": errors_by_type } except FileNotFoundError: logger.error(f"Log-Datei nicht gefunden: {log_file}") return {}

===== Benchmark-Test =====

def run_benchmark(): """Führe Benchmark mit HolySheep AI durch""" logger.info("=" * 60) logger.info("Starte HolySheep AI Performance-Benchmark") logger.info("=" * 60) client = HolySheepAILogger() test_prompts = [ "Erkläre die Grundlagen von Machine Learning in 3 Sätzen.", "Schreibe eine Python-Funktion zur Fibonacci-Berechnung mit Memoization.", "Was sind die Hauptvorteile von Transformer-Architekturen?" ] results = [] for i, prompt in enumerate(test_prompts, 1): logger.info(f"Teste Prompt {i}/{len(test_prompts)}") metrics = client.log_request( prompt=prompt, model="deepseek-v3.2", max_tokens=500 ) results.append(metrics) # Analyse analysis = client.analyze_logs() print("\n" + "=" * 60) print("BENCHMARK ERGEBNISSE") print("=" * 60) print(json.dumps(analysis, indent=2)) return analysis if __name__ == "__main__": run_benchmark()

Kontextfenster-Management und Overflow-Prävention

Einer der kritischsten Fehler in der AI-API-Integration ist der Context-Overflow – wenn dieSumme aus System-Prompt, Historien-Kontext und aktueller Anfrage die Modellkapazität überschreitet. In meiner Praxis bei HolySheep AI-Integrationen habe ich drei Strategien entwickelt, die sich bewährt haben.

#!/usr/bin/env python3
"""
Context Window Manager - Verhindert Overflow-Fehler durch intelligente Verwaltung
"""

import tiktoken
from dataclasses import dataclass
from typing import List, Dict, Tuple, Optional
from enum import Enum

Modell-Konfigurationen (Token-Limits und Preise 2026)

MODEL_CONFIGS = { "deepseek-v3.2": { "context_window": 128000, "max_output": 8192, "input_cost_per_1m": 0.14, # $0.14/MTok "output_cost_per_1m": 0.28, # $0.28/MTok "encoding": "cl100k_base" }, "gpt-4.1": { "context_window": 128000, "max_output": 16384, "input_cost_per_1m": 2.0, "output_cost_per_1m": 6.0, "encoding": "cl100k_base" }, "gemini-2.5-flash": { "context_window": 1048576, # 1M Token! "max_output": 8192, "input_cost_per_1m": 0.35, "output_cost_per_1m": 0.70, "encoding": "cl100k_base" }, "claude-sonnet-4.5": { "context_window": 200000, "max_output": 8192, "input_cost_per_1m": 3.75, "output_cost_per_1m": 11.25, "encoding": "cl100k_base" } } class TruncationStrategy(Enum): """Verfügbare Truncation-Strategien""" FRONT = "front" # Älteste Messages entfernen MIDDLE = "middle" # Mittleren Teil entfernen SMART = "smart" # Nach Wichtigkeit filtern @dataclass class Message: role: str content: str tokens: int = 0 def __post_init__(self): if self.tokens == 0: self.tokens = self._estimate_tokens(self.content) @dataclass class ContextWindow: """Manages conversation context within token limits""" model: str = "deepseek-v3.2" system_prompt: Optional[Message] = None messages: List[Message] = None reserved_output_tokens: int = 500 def __post_init__(self): if self.messages is None: self.messages = [] self.config = MODEL_CONFIGS.get(self.model, MODEL_CONFIGS["deepseek-v3.2"]) self._encoder = tiktoken.get_encoding(self.config["encoding"]) def _estimate_tokens(self, text: str) -> int: """Schnelle Token-Schätzung ohne exakte Encoding-Overhead""" return len(self._encoder.encode(text)) def _exact_tokens(self, text: str) -> int: """Exakte Token-Zählung für finale Validierung""" return len(self._encoder.encode(text)) @property def total_tokens(self) -> int: """Aktuelle Gesamttoken-Nutzung""" system_tokens = self.system_prompt.tokens if self.system_prompt else 0 message_tokens = sum(m.tokens for m in self.messages) return system_tokens + message_tokens @property def available_for_input(self) -> int: """Verfügbare Token für weitere Eingabe""" return self.config["context_window"] - self.reserved_output_tokens @property def usage_percentage(self) -> float: """Auslastung des Kontextfensters in Prozent""" return (self.total_tokens / self.available_for_input) * 100 def needs_truncation(self, additional_tokens: int = 0) -> bool: """Prüft ob Truncation erforderlich ist""" return (self.total_tokens + additional_tokens) > self.available_for_input def truncate( self, strategy: TruncationStrategy = TruncationStrategy.FRONT, preserve_messages: int = 2 ) -> Tuple[int, int]: """ Truncates conversation history to fit context window. Returns: Tuple of (removed_tokens, removed_messages_count) """ if not self.needs_truncation(): return 0, 0 original_tokens = self.total_tokens removed_count = 0 if strategy == TruncationStrategy.FRONT: # Entferne älteste Messages, behalte neueste while self.needs_truncation() and len(self.messages) > preserve_messages: removed = self.messages.pop(0) removed_count += 1 logger.debug(f"Entferne älteste Message: {removed.tokens} Token") elif strategy == TruncationStrategy.MIDDLE: # Entferne Messages aus der Mitte (Summarization-Point) while self.needs_truncation() and len(self.messages) > preserve_messages: # Finde mittlere Message mid_index = len(self.messages) // 2 removed = self.messages.pop(mid_index) removed_count += 1 logger.debug(f"Entferne mittlere Message: {removed.tokens} Token") elif strategy == TruncationStrategy.SMART: # Behalte System und letzte Messages, falle zurück auf FRONT return self.truncate(TruncationStrategy.FRONT, preserve_messages) new_tokens = self.total_tokens logger.info( f"Truncation abgeschlossen: {original_tokens - new_tokens} Token entfernt, " f"{removed_count} Messages entfernt, {self.usage_percentage:.1f}% Auslastung" ) return original_tokens - new_tokens, removed_count def to_api_format(self) -> List[Dict[str, str]]: """Konvertiere zu HolySheep AI API-Format""" result = [] if self.system_prompt: result.append({ "role": "system", "content": self.system_prompt.content }) for msg in self.messages: result.append({ "role": msg.role, "content": msg.content }) return result def estimate_cost(self, output_tokens: int) -> Dict[str, float]: """Schätze API-Kosten für diesen Request""" input_tokens = self.total_tokens config = self.config input_cost = (input_tokens / 1_000_000) * config["input_cost_per_1m"] output_cost = (output_tokens / 1_000_000) * config["output_cost_per_1m"] return { "input_cost": round(input_cost, 6), "output_cost": round(output_cost, 6), "total_cost": round(input_cost + output_cost, 6), "input_tokens": input_tokens, "output_tokens": output_tokens } def validate_and_prepare( self, new_message_tokens: int, max_output_tokens: int, strategy: TruncationStrategy = TruncationStrategy.FRONT ) -> Dict[str, any]: """ Validiert Kontext und führt nötige Anpassungen durch. Returns: Dict mit Validierungsstatus, angepasstem Kontext und Kosten """ validation = { "is_valid": True, "warnings": [], "truncation_performed": False, "tokens_removed": 0, "messages_removed": 0, "final_usage_percentage": self.usage_percentage } # Reserve output tokens anpassen actual_reserved = min(max_output_tokens, self.config["max_output"]) if actual_reserved < max_output_tokens: validation["warnings"].append( f"Output auf {actual_reserved} begrenzt (Max: {self.config['max_output']})" ) # Prüfe Overflow-Risiko if self.needs_truncation(new_message_tokens): # Kritische Warnung: Truncation erforderlich validation["is_valid"] = True # Wird korrigiert validation["warnings"].append( f"Kontext-Overflow erkannt: {self.total_tokens + new_message_tokens} > " f"{self.available_for_input} verfügbar" ) removed_tokens, removed_msgs = self.truncate( strategy=strategy, preserve_messages=2 ) validation["truncation_performed"] = True validation["tokens_removed"] = removed_tokens validation["messages_removed"] = removed_msgs if self.needs_truncation(new_message_tokens): validation["is_valid"] = False validation["warnings"].append( "Kritisch: Selbst nach Truncation ist Context zu groß!" ) # Kosten schätzen validation["cost_estimate"] = self.estimate_cost(actual_reserved) return validation class ConversationManager: """High-Level Manager für Multi-Turn Konversationen""" def __init__(self, model: str = "deepseek-v3.2"): self.model = model self.context = ContextWindow(model=model) self.conversation_id = None self.interaction_count = 0 def set_system_prompt(self, system_prompt: str) -> ContextWindow: """Setze System-Prompt mit Token-Zählung""" tokens = self.context._estimate_tokens(system_prompt) self.context.system_prompt = Message(role="system", content=system_prompt, tokens=tokens) return self.context def add_user_message(self, content: str) -> ContextWindow: """Füge User-Message hinzu""" tokens = self.context._estimate_tokens(content) msg = Message(role="user", content=content, tokens=tokens) self.context.messages.append(msg) self.interaction_count += 1 return self.context def add_assistant_message(self, content: str) -> ContextWindow: """Füge Assistant-Response hinzu""" tokens = self.context._estimate_tokens(content) msg = Message(role="assistant", content=content, tokens=tokens) self.context.messages.append(msg) return self.context def prepare_request( self, max_output_tokens: int = 500, truncation_strategy: TruncationStrategy = TruncationStrategy.SMART ) -> Tuple[List[Dict], Dict]: """ Bereitet Request für HolySheep AI API vor. Returns: Tuple von (API-Payload, Validierungs-Report) """ validation = self.context.validate_and_prepare( new_message_tokens=0, # Keine neue Message, nur bestehenden Kontext prüfen max_output_tokens=max_output_tokens, strategy=truncation_strategy ) payload = self.context.to_api_format() return payload, validation def get_statistics(self) -> Dict: """Gib Konversations-Statistiken zurück""" return { "model": self.model, "interaction_count": self.interaction_count, "total_tokens": self.context.total_tokens, "context_usage_percent": round(self.context.usage_percentage, 2), "messages_in_context": len(self.context.messages), "available_context": self.context.config["context_window"], "max_output": self.context.config["max_output"] }

===== Beispiel-Nutzung =====

if __name__ == "__main__": import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger("ContextManager") # Initialisiere Manager manager = ConversationManager(model="deepseek-v3.2") # System-Prompt setzen manager.set_system_prompt( "Du bist ein hilfreicher Python-Entwickler-Assistent. " "Antworte präzise und strukturiert mit Code-Beispielen." ) # Multi-Turn Konversation simulieren test_conversation = [ ("user", "Wie implementiere ich einen Binary Search Tree in Python?"), ("assistant", "Ein Binary Search Tree in Python:\n\n``python\nclass Node:\n def __init__(self, value):\n self.value = value\n self.left = None\n self.right = None\n``"), ("user", "Füge eine Insert-Methode hinzu."), ("assistant", "Hier die Insert-Methode:\n\n``python\ndef insert(root, value):\n if root is None:\n return Node(value)\n if value < root.value:\n root.left = insert(root.left, value)\n else:\n root.right = insert(root.right, value)\n return root\n``"), ("user", "Implementiere auch eine Delete-Funktion mit allen drei Fällen."), ] for role, content in test_conversation: if role == "user": manager.add_user_message(content) else: manager.add_assistant_message(content) # Statistiken ausgeben stats = manager.get_statistics() print("=" * 60) print("KONVERSATIONS-STATISTIK") print("=" * 60) for key, value in stats.items(): print(f"{key}: {value}") # Request vorbereiten payload, validation = manager.prepare_request( max_output_tokens=1000, truncation_strategy=TruncationStrategy.SMART ) print("\n" + "=" * 60) print("VALIDIERUNG") print("=" * 60) print(f"Valide: {validation['is_valid']}") print(f"Truncation durchgeführt: {validation['truncation_performed']}") print(f"Auslastung: {validation['final_usage_percentage']:.2f}%") cost = validation['cost_estimate'] print(f"\nKostenschätzung:") print(f" Input: ${cost['input_cost']:.6f} ({cost['input_tokens']} Token)") print(f" Output: ${cost['output_cost']:.6f} ({cost['output_tokens']} Token)") print(f" Gesamt: ${cost['total_cost']:.6f}") print("\n" + "=" * 60) print("API PAYLOAD") print("=" * 60) import json print(json.dumps(payload, indent=2, ensure_ascii=False))

Rate-Limiting und Concurrency-Control für Production-Workloads

Bei hochfrequentierten AI-APIs ist effektives Rate-Limiting essentiell. HolySheep AI bietet generous Limits, aber bei skalierbaren Anwendungen müssen Sie eigene Kontrollmechanismen implementieren. Die Kombination aus Token-Bucket-Algorithmen und Request-Queuing hat sich als optimal erwiesen.

#!/usr/bin/env python3
"""
HolySheep AI Rate Limiter & Concurrency Controller
Production-Grade Implementation mit Token Bucket und Request Queuing
"""

import asyncio
import time
import logging
from dataclasses import dataclass, field
from typing import Optional, Callable, Any, Dict, List
from collections import deque
from enum import Enum
from threading import Lock
import heapq

logger = logging.getLogger("RateLimiter")


class RateLimitStrategy(Enum):
    """Verfügbare Rate-Limiting Strategien"""
    TOKEN_BUCKET = "token_bucket"
    LEAKED_BUCKET = "leaked_bucket"
    SLIDING_WINDOW = "sliding_window"
    ADAPTIVE = "adaptive"


@dataclass
class RateLimitConfig:
    """Konfiguration für Rate-Limiting"""
    requests_per_minute: int = 60
    requests_per_second: int = 10
    tokens_per_minute: int = 500_000
    burst_allowance: int = 5
    
    # Retry-Konfiguration
    max_retries: int = 3
    base_retry_delay: float = 1.0
    max_retry_delay: float = 60.0
    retry_multiplier: float = 2.0
    
    # Circuit Breaker
    circuit_breaker_threshold: int = 10
    circuit_breaker_timeout: float = 30.0


class TokenBucket:
    """
    Token Bucket Implementierung für flexible Rate-Limiting.
    Erlaubt Burst-Traffic bis zum definierten Limit.
    """
    
    def __init__(
        self,
        rate: float,
        capacity: int,
        time_unit: float = 1.0
    ):
        self.rate = rate          # Tokens pro time_unit
        self.capacity = capacity  # Maximale Burst-Kapazität
        self.tokens = capacity
        self.time_unit = time_unit
        self.last_update = time.monotonic()
        self._lock = Lock()
    
    def _refill(self):
        """Fülle Bucket basierend auf vergangener Zeit auf"""
        now = time.monotonic()
        elapsed = now - self.last_update
        
        # Tokens hinzufügen basierend auf Rate
        new_tokens = elapsed * (self.rate / self.time_unit)
        self.tokens = min(self.capacity, self.tokens + new_tokens)
        self.last_update = now
    
    def consume(self, tokens: int = 1, blocking: bool = False) -> bool:
        """
        Versuche Tokens zu verbrauchen.
        
        Args:
            tokens: Anzahl der Tokens zu verbrauchen
            blocking: Ob blockieren bis verfügbar
            
        Returns:
            True wenn erfolgreich, False wenn nicht genug Tokens
        """
        while True:
            with self._lock:
                self._refill()
                
                if self.tokens >= tokens:
                    self.tokens -= tokens
                    return True
                
                if not blocking:
                    return False
                
                # Berechne Wartezeit
                tokens_needed = tokens - self.tokens
                wait_time = tokens_needed / (self.rate / self.time_unit)
            
            # Außerhalb des Locks warten
            time.sleep(min(wait_time, 0.1))
    
    @property
    def available_tokens(self) -> float:
        """Aktuell verfügbare Tokens"""
        with self._lock:
            self._refill()
            return self.tokens


class SlidingWindowRateLimiter:
    """
    Sliding Window Counter für präzise Rate-Limiting.
    Genauer als Token Bucket für bursty Traffic.
    """
    
    def __init__(self, max_requests: int, window_seconds: int):
        self.max_requests = max_requests
        self.window_seconds = window_seconds
        self.requests: deque = deque()
        self._lock = Lock()
    
    def _cleanup_old_requests(self):
        """Entferne abgelaufene Requests"""