Skip to content

telemetry: extract bounded staging queue#1945

Open
e-eygin wants to merge 4 commits into
ai-dynamo:mainfrom
e-eygin:nix-1542-extract-telemetry-staging-queue
Open

telemetry: extract bounded staging queue#1945
e-eygin wants to merge 4 commits into
ai-dynamo:mainfrom
e-eygin:nix-1542-extract-telemetry-staging-queue

Conversation

@e-eygin

@e-eygin e-eygin commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

What?

Extracts the bounded, mutex-backed telemetry staging queue out of
nixlTelemetry into a focused internal class,
nixlTelemetryStagingQueue (src/core/telemetry/telemetry_staging_queue.{h,cpp}),
with no change in behavior.

The new class owns all queue mechanics:

  • event storage and its capacity reserve,
  • the producer/consumer mutex,
  • capacity enforcement,
  • all-or-none single (tryPush) and batch (tryPushBatch) insertion,
  • the swap-drain (takePending),
  • the staging-drop counter (exchangeDropped).

nixlTelemetry keeps everything metric-specific: per-metric activation,
event selection, periodic scheduling, exporter dispatch, and synthetic
dropped-event construction. updateData(), addXferStats(),
flushPendingEvents(), and exportDroppedEvents() are rewired onto the new
interface.

Adds focused and concurrent-producer unit tests under
test/gtest/unit/telemetry/, wired into the existing CTest unit target.

No public API, metric, exporter, or BUFFER schema change.

Why?

nixlTelemetry mixed two independent responsibilities: mapping telemetry
operations to events/exporting them, and implementing a bounded
multi-producer/single-consumer queue. Isolating the queue behind a stable
interface makes the queue mechanics independently testable and provides the
seam for the follow-up low-lock implementation (NIX-1544) to replace the queue
without touching metric logic.

Tracking: NIX-1542 (Perf-3, parent NIX-1359).

How?

Behavior is preserved exactly:

  • Metric activation stays at the producer — deactivated event types never enter
    the queue and are not counted as drops.
  • Single-event and variable-size batch insertion keep all-or-none semantics
    under one mutex acquisition; a rejected batch increments drops by its length,
    and a zero-length batch is a no-op with no lock and no drop-accounting change.
  • The consumer swaps the live vector for a fresh capacity-reserved one under the
    mutex and exports outside the lock; drained order is preserved.
  • The synthetic AGENT_TELEMETRY_EVENTS_DROPPED event still bypasses the queue.
  • Shutdown is unchanged (no final flush added).

The interface uses pointer + count for batch insertion so it stays C++17-clean
(no std::span dependency); addXferStats() builds its activated subset in a
fixed-size stack array and submits the populated prefix with no allocation.

Validated: staging-queue unit tests plus existing core-telemetry, Prometheus,
and DOCA telemetry suites pass on the C++17 and C++20 builds; the extracted
queue (including the concurrent-producer test) passes under ThreadSanitizer and
AddressSanitizer.

Summary by CodeRabbit

  • Improvements
    • Upgraded telemetry event buffering to a bounded staging queue with improved concurrent producers handling.
    • Flush now drains queued events consistently while applying a “drop-newest” policy when capacity is exceeded.
    • Transfer statistics are queued in all-or-nothing batches to avoid partial updates.
  • Reliability
    • More accurate dropped-event accounting derived from queue behavior, including proper reset after reporting.
  • Tests
    • Added unit coverage for capacity, ordering, batching, draining, drop-counter reset, and multi-producer concurrency invariants.
  • Chores
    • Updated build configuration to compile the staging queue and include related unit tests.

Move the mutex-backed bounded staging queue out of nixlTelemetry into a
focused internal nixlTelemetryStagingQueue class, with no behavior change.
The queue owns event storage and its capacity reserve, the producer mutex,
capacity enforcement, all-or-none single and batch insertion, the swap-drain,
and the staging-drop counter. nixlTelemetry keeps metric activation, event
selection, periodic scheduling, exporter dispatch, and synthetic
dropped-event construction.

