Bài viết thực chiến từ kinh nghiệm triển khai gateway AI cho hệ thống enterprise với hơn 50K request/ngày.

Khi bạn xây dựng production AI gateway cho doanh nghiệp, việc stress test không chỉ là "đẩy load lên xem chết chỗ nào". Đó là quy trình có hệ thống để đảm bảo: concurrency limiting hoạt động chính xác, retry logic không gây cascade failure, model fallback không rơi vào loop chết, và audit trail đủ chi tiết để debug khi có sự cố. Bài viết này tôi sẽ chia sẻ toàn bộ quy trình từ setup môi trường đến interpret kết quả.

So sánh nhanh: HolySheep vs API chính thức vs Dịch vụ Relay

Tiêu chí HolySheep AI API chính thức (OpenAI/Anthropic) Dịch vụ Relay khác
Tỷ giá ¥1 = $1 (tiết kiệm 85%+) Giá gốc USD Biến đổi, thường cao hơn 20-50%
Thanh toán WeChat, Alipay, Visa Thẻ quốc tế (khó ở Trung Quốc) Hạn chế phương thức
Độ trễ P50 <50ms (route nội địa) 150-300ms (quốc tế) 80-200ms
Rate Limit Tùy gói, linh hoạt Cứng theo tier Theo gói
Retry & Fallback Tích hợp sẵn Phải tự implement Thường không có
Audit Trail Đầy đủ, export được Chỉ usage dashboard Hạn chế
Tín dụng miễn phí Có khi đăng ký $5-18 trial Ít khi có
GPT-4.1 (8M ctx) $8/MTok $8/MTok $10-15/MTok
Claude Sonnet 4.5 $15/MTok $15/MTok $18-22/MTok
Gemini 2.5 Flash $2.50/MTok $2.50/MTok $3-5/MTok
DeepSeek V3.2 $0.42/MTok Không có $0.60-1/MTok

Mục lục

1. Setup môi trường test

Trước khi bắt đầu, bạn cần chuẩn bị môi trường. Tôi khuyến nghị tách biệt môi trường test khỏi production bằng API key riêng.

# Cài đặt dependencies cần thiết
pip install aiohttp asyncio-limiter prometheus-client httpx pytest pytest-asyncio

Tạo file cấu hình test config.py

import os HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1" HOLYSHEEP_API_KEY = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")

Cấu hình test

TEST_CONCURRENT_USERS = [1, 5, 10, 25, 50, 100] TEST_DURATION_SECONDS = 30 RETRY_MAX_ATTEMPTS = 3 RETRY_BACKOFF_FACTOR = 0.5 # exponential backoff factor

Model fallback chain (từ cao xuống thấp)

FALLBACK_CHAIN = [ "gpt-4.1", "gpt-4o-mini", "claude-sonnet-4.5", "gemini-2.5-flash", "deepseek-v3.2" ]

Bạn có thể đăng ký tại đây để nhận API key test miễn phí với tín dụng dùng thử.

2. Test Concurrency Limiting — Chặn request trước khi quá tải

Đây là phần quan trọng nhất. Nếu gateway không có concurrency limit đúng cách, một spike đột ngột sẽ làm toàn bộ hệ thống chết. Tôi đã từng để một team deploy mà không có rate limit, kết quả là 10K request trong 5 giây làm toàn bộ queue overflow.

# stress_test_concurrency.py
import asyncio
import aiohttp
import time
from collections import defaultdict
import statistics

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

