feat(telemetry): instrument NeMo-RL with OpenTelemetry via nemo-lens#3268
Draft
ahmadki wants to merge 8 commits into
Draft
feat(telemetry): instrument NeMo-RL with OpenTelemetry via nemo-lens#3268ahmadki wants to merge 8 commits into
ahmadki wants to merge 8 commits into
Conversation
New `telemetry` extra pulling nemo-lens with the OTel SDK. Kept optional: when the extra is not installed, every instrumentation site degrades to a no-op via nemo_rl/telemetry/_fallbacks.py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
The release Dockerfiles sync the `telemetry` extra into the driver venv (`--extra telemetry` on the final `uv sync`) so the images ship telemetry-ready — driver-side traces and metrics work out of the box. Unconditional, matching the mcore/automodel/modelopt extras (no build-arg gate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
Process-global OpenTelemetry lifecycle for NeMo-RL, built on nemo-lens: - config.py: TelemetryConfig, the optional `telemetry:` block of MasterConfig. - setup.py: init_telemetry_driver() (runs before init_ray(), exports settings as NEMO_RL_OTEL_* env so workers inherit them; raw env overrides YAML), init_telemetry_worker(), get_telemetry(), shutdown_telemetry(). - span_groups.py: RLSpanGroup presets; `per_step` omits `job` so each step is its own bounded root trace. - _fallbacks.py: no-op shims when nemo-lens is not installed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
Add group-gated spans to GRPO (sync and async), PPO, SFT, DPO, RM and distillation for the phases each has (step, data_processing, rollout, generation, logprob, reward, advantage, policy/value update, checkpoint, evaluate), plus a job span per trainer. Spans wrap the existing timer.time() blocks without re-indenting the bodies. Each run_*.py calls init_telemetry_driver() before init_ray() and shutdown_telemetry() at exit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
Driver-side rl.vllm.generate / generate_text spans nest under the rollout span, with gen_ai.* token/latency metrics. Adds opt-in vLLM-native OTLP engine tracing (NEMO_RL_OTEL_VLLM_NATIVE_TRACING), wired by inspecting the vLLM EngineArgs and degrading gracefully when the installed vLLM lacks the args. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
Logger.log_metrics tees the standard train-prefix scalars (reward, loss, grad_norm, learning_rate, throughput, ...) into rl.* metrics while exporting. The mapping lives in nemo_rl/telemetry/metrics.py so it stays importable and testable without the heavy training stack. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
Cover span-group presets/resolution, the no-op fallbacks (lens absent), the config->env translation (env-wins), driver setup + resource attributes, the metrics mapping, and in-memory span/metric assertions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
Seven-page guide under docs/observability/ (index, configuration, span-groups, metrics, vllm-tracing, observability-stack, extending), a docs/index.md toctree entry, and a nemo_rl/telemetry/README.md module index. Backend-agnostic: exports OTLP to any OTLP-compatible backend or an OpenTelemetry Collector. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Ahmad Kiswani <kiswani.ahmad@gmail.com>
rrs45
reviewed
Jul 17, 2026
| del baseline | ||
| del std | ||
|
|
||
| with timer.time("data_processing"): |
rrs45
reviewed
Jul 17, 2026
| # Sample trajectories from replay buffer | ||
| print("📦 Sampling from replay buffer...") | ||
| with timer.time("exposed_generation"): | ||
| with ( |
There was a problem hiding this comment.
This may not be the right place for this metric since for async, the rollout is occurring earlier in trajectory_collector, here it is mainly collecting the buffer and not generation
rrs45
reviewed
Jul 17, 2026
|
|
||
| # Measure pending-generation wait as exposed_generation time | ||
| print("🔄 Coordinating with trajectory collector before refit...") | ||
| with timer.time("exposed_generation"): |
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.
What does this PR do ?
Adds optional OpenTelemetry instrumentation (distributed traces + metrics) across the NeMo-RL training loops, vLLM generation, and metrics logging, built on the shared nemo-lens library. Telemetry is fully optional — when nemo-lens is not installed (or
telemetry.enabledis false) every instrumentation site degrades to a ~0-cost no-op vianemo_rl/telemetry/_fallbacks.py.Highlights:
nemo_rl/telemetry/):TelemetryConfig(thetelemetry:block ofMasterConfig), the driver/worker lifecycle (init_telemetry_driverruns beforeinit_ray()and exportsNEMO_RL_OTEL_*env so Ray workers inherit it; raw env overrides YAML),RLSpanGrouppresets, and the metrics tee.jobspan per trainer. Spans wrap the existingtimer.time()blocks with no body re-indentation.rl.vllm.generate/generate_textspans (nested under rollouts) +gen_ai.*token/latency metrics, plus opt-in vLLM-native OTLP engine tracing (NEMO_RL_OTEL_VLLM_NATIVE_TRACING).Logger.log_metricstees the standardtrain-prefix scalars (reward, loss, grad_norm, learning_rate, throughput, …) intorl.*metrics.telemetryextra (nemo-lens[sdk]); the release Dockerfiles sync it into the driver venv so images ship telemetry-ready.tests/unit/telemetry/and a 7-pagedocs/observability/guide (+nemo_rl/telemetry/README.md).Backend-agnostic: exports OTLP to any OTLP-compatible backend or an OpenTelemetry Collector via the standard
OTEL_EXPORTER_OTLP_*env vars; console/JSON output viaNEMO_RL_OTEL_EXPORTER=console.Issues
N/A
Usage
Enable telemetry and point it at a backend (or the console). No code changes to your run — just env or the
telemetry:config block:Or in the run config:
You then get
rl.grpo.*spans (step, collect_rollouts, compute_logprobs, …),rl.vllm.generatespans, andrl.*metrics (rl.reward.mean,rl.policy_loss,rl.grad_norm,rl.tokens_per_sec, …).Before your PR is "Ready for review"
Pre checks:
tests/unit/telemetry/— span-group presets/resolution, lens-absent fallbacks, config→env translation, driver setup + resource attrs, metrics mapping, and in-memory span/metric assertions)docs/observability/7-page guide +docs/index.mdtoctree +nemo_rl/telemetry/README.md)Additional Information
opentelemetry-apiis imported at module load; the SDK + exporters install via thetelemetryextra / the release image. No hard runtime dependency, no import-time cost when disabled (gate check only).NEMO_RL_OTEL_*env vars (withNEMO_LENS_*fallback) plus thetelemetry:YAML block; raw env always overrides YAML. Endpoint / protocol / headers are the standardOTEL_EXPORTER_OTLP_*vars, so any backend works.grad_norm/learning_rate/tokens_per_secmetrics rely on additive gauges added to nemo-lensrecord_rl_metrics(separate nemo-lens change); without them those specific metrics are skipped and everything else is unaffected.