Repository navigation
Arm opt-in SGLang tracing on GLM-5.3 long tier - #296
henrypark133 wants to merge 4 commits into
Conversation
|
✅ OpenCodeReview: Review failed: 0 finding(s); 3 of 3 selected item(s) failed. |
PierreLeGuen
left a comment
There was a problem hiding this comment.
Reviewed with a focus on privacy, since these spans leave the CVM.
What the spans contain. I read the tracing code at SGLang fc91d24, the base of the pinned image. At level 3, each request produces:
- its SGLang request ID
- prompt, cached and completion token counts
- sampling params (
max_tokens,temperature,top_p,top_k,n) - the model name and the finish type
- per-stage timings, plus one span per decode step with batch size
There's no prompt text, output text or token IDs (span attributes). The only paths that put error messages into spans are in the disaggregation code, which this file doesn't use. There are no customer identifiers either: SGLang only reads traceparent/tracestate from request headers, and the proxy doesn't send those.
One change before merging: filter inside the CVM. The traces pipeline in otelcol_app_config exports spans unfiltered to telemetry.infra.near.ai. That's fine today, but only because this SGLang build happens to emit no content. A future SGLang upgrade could add prompt or completion attributes, and we wouldn't notice. Please add an allowlist to the in-CVM traces pipeline that keeps only the attributes above, on both span and span-event attributes. For example, a transform processor with keep_keys. Then extend the validator to pin it.
Two things to agree on, not blocking:
- The trace level can change without a config change. The file starts both engines at level 0, but SGLang's
/set_trace_levelhas no auth, unlike/freeze_gcnext to it. So anything on the CVM network, or an operator going through compose-manager, can turn on level 3 without a new file or release.- It isn't reachable from outside today. The proxy only serves an explicit route list and returns 404 for everything else, and the soak relay allows six paths and only starts under the
verificationprofile. - Since external verifiers review this file, let's announce each capture, time-box it, and record it.
- It isn't reachable from outside today. The proxy only serves an explicit route list and returns 404 for everything else, and the soak relay allows six paths and only starts under the
- This is the first per-request record exported from the CVM. Step 4 of the runbook, correlating SGLang request IDs with proxy request IDs, is what would tie spans to customers. Let's keep captures short, only do that join when we need it, and make sure our data-handling docs cover trace metadata.
Already handled: SGLang defaults to level 3 when SGLANG_TRACE_LEVEL is unset. The file sets 0 and the validator rejects anything else, so please keep that check.
Non-privacy notes:
- Deploying this reverts the r2 A/B. This file puts both gpu02 replicas on chunk 8192 / pdi 1. The r2 A/B running there now (chunk 16384, indexer split, pdi 2) would be undone if this is deployed as-is, so coordinate the rollout.
- Span volume. Level 3 emits one span per decode step. The in-CVM collector (512 MiB memory limiter, 128-batch sending queue) will likely drop spans during a long-context burst, so check for drops before trusting a capture.
Brings in #299, #300, #302 and #307. Conflicts in the W4AFP8 long-context generator, validator and test are resolved by taking main's per-replica logic (both replicas on the v2 QSPLIT image at chunk 8192, r1 pdi 1 / r2 pdi 2, r2's own environment list derived from the anchor) and re-applying this branch's tracing additions on top: --enable-trace and the OTLP endpoint on both replicas, SGLANG_TRACE_ASYNC=1 / SGLANG_TRACE_LEVEL=0 in the anchor environment (and therefore in r2's derived list), the -trace-async-armed variant suffix on both variants, and the glm53-trace-control job. The compose file is regenerated, not hand-merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Trace env per replica: SGLang fc91d24 treats an unset SGLANG_TRACE_LEVEL as 3 and an unset SGLANG_TRACE_ASYNC as synchronous export, and r2 has its own environment list (a merge key replaces lists). The validator now checks both variables on the merge-resolved environment of every replica that runs --enable-trace, with a failure that names the hazard. The test asserts per replica on the merge-resolved file (parsed with Ruby Psych, as CI has no PyYAML) instead of counting lines. Contract tests remove each variable from r1 and from r2. - Attribute allowlist (blocking review): the collector's traces pipeline runs transform/sglang_trace_allowlist. It uses keep_keys on span and spanevent attributes, keeping exactly the keys SGLang fc91d24 emits here (request id, token counts, sampling params, model, finish type, stage latencies, rank/thread labels, decode_ct, accepted drafts, schedule bid/batch_size/forward_mode). It clears span status messages and uses error_mode propagate so it fails closed. Abort/error text, matched stop strings and host_id are dropped. The generator injects it and the validator pins it exactly, pins the single traces pipeline through it, and strips it from the cross-file view. - Separate trace exporter: otlphttp/gateway_traces has the same endpoint and auth as otlphttp/gateway, an in-memory queue of 32, no file storage and retries capped at 60s, so a level-3 burst cannot back up or drop logs and metrics. Pinned in the validator and tests. - Docs: request-tracing section in the rollout doc, with the unauthenticated /set_trace_level, capture rules (announce, time-box, record), request-id correlation and data handling, level guidance, collector drop metrics and the tokenizer-worker gap (sgl-project/sglang#38210). The generated file header summarises it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@PierreLeGuen, thanks for the review. All of it is addressed in Blocking: filter inside the CVM. Fixed.
Deploying reverts the r2 A/B. Fixed by merging main through the generator (never hand-merging the YAML). The file keeps #307's replica configs: both replicas on Span volume and drops. Addressed.
Found in testing and fixed. After the merge, r2 has its own
Non-blocking items, now in the runbook. They're in a new "Request tracing" section of
r2 image dependencies. Likely fine, but not confirmed by an import test.
Checks. These CI steps were run locally inside
GitHub CI on |
Summary
Arm stock SGLang async OTLP tracing in the promoted W4AFP8 + HiCache long-context compose file. Both replicas start at
SGLANG_TRACE_LEVEL=0. An operator-only, one-shot Compose service calls/set_trace_levelon a selected replica from inside the CVM network; no guest shell or publicly exposed management endpoint is needed. The existing collector already accepts OTLP gRPC on port 4317 and forwards traces to the telemetry gateway. This PR does not deploy the file or turn on request traces at startup.The generator, generated compose file, and exact production validator move together. The config variant identifies the armed state.
Production capture after review and rollout
glm53-trace-controlservice described below to set level 3. Capture a short window of representative 128K+ requests, then run the service with level 0.rid/request metadata with proxy request IDs where possible. Verify that the traces actually arrive in the backend before using them for conclusions.chunked_prefillspans can include scheduler waiting between chunks; they are not pure GPU compute time.Level 3 creates a
decode_loopspan on each decode step plus prefill and other request-stage spans. A 2,000-token output can therefore generate roughly 2,000 decode spans. Level 0 avoids request spans but still initializes tracing/exporter machinery; its startup and performance impact require a production check.CVM control procedure
Use the same immutable tag, compose file, project, and complete gpu-manager env map as the deployed engines. Add
GLM53_TRACE_REPLICA=1andGLM53_TRACE_LEVEL=3to that env map. Call compose-managerPOST /compose/upwithservices: ["glm53-trace-control"],force_recreate: false, anddry_run: true. Inspect the raw plan: only the control job may be created/recreated/started, with no removals or engine changes. Apply the identical payload withdry_run: false, then read its result through scopedPOST /compose/logsforglm53-trace-control(tail: 15). Expecttrace_control_applied replica=1 level=3and no curl error. Repeat withGLM53_TRACE_LEVEL=0to stop new requests from tracing; that env change recreates the stopped one-shot control job. A restart of the SGLang engine also resets it to startup level 0.The job uses the already-pinned
curlimages/curlimage,runc, no GPU, read-only filesystem, dropped capabilities, no Docker socket or mounted secrets, and no published port. It accepts only replica 1/2 and level 0/3. Do not invoke this file before the traced long-context file is itself deployed: compose-manager'supuses--remove-orphans, and a different live file/tag could evict serving containers.Validation
--check).git diff --checkpasses.Array#filter_maprequires a newer Ruby). Other eleven cases pass.