class ConcurrencyTest:
    def __init__(self, max_concurrent: int, requests_per_user: int):
        self.max_concurrent = max_concurrent
        self.requests_per_user = requests_per_user
        self.results = []
        self.semaphore = asyncio.Semaphore(max_concurrent)
    
    async def single_request(self, session: aiohttp.ClientSession, user_id: int):
        """Một request đơn lẻ với semaphore để kiểm soát concurrency"""
        async with self.semaphore:
            start = time.time()
            try:
                async with session.post(
                    f"{BASE_URL}/chat/completions",
                    headers={
                        "Authorization": f"Bearer {API_KEY}",
                        "Content-Type": "application/json"
                    },
                    json={
                        "model": "gpt-4.1",
                        "messages": [{"role": "user", "content": "Say 'test'"}],
                        "max_tokens": 10
                    },
                    timeout=aiohttp.ClientTimeout(total=30)
                ) as resp:
                    latency = (time.time() - start) * 1000
                    status = resp.status
                    await resp.text()
                    self.results.append({
                        "user_id": user_id,
                        "latency_ms": latency,
                        "status": status,
                        "success": status == 200
                    })
            except Exception as e:
                latency = (time.time() - start) * 1000
                self.results.append({
                    "user_id": user_id,
                    "latency_ms": latency,
                    "status": 0,
                    "success": False,
                    "error": str(e)
                })
    
    async def run(self, duration_seconds: int = 30):
        """Chạy test trong khoảng thời gian nhất định"""
        connector = aiohttp.TCPConnector(limit=self.max_concurrent * 2)
        async with aiohttp.ClientSession(connector=connector) as session:
            tasks = []
            start_time = time.time()
            user_id = 0
            
            # Tạo tasks liên tục trong duration
            while time.time() - start_time < duration_seconds:
                if len(asyncio.all_tasks()) < self.max_concurrent * 2:
                    task = asyncio.create_task(self.single_request(session, user_id))
                    tasks.append(task)
                    user_id += 1
                    await asyncio.sleep(0.05)  # 50ms delay giữa mỗi request
            
            await asyncio.gather(*tasks, return_exceptions=True)
        
        return self.generate_report()
    
    def generate_report(self):
        successful = [r for r in self.results if r["success"]]
        failed = [r for r in self.results if not r["success"]]
        latencies = [r["latency_ms"] for r in successful]
        
        return {
            "total_requests": len(self.results),
            "successful": len(successful),
            "failed": len(failed),
            "success_rate": len(successful) / len(self.results) * 100,
            "avg_latency_ms": statistics.mean(latencies) if latencies else 0,
            "p50_latency_ms": statistics.median(latencies) if latencies else 0,
            "p95_latency_ms": sorted(latencies)[int(len(latencies) * 0.95)] if latencies else 0,
            "p99_latency_ms": sorted(latencies)[int(len(latencies) * 0.99)] if latencies else 0,
            "max_latency_ms": max(latencies) if latencies else 0,
            "status_codes": defaultdict(int, {r["status"]: 1 for r in self.results})
        }

async def main():
    print("=" * 60)
    print("CONCURRENCY LIMIT STRESS TEST - HolySheep AI Gateway")
    print("=" * 60)
    
    for max_concurrent in [5, 25, 50, 100]:
        print(f"\n[Testing max_concurrent={max_concurrent}]")
        test = ConcurrencyTest(max_concurrent=max_concurrent, requests_per_user=5)
        report = await test.run(duration_seconds=30)
        
        print(f"  Total: {report['total_requests']} | Success: {report['successful']} | Failed: {report['failed']}")
        print(f"  Success Rate: {report['success_rate']:.1f}%")
        print(f"  Latency P50: {report['p50_latency_ms']:.1f}ms")
        print(f"  Latency P95: {report['p95_latency_ms']:.1f}ms")
        print(f"  Latency P99: {report['p99_latency_ms']:.1f}ms")
        print(f"  Avg Latency: {report['avg_latency_ms']:.1f}ms")

if __name__ == "__main__":
    asyncio.run(main())

3. Test Retry Logic với Exponential Backoff

Khi một request thất bại, bạn cần retry đúng cách. Quan trọng: retry phải có exponential backoff, không phải fixed delay. Tôi đã gặp vô số trường hợp retry liên tục không backoff làm tăng load lên gấp 10 lần khi hệ thống có vấn đề.

# test_retry_with_backoff.py
import asyncio
import aiohttp
import time
import random

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

