Repository navigation
[Fix] metrics: record HTTP request metrics in tokenizer workers - #44663
Merged
hnyls2002 merged 5 commits intoOct 19, 2026
Merged
Conversation
hope1262946533
requested review from
CatherineSue,
JustinTong0323,
ispobock,
merrymercy and
slin1237
as code owners
October 16, 2026 04:36
The track-response middleware was registered from
`_setup_and_run_http_server`, which runs in the parent process. With
`--tokenizer-worker-num > 1` uvicorn spawns the HTTP workers and each of them
re-imports `http_server`, so the app they actually serve never had the
middleware. `sglang:http_requests_total`, `sglang:http_responses_total`,
`sglang:http_requests_active` and `sglang:routing_keys_active` were therefore
missing from `/metrics` whenever more than one tokenizer worker was used.
Register the middleware while the module is imported instead, so that every
worker picks it up. The metrics themselves are created in a separate step,
`init_http_request_metrics`, called from the lifespan once the process has
published its config: prometheus_client fixes its value backend when it is
first imported, and SGLang only sets `PROMETHEUS_MULTIPROC_DIR` in
`_set_envs_and_config`, which runs after `http_server` has been imported.
Creating them at import time would leave them in the in-memory registry that
the `/metrics` endpoint never reads, breaking single-tokenizer mode.
Because the middleware now runs inside each worker, also expose that worker's
in-flight request count as `sglang:http_worker_active_requests{worker_id}`.
hope1262946533
force-pushed
the
fix-http-metrics-multi-tokenizer
branch
from
October 16, 2026 05:02
7a39e75 to
7d42e6b
Compare
…i-tokenizer # Conflicts: # python/sglang/srt/entrypoints/http_server.py
…sion server - Remove sglang:http_worker_active_requests: out of scope, and its label was the worker PID. - Remove the unused extra_labels parameter. - The diffusion HTTP server registers the same middleware, so it now also calls init_http_request_metrics(); without it the server recorded no HTTP metrics. - Run the test file's TestCase from __main__ so CI executes it.
hnyls2002
requested review from
AgainstEntropy,
BBuf,
HaiShaw,
kevin-mii,
mickqian,
niehen6174,
ping1jing2 and
yichiche
as code owners
October 19, 2026 21:01
…t_metrics.py Pure move of RefCountedGauge, the metrics holder, init_http_request_metrics, add_prometheus_track_response_middleware and _get_fastapi_request_path out of utils/common.py; only imports change.
- Rename add_prometheus_track_response_middleware to add_http_request_metrics_middleware, the pair of init_http_request_metrics. - Name the metric attributes after their metrics (requests_total, responses_total). - Make init_http_request_metrics idempotent. - Merge the three tests into one: a request on the module-level app is counted only after init. Drop the subprocess import check, which any unrelated top-level prometheus_client import would break.
Collaborator
|
/rerun-test test_http_request_metrics.py registered/observability/test_metrics.py registered/tokenizer/test_multi_tokenizer.py test_diffusion_metrics.py registered/openai_server/basic/test_http2_server.py registered/e2e/entrypoints/test_engine_multi_tokenizer.py |
Collaborator
|
/tag-and-rerun-ci |
Contributor
|
🚀 🚀 🚀 🚀 |
4 of 5 tasks
detain
pushed a commit
to detain/sglang
that referenced
this pull request
Oct 29, 2026
…project#44663) Cherry-pick of upstream 81ac153. Middleware registration moves to module-import time so tokenizer workers that re-import http_server record http_requests/responses/active and routing_keys; init stays in lifespan (after PROMETHEUS_MULTIPROC_DIR). PORT NOTE: inert-but-correct at our config -- we do not pass --tokenizer-worker-num (default), so the worker-side registration path does not run today; the fix matters when the entry-201 (sgl-project#39716) worker-owned preprocessing story scales workers out. Rides with our entry-201 monitoring story. (cherry picked from commit 81ac153) (cherry picked from commit 5469a4b26c268daab1d3d7e1e9a349860d140753)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
With
--enable-metricsand--tokenizer-worker-num > 1, the HTTP requestmetrics are silently missing from
/metrics:sglang:http_requests_totalsglang:http_responses_totalsglang:http_requests_activesglang:routing_keys_activePer-endpoint request rates, in-flight counts and 5xx ratios therefore cannot be
monitored on a multi-tokenizer deployment, even though
/metricsitself isserved fine.
Modifications
The track-response middleware was registered from
_setup_and_run_http_server,which runs in the parent process. With
--tokenizer-worker-num > 1the serveris started with
uvicorn.run("...:app", workers=N): uvicorn spawns the HTTPworkers and each one re-imports
http_server, so the app they actually serve isa fresh object that never received the middleware.
CORSMiddleware/RequestDecompressionMiddlewareregistrations) so thatevery tokenizer worker picks it up, and drop the parent-process registration.
init_http_request_metrics,called from the lifespan once the process has published its config.
prometheus_clientfixes its value backend when it is first imported, andSGLang only sets
PROMETHEUS_MULTIPROC_DIRin_set_envs_and_config, whichruns after
http_serverhas been imported. Creating the metrics at importtime would therefore leave them in the in-memory registry, where the
MultiProcessCollectorbehind/metricsnever sees them -- including insingle-tokenizer mode.
in-flight request count as
sglang:http_worker_active_requests{worker_id}.This is the number to watch when a shared listening socket concentrates
connections on a few workers.
A unit test in
test/registered/unit/observability/test_http_request_metrics.pycovers all three: that the middleware is on the module-level app, that importing
http_serverdoes not pullprometheus_clientin early, and that a workerprocess records the counters and labels the per-worker gauge.
Accuracy Tests
N/A - metrics only.
Speed Tests and Profiling
N/A - no change to the inference path. With metrics enabled the per-request work
is unchanged; with metrics disabled the middleware returns after one config
lookup.
Checklist
pre-commit.
tests.
documentations.
Not applicable:
docs/docs/references/production_metrics.mdxdoes notdocument the HTTP request metrics at all, so adding only the new one would
be inconsistent.
accuracy
and Benchmark the
speed.
N/A, see above.
guidance.
CI States
Latest PR Test (Base): ⏳ Run #39325198175
Latest PR Test (Extra): ❌ Run #39325198198
Latest PR Test (AMD ROCm 10): ⏳ Run #39325198377