From 603f91840c253c5a5387c9c765da831ec2bd9752 Mon Sep 17 00:00:00 2001 From: Sam Shleifer Date: Fri, 17 Jul 2026 04:45:08 +0000 Subject: [PATCH 1/2] metrics: allow extra labels on HTTP request/response Prometheus metrics Add an optional `extra_labels: Optional[Dict[str, str]]` parameter to `add_prometheus_track_response_middleware` that is merged into the label set of the sglang:http_requests_total / http_responses_total / http_requests_active metrics (and their inc/dec calls). This lets a deployment attach identifying labels (e.g. job id, replica id) to HTTP metrics so they can be filtered/joined the same way as the scheduler metrics, without a label-join. Defaults to no extra labels, so existing behavior is unchanged. --- python/sglang/srt/utils/common.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/python/sglang/srt/utils/common.py b/python/sglang/srt/utils/common.py index 578d55007eb3..24ccc05875ee 100644 --- a/python/sglang/srt/utils/common.py +++ b/python/sglang/srt/utils/common.py @@ -2329,25 +2329,30 @@ def dec(self, key: str): self._gauge.dec() -def add_prometheus_track_response_middleware(app): +def add_prometheus_track_response_middleware( + app, extra_labels: Optional[Dict[str, str]] = None +): from prometheus_client import Counter, Gauge + extra_labels = extra_labels or {} + extra_label_names = list(extra_labels.keys()) + http_request_counter = Counter( name="sglang:http_requests_total", documentation="Total number of HTTP requests by endpoint and method", - labelnames=["endpoint", "method"], + labelnames=extra_label_names + ["endpoint", "method"], ) http_response_counter = Counter( name="sglang:http_responses_total", documentation="Total number of HTTP responses by endpoint and status code", - labelnames=["endpoint", "status_code", "method"], + labelnames=extra_label_names + ["endpoint", "status_code", "method"], ) http_requests_active = Gauge( name="sglang:http_requests_active", documentation="Number of currently active HTTP requests", - labelnames=["endpoint", "method"], + labelnames=extra_label_names + ["endpoint", "method"], multiprocess_mode="livesum", ) @@ -2373,8 +2378,8 @@ async def track_http_status_code(request, call_next): method = request.method routing_key = request.headers.get("x-smg-routing-key") - http_request_counter.labels(endpoint=path, method=method).inc() - http_requests_active.labels(endpoint=path, method=method).inc() + http_request_counter.labels(**extra_labels, endpoint=path, method=method).inc() + http_requests_active.labels(**extra_labels, endpoint=path, method=method).inc() if routing_key: routing_keys_active.inc(routing_key) @@ -2382,6 +2387,7 @@ async def track_http_status_code(request, call_next): response = await call_next(request) http_response_counter.labels( + **extra_labels, endpoint=path, method=method, status_code=str(response.status_code), @@ -2389,7 +2395,7 @@ async def track_http_status_code(request, call_next): return response finally: - http_requests_active.labels(endpoint=path, method=method).dec() + http_requests_active.labels(**extra_labels, endpoint=path, method=method).dec() if routing_key: routing_keys_active.dec(routing_key) From 1eb9719ce1e810aa08e8c597abf7001bae09c13b Mon Sep 17 00:00:00 2001 From: ispobock Date: Sat, 18 Jul 2026 13:18:06 +0800 Subject: [PATCH 2/2] fix lint --- python/sglang/srt/utils/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/sglang/srt/utils/common.py b/python/sglang/srt/utils/common.py index 129b9f518802..6ed4c7f0a20b 100644 --- a/python/sglang/srt/utils/common.py +++ b/python/sglang/srt/utils/common.py @@ -2395,7 +2395,9 @@ async def track_http_status_code(request, call_next): return response finally: - http_requests_active.labels(**extra_labels, endpoint=path, method=method).dec() + http_requests_active.labels( + **extra_labels, endpoint=path, method=method + ).dec() if routing_key: routing_keys_active.dec(routing_key)