class RetryTest:
    """Test retry logic với exponential backoff thông minh"""
    
    def __init__(self, max_attempts: int = 3, backoff_base: float = 0.5,
                 jitter: bool = True, max_backoff: float = 10.0):
        self.max_attempts = max_attempts
        self.backoff_base = backoff_base
        self.jitter = jitter
        self.max_backoff = max_backoff
        self.retry_log = []
        self.success_with_retry = 0
        self.final_failures = 0
    
    def calculate_backoff(self, attempt: int) -> float:
        """Tính toán backoff time với jitter để tránh thundering herd"""
        backoff = min(self.backoff_base * (2 ** attempt), self.max_backoff)
        if self.jitter:
            backoff = backoff * (0.5 + random.random())  # 50%-150% của backoff
        return backoff
    
    async def request_with_retry(self, session: aiohttp.ClientSession, 
                                  simulate_failure_rate: float = 0.3):
        """Request với retry logic - mô phỏng failure để test"""
        last_error = None
        
        for attempt in range(self.max_attempts):
            request_start = time.time()
            should_simulate_fail = (attempt < self.max_attempts - 1 and 
                                    random.random() < simulate_failure_rate)
            
            try:
                if should_simulate_fail:
                    # Mô phỏng lỗi 429 hoặc 500 để test retry
                    error_status = random.choice([429, 500, 502, 503])
                    await asyncio.sleep(0.1)  # Simulate network
                    raise aiohttp.ClientResponseError(
                        request_info=None,
                        history=None,
                        status=error_status,
                        message=f"Simulated {error_status} Error"
                    )
                
                async with session.post(
                    f"{BASE_URL}/chat/completions",
                    headers={
                        "Authorization": f"Bearer {API_KEY}",
                        "Content-Type": "application/json"
                    },
                    json={
                        "model": "gpt-4o-mini",
                        "messages": [{"role": "user", "content": "Test retry"}],
                        "max_tokens": 5
                    },
                    timeout=aiohttp.ClientTimeout(total=30)
                ) as resp:
                    latency = (time.time() - request_start) * 1000
                    text = await resp.text()
                    
                    if resp.status == 200:
                        self.retry_log.append({
                            "attempt": attempt + 1,
                            "success": True,
                            "latency_ms": latency,
                            "status": 200
                        })
                        if attempt > 0:
                            self.success_with_retry += 1
                        return {"success": True, "attempts": attempt + 1}
                    else:
                        last_error = f"HTTP {resp.status}"
                        self.retry_log.append({
                            "attempt": attempt + 1,
                            "success": False,
                            "latency_ms": latency,
                            "status": resp.status
                        })
                        if attempt < self.max_attempts - 1:
                            backoff = self.calculate_backoff(attempt)
                            await asyncio.sleep(backoff)
                        continue
                            
            except aiohttp.ClientError as e:
                latency = (time.time() - request_start) * 1000
                last_error = str(e)
                self.retry_log.append({
                    "attempt": attempt + 1,
                    "success": False,
                    "latency_ms": latency,
                    "error": str(e)
                })
                if attempt < self.max_attempts - 1:
                    backoff = self.calculate_backoff(attempt)
                    print(f"  Attempt {attempt + 1} failed, retrying in {backoff:.2f}s...")
                    await asyncio.sleep(backoff)
        
        self.final_failures += 1
        return {"success": False, "error": last_error, "attempts": self.max_attempts}
    
    async def run_batch(self, num_requests: int = 50, 
                        simulate_failure_rate: float = 0.3):
        connector = aiohttp.TCPConnector(limit=20)
        async with aiohttp.ClientSession(connector=connector) as session:
            tasks = [
                self.request_with_retry(session, simulate_failure_rate)
                for _ in range(num_requests)
            ]
            results = await asyncio.gather(*tasks)
        
        return self.generate_report(results)
    
    def generate_report(self, results):
        successful = [r for r in results if r["success"]]
        retries = [e for e in self.retry_log if e["attempt"] > 1]
        
        print(f"\n{'='*50}")
        print(f"RETRY STRESS TEST REPORT")
        print(f"{'='*50}")
        print(f"Total Requests: {len(results)}")
        print(f"Successful: {len(successful)}")
        print(f"Success with Retry: {self.success_with_retry}")
        print(f"Final Failures: {self.final_failures}")
        print(f"Total Retry Attempts: {len(retries)}")
        
        if self.retry_log:
            attempts_dist = {}
            for entry in self.retry_log:
                key = entry["attempt"]
                attempts_dist[key] = attempts_dist.get(key, 0) + 1
            print(f"\nAttempts Distribution:")
            for attempt, count in sorted(attempts_dist.items()):
                print(f"  Attempt {attempt}: {count} requests")

