Coverage for .venv/lib/python3.13/site-packages/litellm/proxy/middleware/in_flight_requests_middleware.py: 88%
40 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
1"""
2Tracks the number of HTTP requests currently in-flight on this uvicorn worker.
4Used by /health/backlog to expose per-pod queue depth, and emitted as the
5Prometheus gauge `litellm_in_flight_requests`.
6"""
8import os
9from typing import Any, Final
11from starlette.types import ASGIApp, Receive, Scope, Send
14class InFlightRequestsMiddleware:
15 """
16 ASGI middleware that increments a counter when a request arrives and
17 decrements it when the response is sent (or an error occurs).
19 The counter is class-level and therefore scoped to a single uvicorn worker
20 process — exactly the per-pod granularity we want.
22 Also updates the `litellm_in_flight_requests` Prometheus gauge if
23 prometheus_client is installed. The gauge is lazily initialised on the
24 first request so that PROMETHEUS_MULTIPROC_DIR is already set by the time
25 we register the metric. Initialisation is attempted only once — if
26 prometheus_client is absent the class remembers and never retries.
27 """
29 _in_flight: int = 0
30 _gauge: Any | None = None
31 _gauge_init_attempted: bool = False
33 def __init__(self, app: ASGIApp) -> None:
34 self.app = app
36 async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
37 if scope["type"] != "http":
38 await self.app(scope, receive, send)
39 return
41 InFlightRequestsMiddleware._in_flight += 1
42 gauge: Final = InFlightRequestsMiddleware._get_gauge()
43 if gauge is not None: 43 ↛ 45line 43 didn't jump to line 45 because the condition on line 43 was always true
44 gauge.inc()
45 try:
46 await self.app(scope, receive, send)
47 finally:
48 InFlightRequestsMiddleware._in_flight -= 1
49 if gauge is not None: 49 ↛ exitline 49 didn't return from function '__call__' because the condition on line 49 was always true
50 gauge.dec()
52 @staticmethod
53 def get_count() -> int:
54 """Return the number of HTTP requests currently in-flight."""
55 return InFlightRequestsMiddleware._in_flight
57 @staticmethod
58 def _get_gauge() -> Any | None:
59 if InFlightRequestsMiddleware._gauge_init_attempted:
60 return InFlightRequestsMiddleware._gauge
61 InFlightRequestsMiddleware._gauge_init_attempted = True
62 try:
63 from prometheus_client import Gauge
65 if "PROMETHEUS_MULTIPROC_DIR" in os.environ: 65 ↛ 67line 65 didn't jump to line 67 because the condition on line 65 was never true
66 # livesum aggregates across all worker processes in the scrape response
67 InFlightRequestsMiddleware._gauge = Gauge(
68 "litellm_in_flight_requests",
69 "Number of HTTP requests currently in-flight on this uvicorn worker",
70 multiprocess_mode="livesum",
71 )
72 else:
73 InFlightRequestsMiddleware._gauge = Gauge(
74 "litellm_in_flight_requests",
75 "Number of HTTP requests currently in-flight on this uvicorn worker",
76 )
77 except Exception:
78 InFlightRequestsMiddleware._gauge = None
79 return InFlightRequestsMiddleware._gauge
82def get_in_flight_requests() -> int:
83 """Module-level convenience wrapper used by the /health/backlog endpoint."""
84 return InFlightRequestsMiddleware.get_count()