Metric gating stays at the producer (deactivated types never enter the
queue and are not counted as drops), batch insertion remains all-or-none,
drop accounting stays exact, the drain still swaps under one mutex and
exports outside it, and shutdown behavior is unchanged. This extracted
interface (tryPush/tryPushBatch/takePending/exchangeDropped/capacity) is the
stable seam for the later NIX-1544 low-lock implementation.

Add focused and concurrent-producer unit tests under
test/gtest/unit/telemetry, run through the existing CTest unit target.

NIX-1542

Signed-off-by: Efraim Eygin <eeygin@nvidia.com>
@e-eygin e-eygin requested a review from a team as a code owner July 15, 2026 08:28
@copy-pr-bot

copy-pr-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown

👋 Hi e-eygin! Thank you for contributing to ai-dynamo/nixl.

Your PR reviewers will review your contribution then trigger the CI to test your changes.

🚀

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 1a5cf085-efca-4052-847f-463b68f841ac

📥 Commits

Reviewing files that changed from the base of the PR and between b923ec4 and f3cd5f9.

📒 Files selected for processing (4)
  • src/core/telemetry/telemetry.cpp
  • src/core/telemetry/telemetry_staging_queue.cpp
  • src/core/telemetry/telemetry_staging_queue.h
  • test/gtest/unit/telemetry/telemetry_staging_queue_test.cpp

📝 Walkthrough

Walkthrough

A bounded telemetry staging queue replaces manual event buffering and drop accounting. Telemetry updates and transfer statistics enqueue through the queue, exports drain pending events, and unit tests cover queue semantics and concurrency.

Changes

Telemetry staging queue

Layer / File(s) Summary
Queue contract and implementation
src/core/telemetry/telemetry_staging_queue.*
Adds bounded single-event and all-or-none batch insertion, draining, drop-counter retrieval, and capacity access.
Telemetry buffering and export integration
src/core/telemetry/telemetry.*
Replaces the event vector, mutex, and atomic drop counter with staging-queue operations for updates, transfer batches, flushing, and dropped-event export.
Build wiring and queue validation
src/core/meson.build, test/gtest/unit/meson.build, test/gtest/unit/telemetry/meson.build, test/gtest/unit/telemetry/telemetry_staging_queue_test.cpp
Adds library and unit-test build wiring and validates capacity, ordering, batch atomicity, draining, drop retrieval, and concurrent producer behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • ai-dynamo/nixl#1919: Modifies the same telemetry hot-path functions and dropped-event handling.

Sequence Diagram(s)