async def main():
    test = RetryTest(max_attempts=3, backoff_base=0.5, jitter=True)
    await test.run_batch(num_requests=50, simulate_failure_rate=0.3)

if __name__ == "__main__":
    asyncio.run(main())

4. Test Model Fallback Chain — Không bao giờ để hệ thống chết

Model fallback là cứu cánh khi model chính quá tải hoặc gặp lỗi. Chain của tôi: GPT-4.1 → GPT-4o-mini → Claude Sonnet 4.5 → Gemini 2.5 Flash → DeepSeek V3.2. Mỗi bước fallback đều phải được log để theo dõi chất lượng phục vụ.

# test_model_fallback.py
import asyncio
import aiohttp
import time
from typing import List, Optional, Dict
from dataclasses import dataclass
from collections import Counter

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

@dataclass
class FallbackResult:
    original_model: str
    fallback_chain: List[str]
    final_model_used: str
    success: bool
    total_latency_ms: float
    fallback_count: int
    error: Optional[str] = None

class ModelFallbackTest:
    """Test model fallback chain đầy đủ"""
    
    def __init__(self, fallback_chain: List[str]):
        self.fallback_chain = fallback_chain
        self.results: List[FallbackResult] = []
        self.fallback_counter = Counter()
    
    async def request_with_fallback(
        self, session: aiohttp.ClientSession, 
        original_model: str, 
        test_failure_scenario: bool = False
    ) -> FallbackResult:
        """Request với fallback chain đầy đủ"""
        total_start = time.time()
        models_to_try = self.fallback_chain.copy()
        
        if original_model not in models_to_try:
            models_to_try.insert(0, original_model)
        
        fallback_count = 0
        last_error = None
        
        for model in models_to_try:
            request_start = time.time()
            
            # Mô phỏng failure cho model đầu tiên để test fallback
            if test_failure_scenario and model == models_to_try[0] and fallback_count == 0:
                await asyncio.sleep(0.05)
                last_error = "Simulated model unavailability"
                fallback_count += 1
                self.fallback_counter[f"{models_to_try[0]}->{models_to_try[1]}"] += 1
                continue
            
            try:
                async with session.post(
                    f"{BASE_URL}/chat/completions",
                    headers={
                        "Authorization": f"Bearer {API_KEY}",
                        "Content-Type": "application/json"
                    },
                    json={
                        "model": model,
                        "messages": [{"role": "user", "content": "Fallback test"}],
                        "max_tokens": 10
                    },
                    timeout=aiohttp.ClientTimeout(total=15)
                ) as resp:
                    latency = time.time() - request_start
                    
                    if resp.status == 200:
                        await resp.text()
                        total_latency = (time.time() - total_start) * 1000
                        result = FallbackResult(
                            original_model=original_model,
                            fallback_chain=models_to_try[:models_to_try.index(model) + 1],
                            final_model_used=model,
                            success=True,
                            total_latency_ms=total_latency,
                            fallback_count=fallback_count
                        )
                        self.results.append(result)
                        return result
                    elif resp.status == 429:
                        last_error = f"429 Rate Limited on {model}"
                        if model != models_to_try[-1]:
                            fallback_count += 1
                            self.fallback_counter[f"{model}->{models_to_try[models_to_try.index(model)+1]}"] += 1
                    elif resp.status >= 500:
                        last_error = f"{resp.status} Server Error on {model}"
                        if model != models_to_try[-1]:
                            fallback_count += 1
                            self.fallback_counter[f"{model}->{models_to_try[models_to_try.index(model)+1]}"] += 1
                    else:
                        last_error = f"{resp.status} on {model}"
                        break
                        
            except asyncio.TimeoutError:
                last_error = f"Timeout on {model}"
                if model != models_to_try[-1]:
                    fallback_count += 1
                    self.fallback_counter[f"{model}->{models_to_try[models_to_try.index(model)+1]}"] += 1
            except Exception as e:
                last_error = f"{type(e).__name__} on {model}"
                if model != models_to_try[-1]:
                    fallback_count += 1
                    self.fallback_counter[f"{model}->{models_to_try[models_to_try.index(model)+1]}"] += 1
        
        total_latency = (time.time() - total_start) * 1000
        result = FallbackResult(
            original_model=original_model,
            fallback_chain=models_to_try,
            final_model_used="NONE",
            success=False,
            total_latency_ms=total_latency,
            fallback_count=fallback_count,
            error=last_error
        )
        self.results.append(result)
        return result
    
    async def run_comprehensive_test(self, requests_per_scenario: int = 20):
        connector = aiohttp.TCPConnector(limit=30)
        async with aiohttp.ClientSession(connector=connector) as session:
            # Scenario 1: Normal traffic (no forced failures)
            print("\n[Scenario 1: Normal Traffic]")
            tasks = [
                self.request_with_fallback(session, "gpt-4.1", test_failure_scenario=False)
                for _ in range(requests_per_scenario)
            ]
            results = await asyncio.gather(*tasks)
            
            # Scenario 2: Forced fallback (model unavailability)
            print("[Scenario 2: Model Unavailability - Testing Fallback]")
            tasks = [
                self.request_with_fallback(session, "gpt-4.1", test_failure_scenario=True)
                for _ in range(requests_per_scenario)
            ]
            results = await asyncio.gather(*tasks)
        
        self.print_report()
    
    def print_report(self):
        print(f"\n{'='*60}")
        print(f"MODEL FALLBACK STRESS TEST REPORT")
        print(f"{'='*60}")
        
        total = len(self.results)
        successful = sum(1 for r in self.results if r.success)
        
        print(f"Total Requests: {total}")
        print(f"Successful: {successful} ({successful/total*100:.1f}%)")
        print(f"Failed: {total - successful}")
        
        print(f"\nFallback Statistics:")
        for transition, count in self.fallback_counter.most_common():
            print(f"  {transition}: {count} times")
        
        latencies = [r.total_latency_ms for r in self.results if r.success]
        if latencies:
            latencies.sort()
            print(f"\nLatency Distribution:")
            print(f"  P50: {latencies[int(len(latencies)*0.50)]:.1f}ms")
            print(f"  P95: {latencies[int(len(latencies)*0.95)]:.1f}ms")
            print(f"  P99: {latencies[int(len(latencies)*0.99)]:.1f}ms")
        
        # Model usage breakdown
        model_usage = Counter(r.final_model_used for r in self.results if r.success)
        print(f"\nModel Usage Breakdown:")
        for model, count in model_usage.most_common():
            print(f"  {model}: {count} ({count/successful*100:.1f}%)")

