Skip to main content

The Telemetry Pipeline

You have the signals (taxonomy), the sources (protocols), and the join keys (correlation). This page is the plumbing that carries all of it — from a counter on a switch ASIC to a panel on an on-call engineer's screen — without falling over at 10k-GPU scale.

The shape is always the same five stages. The engineering is entirely in the two constraints that decide whether it survives: cardinality and retention.

After this page, you'll be able to
  1. Draw the five-stage pipeline — collect → transport → store → visualize → alert — and place each exporter.
  2. Choose the collectors per layer (gNMI, sFlow, WJH, node_exporter, dcgm-exporter, NCCL profiler).
  3. Do the cardinality math and apply the aggregate-at-the-exporter rule so RoCE per-QP metrics don't melt the TSDB.
  4. Design tiered retention — high-resolution recent, downsampled long-term — and use recording rules for expensive rollups.
  5. Know where OpenTelemetry fits and why you must monitor the pipeline itself.

The five-stage pipeline

Prefer streaming telemetry (gNMI subscribe in STREAM/SAMPLE mode) over SNMP polling for the fabric — sub-second congestion events are invisible at 30 s SNMP intervals.


Collectors & exporters

LayerCollector / exporterProtocolEmits
SwitchgNMI (OpenConfig streaming)gNMI/gRPCqueue stats, PFC/ECN, watermarks, interface counters
SwitchsFlow + WJHsFlow / event streamsampled flows + event-based drop reasons
Host NICnode_exporter (+ RDMA/perfquery collector)HTTP :9100hw_counters, per-priority pause/ECN, port errors
GPUdcgm-exporterHTTP :9400all DCGM_FI_* fields, labelled by GPU UUID
JobNCCL profiler pluginpush / OTelper-collective timing, busbw

The collector tier for switches is usually gNMIc or Telegraf subscribing to the streams and re-emitting to the TSDB; large operators fan through Kafka first so multiple consumers (TSDB, anomaly detection, long-term archive) can each read the firehose independently.


Storage: Prometheus and where it stops scaling

Prometheus is the default and the right starting point: pull-based scraping, PromQL, a huge exporter ecosystem. A single Prometheus handles a rack or a pod comfortably. At fabric scale you outgrow one instance and move to a horizontally-scalable, long-retention backend that still speaks PromQL:

BackendModelWhy you'd pick it
Prometheussingle-node scrape + local TSDBstart here; per-pod / per-rack
VictoriaMetricsclustered, high-cardinality tolerantwhen cardinality is the pain point
Thanos / MimirPrometheus + object storage, global querylong retention + a single global view

The migration trigger is almost always cardinality, not query load — which is the constraint below.


Cardinality & retention — the real design constraint

This is where naïve observability designs die. RoCE metrics are per-queue-pair, and a large fabric has thousands of QPs per NIC × hundreds of NICs — scrape all of that per-QP into Prometheus and you'll melt the TSDB.

The rules that keep it alive:

  • Aggregate at the exporter. Emit per-port and per-priority by default; expose per-QP only on demand (rdma statistic show qp during an incident), not as a standing scrape.
  • Recording rules for the expensive rollups (per-rack ECN rate, per-leaf drop rate) so dashboards query pre-computed series instead of re-aggregating raw ones on every refresh.
  • Tiered retention: high-resolution (1–5 s) for a short window, downsampled for long-term trend and baselining.
  • Label discipline: the join-key labels are worth their cardinality; free-form or per-flow labels are not. Every label multiplies series count — spend them deliberately.

A back-of-envelope

Take 1,000 NICs. Emit 20 useful counters each, sliced per-port × 8 priorities — that's 1000 × 20 × 8 = 160,000 series. Bounded and totally fine. Now add a naïve per-QP label at 2,000 QPs/NIC: 1000 × 20 × 2000 = 40,000,000 series — a 250× explosion that no single TSDB survives. Same counters, one label, two wildly different outcomes. That is the entire cardinality lesson in one line: bound the dimension or sample it; never stream the unbounded one.


Tiered retention

Not every resolution is worth keeping forever:

TierResolutionRetentionPurpose
Hot1–5 shours–daysincident forensics, the walk-down
Warm30 s–1 minweeksdashboards, recent trend
Cold5 min (downsampled)months–yearsbaselining, seasonality, capacity

Baselining and seasonal alerting (next page) depend on the cold tier — you can't alert on "10× the 7-day median" if you only kept 48 hours.


Where OpenTelemetry fits

OpenTelemetry (OTel) is the converging standard for application-emitted telemetry — the NCCL profiler and framework instrumentation naturally speak it (metrics, traces, and the collective "spans" that are your best approximation of tracing). The practical pattern:

  • Fabric/host counters → stay on the Prometheus/gNMI path (that ecosystem is mature and counter-shaped).
  • Job/collective signals → OTel SDK → OTel Collector, which can fan out to the same TSDB and to a trace backend.
  • The OTel Collector is also a convenient single point to attach the join-key labels consistently before data lands in storage.

Don't rip out Prometheus for OTel; let OTel own the application/job pillar and Prometheus own the infrastructure counters, unified at the storage/query layer.


Monitor the pipeline itself

If the pipeline is down, you're blind — and worse, you may not know it. The observability stack is Tier-0 infrastructure and must watch itself:

  • up / scrape success for every exporter — a silent dead dcgm-exporter means that node is invisible, not healthy.
  • Ingestion rate and active series count — your early warning that a cardinality bomb just got deployed.
  • Retention headroom / disk — the classic 3 AM "why is there no data from last night" is a full TSDB.
  • Alert-path liveness — a synthetic heartbeat alert that must fire; if it stops, Alertmanager/PagerDuty is broken.

💡 What you should remember

#ConceptWhy it matters
1🔟Five stagescollect → transport → store → visualize → alert — every design is this shape.
2🧮Aggregate at the exporterPer-port × per-priority is bounded; per-QP is a 250× cardinality bomb.
3🗜️Recording rules + tiered retentionPre-compute rollups; keep hot data fine-grained and cold data downsampled.
4📶Stream, don't poll, the fabric30 s SNMP averages away the microsecond congestion events.
5🔭OTel owns the job pillarLet OTel carry collective telemetry; keep Prometheus for infra counters.
6👁️Watch the watcherAlert on scrape failures, series growth, and a heartbeat — a dead exporter looks like a quiet node.

Next: SLIs, SLOs & Alerting → — turning these signals into a pager that fires when the job is actually hurting, not when a counter is merely non-zero.