Metrics
NeMo Lens ships opinionated metric instruments under nemo.lens.instruments for common observability needs: GenAI inference, RL training, and Gym servers. Training-specific metrics (e.g., megatron.training.loss) live in the consumer project; they are not generic.
Import each record function from its submodule, e.g., from nemo.lens.instruments.rl import record_rl_metrics. Only record_inference_metrics is re-exported at the package level (from nemo.lens.instruments import record_inference_metrics); the RL and Gym functions are available only through their submodules.
The meter argument is the OTel Meter to record on. You can use handle.meter from setup_telemetry(), or grab one directly with get_meter(name="nemo.lens") (from nemo.lens import get_meter).
Architecture
Each module under instruments/ follows the same pattern:
- A module-level
WeakKeyDictionarycaches instruments perMeter, so re-initializing the meter does not leak memory. - A
_get_*_instruments(meter)helper creates (and caches) all instruments for a meter on first call. - A
record_*_metrics(meter, ...)function takes a requiredmeterplus optional per-metric arguments (best passed by keyword) and records only the ones that are notNone.
Callers can record partial data without conditional logic:
Inference with instruments/inference.py
This module emits metrics following the OTel GenAI semantic conventions.
Token usage is labeled with gen_ai.token.type ("input" or "output"); filter on that label in Prometheus or Grafana.
All data points carry gen_ai.operation.name = "text_completion" and gen_ai.provider.name = "nemo" by default; override through the operation_name= or provider_name= args.
NeMo RL with instruments/rl.py
This module emits NeMo RL-specific gauges and histograms in the rl.* namespace.
NeMo Gym with instruments/gym.py
This module emits NeMo Gym server metrics in the gym.* namespace.
Write Custom Instruments
The same WeakKeyDictionary pattern works for project-specific metrics. Megatron’s instruments/training.py (shipped in the Megatron repository, not NeMo Lens) emits megatron.training.* metrics the same way.
If your project has a recurring metric shape, add a module under nemo.lens.instruments.<domain> with:
Choose Between Gauges and Histograms
- Gauge: Point-in-time value. Prometheus shows the last reported value. Good for losses, rates, and counts.
- Histogram: Distribution of values. Prometheus computes quantiles. Good for durations, sizes, and any value where percentiles matter.
- Counter: Monotonic cumulative value. Prometheus shows the rate of change. Use for event counts (
skipped_itersanderrors).
Do not put durations on gauges; you lose the ninety-ninth percentile. Do not put event counts on histograms; the cardinality is incorrect.
Metrics, Span Attributes, and Resource Attributes
Avoid mixing these concepts. Use the following decision table to choose the correct telemetry type:
Specifically, do not record a continuously-varying metric, such as loss, as a span attribute. Doing so wastes span storage, and Jaeger cannot aggregate across spans. Use record_*_metrics() to emit the value as a real metric.