async def main():
    # Định nghĩa fallback chain theo chi phí giảm dần
    fallback_chain = [
        "gpt-4.1",        # $8/MTok - đắt nhất, thử trước
        "gpt-4o-mini",    # fallback 1
        "claude-sonnet-4.5",  # fallback 2
        "gemini-2.5-flash",    # fallback 3 - $2.50/MTok
        "deepseek-v3.2"        # fallback cuối - $0.42/MTok (rẻ nhất)
    ]
    
    test = ModelFallbackTest(fallback_chain=fallback_chain)
    await test.run_comprehensive_test(requests_per_scenario=20)

if __name__ == "__main__":
    asyncio.run(main())

5. Test Audit Trail — Logging chi tiết cho production

Trong môi trường enterprise, audit trail không phải là tùy chọn. Bạn cần biết: ai gọi model nào, bao lâu, kết quả thế nào, và quan trọng nhất — khi có sự cố, bạn có đủ data để debug trong 5 phút không.

# audit_logger.py
import json
import time
import asyncio
from datetime import datetime
from typing import Optional, Dict, Any, List
from dataclasses import dataclass, asdict, field
from enum import Enum
import aiohttp

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

class RequestStatus(Enum):
    SUCCESS = "success"
    RETRY = "retry"
    FALLBACK = "fallback"
    FAILED = "failed"
    TIMEOUT = "timeout"
    RATE_LIMITED = "rate_limited"

