Files
remnawave-bedolaga-telegram…/app/webapi/middleware.py
Fringg 25e8c9f8fc fix: use sync context manager for structlog bound_contextvars
bound_contextvars() returns a sync _GeneratorContextManager, not async.
Using `async with` caused TypeError crashing all web API requests.
2026-02-16 09:23:22 +03:00

41 lines
1.7 KiB
Python

from __future__ import annotations
from time import monotonic
import structlog
from sqlalchemy.exc import InterfaceError, OperationalError
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.requests import Request
from starlette.responses import JSONResponse, Response
from structlog.contextvars import bound_contextvars
logger = structlog.get_logger('web_api')
class RequestLoggingMiddleware(BaseHTTPMiddleware):
"""Логирование входящих запросов в административный API."""
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
with bound_contextvars(http_method=request.method, http_path=request.url.path):
start = monotonic()
response: Response | None = None
try:
response = await call_next(request)
return response
except (TimeoutError, ConnectionRefusedError, OSError, OperationalError, InterfaceError) as e:
logger.error(
'Database connection error on', method=request.method, path=request.url.path, e=str(e)[:200]
)
response = JSONResponse(
status_code=503,
content={'detail': 'Service temporarily unavailable. Please try again later.'},
)
return response
finally:
duration_ms = (monotonic() - start) * 1000
status = response.status_code if response else 'error'
logger.debug(
'-> (ms)', method=request.method, path=request.url.path, status=status, duration_ms=duration_ms
)