mirror of
https://github.com/aljazceru/enclava.git
synced 2025-12-17 07:24:34 +01:00
debugging
This commit is contained in:
115
backend/app/middleware/debugging.py
Normal file
115
backend/app/middleware/debugging.py
Normal file
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
Debugging middleware for detailed request/response logging
|
||||
"""
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional
|
||||
from fastapi import Request, Response
|
||||
from fastapi.responses import JSONResponse
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from uuid import uuid4
|
||||
|
||||
from app.core.logging import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class DebuggingMiddleware(BaseHTTPMiddleware):
|
||||
"""Middleware to log detailed request/response information for debugging"""
|
||||
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
# Generate unique request ID for tracing
|
||||
request_id = str(uuid4())
|
||||
|
||||
# Skip debugging for health checks and static files
|
||||
if request.url.path in ["/health", "/docs", "/redoc", "/openapi.json"] or \
|
||||
request.url.path.startswith("/static"):
|
||||
return await call_next(request)
|
||||
|
||||
# Log request details
|
||||
request_body = None
|
||||
if request.method in ["POST", "PUT", "PATCH"]:
|
||||
try:
|
||||
# Clone request body to avoid consuming it
|
||||
body_bytes = await request.body()
|
||||
if body_bytes:
|
||||
try:
|
||||
request_body = json.loads(body_bytes)
|
||||
except json.JSONDecodeError:
|
||||
request_body = body_bytes.decode('utf-8', errors='replace')
|
||||
# Restore body for downstream processing
|
||||
request._body = body_bytes
|
||||
except Exception:
|
||||
request_body = "[Failed to read request body]"
|
||||
|
||||
# Extract headers we care about
|
||||
headers_to_log = {
|
||||
"authorization": request.headers.get("Authorization", "")[:50] + "..." if
|
||||
request.headers.get("Authorization") else None,
|
||||
"content-type": request.headers.get("Content-Type"),
|
||||
"user-agent": request.headers.get("User-Agent"),
|
||||
"x-forwarded-for": request.headers.get("X-Forwarded-For"),
|
||||
"x-real-ip": request.headers.get("X-Real-IP"),
|
||||
}
|
||||
|
||||
# Log request
|
||||
logger.info("=== API REQUEST DEBUG ===", extra={
|
||||
"request_id": request_id,
|
||||
"method": request.method,
|
||||
"url": str(request.url),
|
||||
"path": request.url.path,
|
||||
"query_params": dict(request.query_params),
|
||||
"headers": {k: v for k, v in headers_to_log.items() if v is not None},
|
||||
"body": request_body,
|
||||
"client_ip": request.client.host if request.client else None,
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
})
|
||||
|
||||
# Process the request
|
||||
start_time = time.time()
|
||||
response = None
|
||||
response_body = None
|
||||
|
||||
try:
|
||||
response = await call_next(request)
|
||||
|
||||
# Capture response body for successful JSON responses
|
||||
if response.status_code < 400 and isinstance(response, JSONResponse):
|
||||
try:
|
||||
response_body = json.loads(response.body.decode('utf-8'))
|
||||
except:
|
||||
response_body = "[Failed to decode response body]"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Request processing failed: {str(e)}", extra={
|
||||
"request_id": request_id,
|
||||
"error": str(e),
|
||||
"error_type": type(e).__name__
|
||||
})
|
||||
response = JSONResponse(
|
||||
status_code=500,
|
||||
content={"error": "INTERNAL_ERROR", "message": "Internal server error"}
|
||||
)
|
||||
|
||||
# Calculate timing
|
||||
end_time = time.time()
|
||||
duration = (end_time - start_time) * 1000 # milliseconds
|
||||
|
||||
# Log response
|
||||
logger.info("=== API RESPONSE DEBUG ===", extra={
|
||||
"request_id": request_id,
|
||||
"status_code": response.status_code,
|
||||
"duration_ms": round(duration, 2),
|
||||
"response_body": response_body,
|
||||
"response_headers": dict(response.headers),
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
})
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def setup_debugging_middleware(app):
|
||||
"""Add debugging middleware to the FastAPI app"""
|
||||
app.add_middleware(DebuggingMiddleware)
|
||||
logger.info("Debugging middleware configured")
|
||||
Reference in New Issue
Block a user