@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / e8d3e22c88
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Fix included router missing path for `FastAPI >=0.137` (#45629)

Signed-off-by: Roger Wang <hey@rogerw.io> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

Roger Wang committed Jun 14, 2026 at 21:28 UTC e8d3e22c884e95a7499ffcf37fa932751f0780df
1 file changed +38 -1
vllm/entrypoints/serve/instrumentator/metrics.py
+38 -1
@@ -7,11 +7,48 @@ import regex as re
7 from fastapi import FastAPI, Response
8 from prometheus_client import make_asgi_app
9 from prometheus_fastapi_instrumentator import Instrumentator
10 -from starlette.routing import Mount
10 +from prometheus_fastapi_instrumentator import routing as _pfi_routing
11 +from starlette.routing import Match, Mount
12 +from starlette.types import Scope
13
14 from vllm.v1.metrics.prometheus import get_prometheus_registry
15
16
17 +def _patch_instrumentator_route_walk() -> None:
18 + """Make prometheus-fastapi-instrumentator's route walk tolerate routes
19 + without a ``.path``.
20 +
21 + FastAPI >= 0.137 stores lazy ``_IncludedRouter`` objects in ``app.routes``;
22 + these are ``BaseRoute`` subclasses with no ``.path`` attribute. The
23 + instrumentator's ``_get_route_name`` (up to 8.0.0) reads ``route.path``
24 + unconditionally, so every request raises ``AttributeError`` in the metrics
25 + middleware and the server returns 500 (e.g. ``/health`` never goes ready).
26 + Skip path-less routes; this only affects the metric handler label, not
27 + request routing. Idempotent.
28 + """
29 +
30 + def _get_route_name(scope: Scope, routes, route_name=None):
31 + for route in routes:
32 + if getattr(route, "path", None) is None:
33 + continue
34 + match, child_scope = route.matches(scope)
35 + if match == Match.FULL:
36 + route_name = route.path
37 + child_scope = {**scope, **child_scope}
38 + if isinstance(route, Mount) and route.routes:
39 + child = _get_route_name(child_scope, route.routes, route_name)
40 + route_name = None if child is None else route_name + child
41 + return route_name
42 + elif match == Match.PARTIAL and route_name is None:
43 + route_name = route.path
44 + return None
45 +
46 + _pfi_routing._get_route_name = _get_route_name
47 +
48 +
49 +_patch_instrumentator_route_walk()
50 +
51 +
52 class PrometheusResponse(Response):
53 media_type = prometheus_client.CONTENT_TYPE_LATEST
54