sequenceDiagram
  participant TelemetryProducer
  participant nixlTelemetryStagingQueue
  participant PeriodicExportTask
  TelemetryProducer->>nixlTelemetryStagingQueue: tryPush or tryPushBatch
  PeriodicExportTask->>nixlTelemetryStagingQueue: takePending
  nixlTelemetryStagingQueue-->>PeriodicExportTask: pending events
  PeriodicExportTask->>nixlTelemetryStagingQueue: takeNumDropped
  nixlTelemetryStagingQueue-->>PeriodicExportTask: dropped-event count
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed It clearly summarizes the main change: extracting the telemetry staging queue.
Description check ✅ Passed It includes the required What, Why, and How sections and provides adequate implementation detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/telemetry/telemetry_staging_queue.cpp`:
- Line 25: Mark the local std::lock_guard instance at the shown mutex
acquisition, and the corresponding instances at the other two lock sites, as
const. Do not change locking behavior or the surrounding critical sections.

In `@src/core/telemetry/telemetry_staging_queue.h`:
- Around line 43-45: Add a Doxygen `@brief` comment immediately before the public
constructor nixlTelemetryStagingQueue, documenting its purpose and the capacity
parameter, including whether a capacity of 0 is valid according to the
implementation’s behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 2ad69118-fca5-4a22-95a4-de4dbc274da2

📥 Commits

Reviewing files that changed from the base of the PR and between a7f2232 and eea0fba.

📒 Files selected for processing (8)
  • src/core/meson.build
  • src/core/telemetry/telemetry.cpp
  • src/core/telemetry/telemetry.h
  • src/core/telemetry/telemetry_staging_queue.cpp
  • src/core/telemetry/telemetry_staging_queue.h
  • test/gtest/unit/meson.build
  • test/gtest/unit/telemetry/meson.build
  • test/gtest/unit/telemetry/telemetry_staging_queue_test.cpp

Comment thread src/core/telemetry/telemetry_staging_queue.cpp Outdated
Comment thread src/core/telemetry/telemetry_staging_queue.h
Mark the three local std::lock_guard instances in nixlTelemetryStagingQueue
const, matching the repo convention already used in addXferStats. Add a
Doxygen @brief to the constructor documenting the capacity parameter and
that a zero capacity is accepted (the queue then drops every push);
rejecting a zero telemetry buffer size stays the caller's responsibility.

No behavior change.

Signed-off-by: Efraim Eygin <eeygin@nvidia.com>
@e-eygin

e-eygin commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

@ColinNV @ovidiusm please review

@e-eygin

e-eygin commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

/build

Comment thread src/core/telemetry/telemetry_staging_queue.cpp Outdated
Comment thread src/core/telemetry/telemetry.h Outdated
Comment thread src/core/telemetry/telemetry.cpp
@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-build-wheel · commit 329a6e59

TL;DR: The vLLM sanity test failed because both vLLM engines aborted at startup with ValueError: No available memory for the cache blocks — the --gpu-memory-utilization 0.3 budget (with vLLM 0.23.0 + NixlConnector's 1 GB kv_buffer_size) leaves negative KV-cache memory (Available KV cache memory: -2.8/-12.38 GiB), so both servers exit and the health check times out (300 s). The fix is to raise GPU_MEM_FRACTION for vLLM.

Full analysis

Summary: Stage 535 "Run vLLM sanity" failed; both prefill/decode vLLM servers crashed on EngineCore init and the /health wait timed out after 300 s, returning exit code 1.

Root cause: vLLM 0.23.0 EngineCore computed negative available KV-cache memory under --gpu-memory-utilization 0.3 on the GB200 CI node. The log shows gpu_worker.py:480 Available KV cache memory: -2.8 GiB (consumer) and -12.38 GiB (producer), then kv_cache_utils.py:720 _check_enough_kv_cache_memory raising ValueError: No available memory for the cache blocks. With the model (~15.27 GiB weights) plus vLLM's own runtime/activation reservations and the NixlConnector kv_buffer_size=1000000000.0 (1 GB) carved out of the same budget, 0.3 of the GPU is insufficient after non-KV overhead — so the check fails and both engines abort. This is a genuine crash, not a wall-clock hang: the timeouts at 10:40 (timeout (300s) waiting for .../health) are downstream of the 10:35:51 crash, and the largest log gap is the model-download prefetch (~10:31→10:35), which completed normally. Note the SGLang sanity (stage 559) passed with the same 0.3 fraction because SGLang's --mem-fraction-static accounting differs and it doesn't add the NIXL kv_buffer_size on top.

Implicated commit: unknown (the 0.3 value predates this change — likely a vLLM-version bump making the budget too tight; not attributable to a specific commit from the logs)

File: .gitlab/test_vllm_sglang_sanity.sh:47 (GPU_MEM_FRACTION="${GPU_MEM_FRACTION:-0.3}"), consumed at lines 111 and 117.

Suggested fix: Raise the vLLM memory budget so KV-cache memory is positive after weights + overhead + the 1 GB NIXL buffer — e.g. set a vLLM-specific GPU_MEM_FRACTION of 0.60.8 (the comment at lines 43–46 already notes 0.3→~56 GiB was the intent, but vLLM 0.23.0's accounting shows that is not enough). Concretely, decouple the two frameworks: keep 0.3 for SGLang (which passes) and bump vLLM, or explicitly bound the NIXL kv_buffer_size down and increase the fraction. Given the GB200 has ~186 GiB and only ~15 GiB of weights, 0.7 is safe and leaves ample room.

Related: none found in the provided tooling; the vLLM error links to https://docs.vllm.ai/en/latest/configuration/conserving_memory/ for the gpu_memory_utilization guidance.

@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-gpu · commit 329a6e59

TL;DR: The nixl-ci-gpu #2754 UCX-v1.22.x CPP-test stage was killed by Jenkins on wall-clock timeout (exit 143), not because it hung but because the telemetry-heavy threadpool gtests (ucx_telemetry_threadpool*, ucx_threadpool_no_pt) each ballooned to ~2 minutes, so the suite couldn't finish in time. The regression is in PR #1945's reworked telemetry staging-queue enqueue path contending with the dedicated UCX progress thread.

Full analysis

Summary: Stage 248 ("Run CPP tests", UCX v1.22.x variant) aborted after ~61 min when Jenkins sent an interrupt during gtest-parallel; the run was still progressing but far too slowly to complete.

Root cause: Wall-clock kill caused by a severe per-test slowdown (not a hang — output is continuous to the kill). Telemetry-path tests regressed sharply: ucx/TestTransfer.* take 10–38 s each while ucx_telemetry_threadpool* and ucx_threadpool_no_pt tests take 113–179 s each, so tests 111–131 alone consumed ~40 min. The commit under test is PR #1945 "telemetry: extract bounded staging queue," which reworks the exact enqueue/flush path (updateData → staging queue → flushPendingEvents under mutex_) exercised by every transfer. Under the dedicated UCX progress thread (threadpool) configuration, the new bounded staging queue introduces contention/overhead on the transfer hot path, multiplying per-transfer cost. The same NIXL commit built against ucx-master (stage 209) passed CPP tests in ~29 min, so the interaction is worsened under UCX v1.22.x.

Implicated commit: [REDACTED:Hex High Entropy String] (PR #1945, "telemetry: extract bounded staging queue")

File: src/core/telemetry/telemetry.cpp — hot-path updateData() (line ~127) and flushPendingEvents()/staging under mutex_ (lines ~74–92)

Suggested fix: Profile the telemetry enqueue path introduced by #1945 in the threadpool/dedicated-progress-thread configuration and remove the per-event contention — e.g. avoid taking mutex_ on every updateData() call from the transfer hot path (use a lock-free or per-thread staging buffer, or batch), and confirm the bounded queue isn't doing O(n) work or blocking per event. Re-run the ucx_telemetry_threadpool* gtests locally and compare per-test durations against the pre-#1945 baseline (~38 s vs. the observed ~120 s). Do not simply raise the CI time limit — the 3–5x per-test blowup is a real performance regression to fix.

Related: PR #1945 (#1945); UCX bump PR #1868 (v1.22.x) which is the branch that tips the suite over the wall-clock budget; PR #1880 (ucx dedicated-thread fix) for context on the threadpool path.

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id a0945811-bf48-4acb-adcd-27e7acc8b81d in the triage console for the audit trail.

- tryPushBatch: rewrite the capacity check as `count > capacity_ -
  events_.size()` to avoid a theoretical size_t overflow in the sum
  (events_.size() <= capacity_ always holds, so the subtraction never
  underflows).
- telemetry.h: drop the now-unused <vector> and <mutex> includes; neither
  std::vector nor std::mutex is referenced there after the extraction.

No behavior change.

Signed-off-by: Efraim Eygin <eeygin@nvidia.com>
@e-eygin e-eygin requested a review from guy-ealey-morag July 15, 2026 11:34
Comment thread src/core/telemetry/telemetry.cpp Outdated
Comment thread src/core/telemetry/telemetry.cpp Outdated
- tryPushBatch now takes std::span<const nixlTelemetryEvent> instead of a
  pointer+count pair; the repo builds as C++20, so no C++17 workaround is
  needed. addXferStats submits its activated prefix via
  std::span{batch}.first(count).
- Rename the drop counter to convey it is a count, not the events: member
  droppedEvents_ -> numDroppedEvents_ and exchangeDropped() -> takeNumDropped()
  (parallels takePending()'s take-and-reset semantics).
- Mark the whole queue interface [[nodiscard]]; the producer call sites that
  intentionally ignore the accepted/dropped result now (void)-cast it.

No behavior change.

Signed-off-by: Efraim Eygin <eeygin@nvidia.com>
@e-eygin e-eygin requested a review from guy-ealey-morag July 15, 2026 13:24
@e-eygin

e-eygin commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

/build

@e-eygin

e-eygin commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test f3cd5f9

@e-eygin e-eygin enabled auto-merge (squash) July 15, 2026 14:05
@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-build-wheel · commit 3285ae35

TL;DR: The wheel built fine; the failure is in the "Build sanity image" stage where apt install curl git in contrib/Dockerfile.vllm couldn't reach ports.ubuntu.com ("Network is unreachable"). This is a CI network/infra outage, not a code bug — retry the build once network is restored.

Full analysis

Summary: Jenkins stage 483 "Build sanity image" (aarch64 vLLM image) failed with exit code 100 during docker build -f contrib/Dockerfile.vllm.

Root cause: The RUN apt update && apt install -y curl git step could not download the .deb packages. Every fetch to ports.ubuntu.com failed with connect (101: Network is unreachable) on IPv6 (2620:2d:4002:1::10a/b/c) and connection timed out on IPv4 (91.189.91.102/103/104). apt-get then aborted: E: Unable to fetch some archives ... exit status 100. The nixl wheel itself (stages 398/411/442) compiled and repaired successfully — this is purely an external package-mirror/network reachability problem on the aarch64 build node, unrelated to the PR's code.

Implicated commit: None — not a code regression. (The failure is environmental; commit 3285ae3 / PR #1945 did not touch contrib/Dockerfile.vllm in a way that caused this.)

File: contrib/Dockerfile.vllm:22-25 (the apt update && apt install step where the network fetch failed).

Suggested fix:

  1. Immediate: Re-run the build once outbound connectivity to Ubuntu mirrors is restored — this is a transient/infra network failure (the node appears to have broken IPv6 routing and blocked/timed-out IPv4 to ports.ubuntu.com).
  2. Hardening (to make this stage resilient):
    • Force IPv4 for apt on this node, since the IPv6 route is unreachable: add echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99force-ipv4 before apt update.
    • Point apt at an internal/artifactory Ubuntu mirror instead of the public ports.ubuntu.com, consistent with how base images are already pulled from artifactory.nvidia.com.
    • Add retry logic to the apt step (e.g. Acquire::Retries "5";) so transient mirror flakiness doesn't fail the build.

Related: none found.

Note: stage 332 build_helper_vllm/aarch64 is also marked FAILURE, but its companion node 586 "pipline stop on build_helper_vllm" indicates that is the pipeline's intentional stop/propagation of this same sanity-image failure, not an independent cause.

@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-dl-gpu-ep · commit 3285ae35

TL;DR: The build succeeded; the "Allocate DL EP Environment" stage failed because a Slurm salloc for a GB200 node in partition gb200nvl72_cx8 sat queued for the full 1-hour --immediate=3600 window and returned "Unable to allocate resources: Connection timed out." This is a cluster capacity/scheduler issue, not a code defect.

Full analysis

Summary: Stage 224 "Allocate DL EP Environment" failed on a Slurm resource allocation timeout after waiting ~1 hour for a GB200 node.

Root cause: The salloc -N 1 -p gb200nvl72_cx8 --immediate=3600 --time=01:30:00 request stayed in "queued and waiting for resources" for the entire 3600s immediate window (14:19:48 → 15:19:57 — a 60-minute gap with no output) and Slurm then returned error: Unable to allocate resources: Connection timed out, so the script exited 1. No GPU node was free in that partition. The parallel UCX build stages (124/125) actually completed successfully (UCX built, NIXL built, image pushed); stage 125's "FAILURE" is a side effect of the pipeline abort, not a real build error.

Implicated commit: unknown — not a code regression; PR #1945 (commit 3285ae3) code compiled and installed cleanly.

File: unknown (infrastructure) — the failing command originates from the shared swx-jenkins-lib slurm.allocation step invoked in the "Allocate DL EP Environment" pipeline stage.

Suggested fix: Retry the build — this is a transient cluster-availability failure, not a code issue. If GB200 (gb200nvl72_cx8) contention is chronic, consider: (1) adding automatic retry/backoff around the slurm.allocation step, (2) raising --immediate only if you confirm jobs eventually run (here it never got scheduled, so a longer wait alone won't help), or (3) routing this job to a less-contended partition/reservation. No change to the nixl source or PR #1945 is warranted.

Related: none found.

@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-build-wheel · commit 3285ae35

TL;DR: The wheel built fine; the "Build sanity image" stage failed because apt update/apt install -y curl git in contrib/Dockerfile.vllm couldn't reach ports.ubuntu.com (network unreachable/timeout), yielding E: Package 'git' has no installation candidate (exit 100). This is a transient infra/network egress failure, not a code bug in PR #1945.

Full analysis

Summary: Stage 470 "Build sanity image" (and its parent stage 332 build_helper_vllm) failed while building contrib/Dockerfile.vllm on the aarch64 node.

Root cause: apt could not fetch the Ubuntu ports package index — repeated Cannot initiate the connection to ports.ubuntu.com:80 ... Network is unreachable and connection timed out for both IPv6 and IPv4 mirrors. With a stale/empty index, apt install -y curl git failed: E: Package 'git' has no installation candidate, causing the Dockerfile RUN at line 22 to exit 100. The NIXL wheel build itself completed and was successfully repaired/extracted.

Implicated commit: None (transient network failure). The failing RUN apt update && apt install -y curl git line was introduced/last touched by the sanity-testing work in contrib/Dockerfile.vllmb594eb0 (NirWolfer, "ci: add vLLM/SGLang NIXL disaggregation sanity testing", #1777) — but that is not the cause.

File: contrib/Dockerfile.vllm:22-25

Suggested fix: Re-run the build; the failure is an external network outage to ports.ubuntu.com from the aarch64 build host. To harden against this recurring: (1) point the aarch64 base image's apt sources at an internal/artifactory Ubuntu ports mirror, (2) disable IPv6 for apt or force IPv4 (Acquire::ForceIPv4 "true";), and/or (3) bake curl and git into the vllm-nixl-base image so the PR-time Dockerfile doesn't need network apt access at all. If it's a persistent egress restriction on the node, investigate the build node's outbound network/firewall config.

Related: none

@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-build-wheel · commit 3285ae35

TL;DR: The wheel build succeeded; the "Build sanity image" stage failed because apt update couldn't reach ports.ubuntu.com (port 80) — "Network is unreachable" — so apt install git failed with E: Package 'git' has no installation candidate (exit 100). This is a transient CI network/egress problem, not a code defect; retry the build (or fix the node's outbound HTTP access to the Ubuntu ports mirror).

Full analysis

Summary: Jenkins stage 483 "Build sanity image" (aarch64 vLLM sanity image) failed at docker build -f contrib/Dockerfile.vllm during apt update && apt install -y curl git.

Root cause: The build node could not reach http://ports.ubuntu.com on any mirror (IPv6 2620:2d:4002:1::10a/b/c and IPv4 91.189.91.102/103/104) — repeated "connect (101: Network is unreachable)" and connection timeouts. With a stale/empty package index, apt install git had no candidate → E: Package 'git' has no installation candidate, exit code 100. HTTPS repos (NVIDIA CUDA, deadsnakes PPA) succeeded, so only outbound HTTP:80 to the Ubuntu ports mirror was broken. The wheel build (stage 442/398/423) itself passed. (Stage 332 build_helper_vllm is a normal early "pipeline stop" gating step, not the real error.)

Implicated commit: None — not a code regression. contrib/Dockerfile.vllm was last changed by b594eb0 (NirWolfer, #1777, 2026-07-14), unrelated to this failure and unrelated to PR #1945.

File: contrib/Dockerfile.vllm:22-23 (the apt update && apt install -y curl git step that fails when the mirror is unreachable).

Suggested fix: Re-run the build — this is a transient infrastructure/network issue on the aarch64 agent. If it recurs: (1) restore outbound access to ports.ubuntu.com:80 (or route the node through a reachable Ubuntu-ports mirror / apt proxy, preferably over HTTPS), and (2) harden the Dockerfile by adding retries/--fix-missing or pinning an internal mirror so a single flaky mirror doesn't fail the whole sanity image build. Do not treat this as a PR code problem.

Related: none

@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-dl-gpu-ep · commit 3285ae35

TL;DR: The build compiled and pushed fine; the job failed in "Allocate DL EP Environment" because salloc on the gb200nvl72_cx8 Slurm partition waited its full --immediate=3600 (1 hour) window without getting a node and exited with "Unable to allocate resources: Connection timed out." This is a cluster capacity/scheduling problem, not a defect in PR #1945.

Full analysis

Summary: nixl-ci-dl-gpu-ep #329 failed in the "Allocate DL EP Environment" stage when the Slurm salloc request for a GB200 node timed out after 1 hour of queueing.

Root cause: In stage 183/200, the pipeline ran salloc -N 1 -p gb200nvl72_cx8 --immediate=3600 --time=01:30:00 --no-shell --account=blackwell via SSH to dlcluster.nvidia.com. Log timestamps show the request submitted at 17:18:52, job 1564210 "queued and waiting for resources," then at 18:19:01 (exactly ~1 hour, the --immediate=3600 limit) Slurm returned error: Unable to allocate resources: Connection timed out. The GB200 partition had no free nodes within the allowed wait window. Note this is a genuine resource-wait (salloc is designed to block here), not an application hang — the large timestamp gap corresponds to Slurm's own queueing, and the earlier build phases (docker image compile/push) all succeeded, so the PR code is not implicated.

Implicated commit: none — 3285ae3 built and packaged successfully; failure is infrastructure/cluster-side.

File: N/A (Jenkins pipeline Slurm allocation step; slurm.allocation call with partition:gb200nvl72_cx8, immediateTimeout:3600)

Suggested fix: Retry the build — this is transient cluster contention on the gb200nvl72_cx8 partition. If GB200 allocation timeouts are recurring, either (a) increase --immediate/immediateTimeout to allow longer queueing, (b) add an automatic re-queue/retry on "Unable to allocate resources", or (c) coordinate with the cluster team on blackwell account capacity/reservation. Do not treat this as a code change to the PR.

Related: none found.

@svc-nixl

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agentnixl-ci-dl-gpu-ep · commit 3285ae35

TL;DR: The build/image steps all succeeded; the job failed in the "Allocate DL EP Environment" stage because salloc on the gb200nvl72_cx8 SLURM partition waited the full --immediate=3600 window (18:46 → 19:46) and gave up with "Unable to allocate resources: Connection timed out." This is a cluster capacity/infrastructure issue, not a code defect in PR #1945.

Full analysis

Summary: Jenkins stages "Allocate DL EP Environment" (node 183 and 200) failed after ~3600 s waiting for a GB200 SLURM node that never became available.

Root cause: SLURM salloc -N 1 -p gb200nvl72_cx8 --immediate=3600 queued the job (salloc: job 1565110 queued and waiting for resources) and, because no node freed up within the 1-hour immediate timeout, terminated with salloc: error: Unable to allocate resources: Connection timed out (exit code 1). The ~1-hour gap between the request line (18:46:23) and the failure (19:46:32) exactly matches the 3600 s --immediate budget — the allocator was legitimately waiting in queue, not hung in application code. The docker image compile (nodes 168/155) and the NIXL/nixlbench builds all completed successfully, so nothing in the PR's code is implicated. The earlier build_helper_dl_ep FAILUREs (124/125) were transient and were re-run successfully (151/142).

Implicated commit: none — infrastructure/resource contention, unrelated to commit 3285ae3.

File: N/A (Jenkins pipeline SLURM allocation step invoking swx-jenkins-lib slurm.allocation; partition gb200nvl72_cx8)

Suggested fix: Retry the CI job — this is a cluster-availability failure. If GB200 contention on gb200nvl72_cx8 is chronic, mitigate at the infra level: increase immediateTimeout beyond 3600 s so jobs can wait longer in queue, add automatic requeue/retry on "Unable to allocate resources", or reserve capacity for the blackwell account. No source change to PR #1945 is warranted.

Related: none

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants