import json import logging import time import uuid import os from datetime import datetime from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint from app.services.log_config import LOG_R_Q_DIR, LOG_FILENAME_FORMAT, LOG_DATE_FORMAT, encrypt_data logger = logging.getLogger("videogen") os.makedirs(LOG_R_Q_DIR, exist_ok=True) def get_today_log_file() -> str: today = datetime.now().strftime(LOG_DATE_FORMAT) filename = LOG_FILENAME_FORMAT.format(date=today) return os.path.join(LOG_R_Q_DIR, filename) class RequestLoggingMiddleware(BaseHTTPMiddleware): async def dispatch( self, request: Request, call_next: RequestResponseEndpoint ) -> Response: path = request.url.path if path.startswith("/static/") or path.startswith("/videos/") or path.startswith("/images/"): return await call_next(request) if path in ("/internal/health", "/internal/api-docs", "/openapi.json", "/internal/api-redoc","internal/decrypt-data"): return await call_next(request) #GET请求不记录日志 if request.method == "GET": return await call_next(request) request_id = str(uuid.uuid4())[:8] start = time.perf_counter() request_body = {} try: if request.method in ("POST", "PUT", "PATCH"): body = await request.json() request_body = body except Exception: pass response = await call_next(request) duration_ms = round((time.perf_counter() - start) * 1000, 1) log_entry = { "timestamp": datetime.now().isoformat(), "request_id": request_id, "method": request.method, "path": request.url.path, "query_params": dict(request.query_params), "request_body": encrypt_data(request_body, True) if request_body else "", "status": response.status_code, "duration_ms": duration_ms, "ip": request.client.host if request.client else "-", "user_agent": request.headers.get("user-agent", "-"), } log_file = get_today_log_file() with open(log_file, "a", encoding="utf-8") as f: f.write(json.dumps(log_entry, ensure_ascii=False) + "\n") response.headers["X-Request-ID"] = request_id return response