|
""" |
|
Request middleware for logging, metrics, and request tracking |
|
""" |
|
|
|
import time |
|
from fastapi import Request |
|
from ..core.logging import get_logger |
|
from ..core.metrics import REQUEST_COUNT, REQUEST_DURATION, ERROR_COUNT |
|
from ..utils.helpers import generate_request_id |
|
|
|
logger = get_logger() |
|
|
|
|
|
async def request_middleware(request: Request, call_next): |
|
"""Middleware for request tracking, metrics, and logging""" |
|
start_time = time.time() |
|
request_id = generate_request_id() |
|
|
|
|
|
request.state.request_id = request_id |
|
|
|
|
|
logger.info( |
|
"request_started", |
|
request_id=request_id, |
|
method=request.method, |
|
url=str(request.url), |
|
client_ip=request.client.host if request.client else "unknown", |
|
user_agent=request.headers.get("user-agent", "unknown") |
|
) |
|
|
|
try: |
|
response = await call_next(request) |
|
|
|
|
|
duration = time.time() - start_time |
|
|
|
|
|
REQUEST_COUNT.labels( |
|
method=request.method, |
|
endpoint=request.url.path, |
|
status=response.status_code |
|
).inc() |
|
|
|
REQUEST_DURATION.labels( |
|
method=request.method, |
|
endpoint=request.url.path |
|
).observe(duration) |
|
|
|
|
|
logger.info( |
|
"request_completed", |
|
request_id=request_id, |
|
status_code=response.status_code, |
|
duration=duration |
|
) |
|
|
|
|
|
response.headers["X-Request-ID"] = request_id |
|
response.headers["X-Response-Time"] = f"{duration:.3f}s" |
|
response.headers["X-Response-Time-Ms"] = f"{duration * 1000:.1f}" |
|
|
|
return response |
|
|
|
except Exception as e: |
|
duration = time.time() - start_time |
|
|
|
|
|
ERROR_COUNT.labels(error_type=type(e).__name__).inc() |
|
|
|
|
|
logger.error( |
|
"request_failed", |
|
request_id=request_id, |
|
error=str(e), |
|
error_type=type(e).__name__, |
|
duration=duration |
|
) |
|
|
|
raise |
|
|