Repository navigation
feat(telemetry): name the rollout in X-Request-Id on model-server backend calls - #4750
Conversation
…kend calls Inside a rollout, every call a Gym model server makes to its inference backend now carries `X-Request-Id: <rollout id>-<8 hex chars>`. vLLM takes its request id from that header and records it as `gen_ai.request.id` on the request's span and in its request log, so an engine span or log line can be matched to a rollout directly, without walking the trace tree. The header is set in the shared OpenAI client wrapper, so every model server that uses it gets it. It is only added inside a rollout context, and a caller's own `X-Request-Id` is kept. The random suffix keeps calls distinct across server workers that cannot share a counter. Signed-off-by: Ingo Guehring <iguehring@nvidia.com>
|
🌿 Preview your docs: https://nvidia-preview-pr-4750-79caf559b7e1.docs.buildwithfern.com/nemo/gym |
|
/review |
svcnvidia-nemo-ci
left a comment
There was a problem hiding this comment.
SHIP
LGTM — no reliability concerns. Reviewed all three changed files and traced rollout-context propagation and the shared HTTP transport. Header generation preserves caller-provided request IDs case-insensitively, leaves out-of-rollout calls unchanged, and does not mutate client defaults.
Validation was limited to source and test inspection; tests were not executed.
Note: formal approval is not available for this request, so this review is posted as a comment only.
Review generated by codex
|
🔄 Merge queue validation started! You can track the progress here: https://github.com/NVIDIA-NeMo/Gym/actions/runs/39427799824 |
What does this PR do?
Inside a rollout, every call a Gym model server makes to its inference backend now carries
X-Request-Id: <rollout id>-<8 hex chars>, set in the shared OpenAI client wrapper (NeMoGymAsyncOpenAI._request) so every model server built on it gets it.Why: vLLM takes its request id from
X-Request-Idand records it asgen_ai.request.idon the request's span and in its request log. With the rollout id in front, an engine span or an engine log line can be matched to its rollout directly, by attribute, instead of by walking the trace from the engine span up through the Gym client span and the model-call span to the rollout span. That also keeps the match intact when a parent span is dropped. The rollout id is the same correlation key Gym already uses in the/ng-rollout/<id>/URL prefix and on its own spans.Behaviour:
current_rollout_id()set). Calls made outside a rollout are unchanged.X-Request-Idheader, in any case, is kept.No issue; a small follow-on to the rollout correlation work (#2647).
Validation
pytest tests/unit_tests/test_openai_utils.py: 299 passed, including two new tests: the header names the rollout and differs per call; it is absent outside a rollout and never overrides a caller's header.pytest tests/unit_tests/telemetry tests/unit_tests/test_rollout_correlation.py: 357 passed; the 4 failures are the pre-existing macOS-only ones (test_memory,test_connection_pool,test_call_sitesactive-servers gauge) and fail identically onmain.pre-commit run --files <changed files>: passed._base_request_idreadsX-Request-Idand the id reaches thellm_requestspan asgen_ai.request.id.Rollout evidence
N/A for behaviour: the change adds one request header; request bodies, retries and responses are unchanged. The end-to-end effect (rollout id visible on engine spans) will be confirmed in the next collector validation run together with #4749.
Combined end-to-end run (added after opening)
Run on a Slurm cluster from a temporary branch merging #4749, #4750 and #4751 on top of
main(7719379), withotel.vllm_traces: trueand no hand-set flags: Nano 3.5 on vLLM 0.26.0, 2 GPUs (TP2), 16 scicode rollouts, 8 in parallel. Completed in 8 min 31 s, 16 of 16 scored, collector log clean, no token in the job directory.otlp_traces_endpoint; 72llm_requestspans arrived, each a child of the policy model's client span.Received request chatcmpl-<rollout id>-<8 hex>for all 72 requests, andgen_ai.request.idon every engine span carries the same id.gym.rollout.dispatchroots in 16 distinct traces, every one with a span link to thegym.jobspan; each trace holds itsgym.rolloutand its engine spans. Thegym.jobtrace holds only the job span and the aggregate-metrics calls; startup spans are their own trace as before. Largest trace: 271 spans, versus the whole run in one trace before.Sandboxed end-to-end run (added after opening)
Terminal-bench 4 miniswe on OpenSandbox sandboxes, 8 tasks, agent running inside the sandbox and calling the policy model through the rollout-prefixed URL. vLLM's request log shows a rollout-prefixed id for all 321 requests, and
gen_ai.request.idon all 321 engine spans carries it. Those engine spans are roots of their own traces, because the in-sandbox harness sends notraceparent; the request-id prefix is what ties them to the rollout, which is the case this header exists for.