@dataclass
class AuditLogEntry:
    """Một entry log cho mỗi request"""
    request_id: str
    timestamp: str
    user_id: Optional[str]
    model: str
    status: str
    latency_ms: float
    prompt_tokens: int = 0
    completion_tokens: int = 0
    total_tokens: int = 0
    cost_usd: float = 0.0
    retry_count: int = 0
    fallback_chain: List[str] = field(default_factory=list)
    error_message: Optional[str] = None
    status_code: Optional[int] = None
    request_metadata: Dict[str, Any] = field(default_factory=dict)

class AuditLogger:
    """
    Audit logger cho enterprise - lưu trữ local + có thể push lên centralized system
    """
    
    def __init__(self, log_dir: str = "./audit_logs"):
        self.log_dir = log_dir
        self.entries: List[AuditLogEntry] = []
        self.request_counter = 0
    
    def generate_request_id(self) -> str:
        self.request_counter += 1
        return f"req_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{self.request_counter:06d}"
    
    def log_request(self, entry: AuditLogEntry):
        """Ghi một entry vào log"""
        self.entries.append(entry)
        
        # Xuất ra JSON line format (có thể redirect sang file hoặc ELK stack)
        log_line = json.dumps(asdict(entry), ensure_ascii=False, indent=2)
        print(f"[AUDIT] {log_line}")
    
    async def send_to_audit_service(self, entry: AuditLogEntry):
        """
        Gửi log entry lên centralized audit service
        Thay thế bằng endpoint thực tế của bạn (ELK, Splunk, etc.)
        """
        # Ví dụ: gửi lên audit service
        # await self.http_client.post("https://audit.internal/log", json=asdict(entry))
        pass
    
    def export_summary(self) -> Dict[str, Any]:
        """Xuất summary report"""
        total = len(self.entries)
        if total == 0:
            return {"error": "No entries"}
        
        status_counts = {}
        model_costs = {}
        model_latencies = {}
        
        for entry in self.entries:
            status_counts[entry.status] = status_counts.get(entry.status, 0) + 1
            model_costs[entry.model] = model_costs.get(entry.model, 0) + entry.cost_usd
            if entry.model not in model_latencies:
                model_latencies[entry.model] = []
            model_latencies[entry.model].append(entry.latency_ms)
        
        total_cost = sum(model_costs.values())
        avg_latencies = {
            model: sum(lats) / len(lats) 
            for model, lats in model_latencies.items()
        }
        
        return {
            "total_requests": total,
            "status_breakdown": status_counts,
            "cost_by_model": model_costs,
            "total_cost_usd": total_cost,
            "avg_latency_by_model": avg_latencies,
            "total_prompt_tokens": sum(e.prompt_tokens for e in self.entries),
            "total_completion_tokens": sum(e.completion_tokens for e in self.entries),
            "total_tokens": sum(e.total_tokens for e in self.entries)
        }

Ví dụ sử dụng audit logger

async def example_with_audit(): logger = AuditLogger() for i in range(5): request_id = logger.generate_request_id() start = time.time() async with aiohttp.ClientSession() as session: try: async with session.post( f"{BASE_URL}/chat/completions", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" }, json={ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Audit test"}], "max_tokens": 20 } ) as resp: latency = (time.time() - start) * 1000 if resp.status == 200: data = await resp.json() usage = data.get("usage", {}) entry = AuditLogEntry( request_id=request_id, timestamp=datetime.now().isoformat(), user_id=f"user_{i}", model="gpt-4o-mini", status=RequestStatus.SUCCESS.value, latency_ms=latency, prompt_tokens=usage.get("prompt_tokens", 0), completion_tokens=usage.get("completion_tokens", 0), total_tokens=usage.get("total_tokens", 0), cost_usd=usage.get("total_tokens", 0) * 8 / 1_000_000, status_code=200, request_metadata={"stream": False} ) else: entry = AuditLogEntry( request_id=request_id, timestamp=datetime.now().isoformat(), user_id=f"user_{i}", model="gpt-4o-mini", status=RequestStatus.FAILED.value, latency_ms=latency, status_code=resp.status, error_message=f"HTTP {resp.status}" ) logger.log_request(entry) except asyncio.TimeoutError: entry = AuditLogEntry( request_id=request_id, timestamp=datetime.now().isoformat(), user_id=f"user_{