nemo_rl.telemetry.vocabulary#

Names shared between the code that produces metrics and the code that exports them.

Every name here has at least two readers on opposite sides of that split, and the module imports nothing so either side can reach it: an owner is free to be a torch-heavy training module, and telemetry is free to be importable without the training stack.

The teed rows in particular live next to the code that produces their keys, not here and not in :mod:nemo_rl.telemetry.metrics: a module that logs "reward" declares rl.reward.mean in the same file, so renaming the key renames the declaration with it and there is no second copy to drift. Owners call :func:register_teed_metrics at import; the rows are collected process-wide and handed to lens once, on the first tee, so an owner that is never imported (ppo.py in a GRPO run) simply declares nothing.

Module Contents#

Classes#

RecordedMetric

A series recorded directly, with no Logger key behind it.

TeedMetric

One Logger key mirrored into OTel, and how it is declared to lens.

Functions#

as_scalar

Coerce a logged value to float, or None when it is not a usable scalar.

registry_key

Registry key for a series name (rl.reward.mean -> reward_mean).

freeze_metrics

Close registration, once the rows have been handed to lens.

_check_not_frozen

register_teed_metrics

Declare rows for teeing, from the module that logs their keys.

teed_metrics

Every row declared so far, in declaration order.

register_recorded_metrics

Declare rows from the module that records them.

recorded_metrics

Every directly-recorded row declared so far, in declaration order.

Data#

API#

nemo_rl.telemetry.vocabulary.METRIC_NAME_PREFIX#

‘rl.’

nemo_rl.telemetry.vocabulary.INIT_TOTAL_CATEGORY#

‘init/total’

nemo_rl.telemetry.vocabulary.RUN_WINDOW_WALL_CLOCK_CATEGORIES: frozenset[str]#

‘frozenset(…)’

nemo_rl.telemetry.vocabulary.as_scalar(value: Any) → Optional[float]#

Coerce a logged value to float, or None when it is not a usable scalar.

Shared by every family that reads a raw Logger dict, so they agree on what counts as a number.

nemo_rl.telemetry.vocabulary.registry_key(name: str) → str#

Registry key for a series name (rl.reward.mean -> reward_mean).

lens keys must be Python identifiers, so the shared prefix goes and the dots become underscores. Derived rather than typed out so a row cannot name its series one thing and record against another.

class nemo_rl.telemetry.vocabulary.RecordedMetric#

A series recorded directly, with no Logger key behind it.

Declared by its owner for the same reason the teed rows are: the module that calls record_metrics for a series is the one that names it.

.. attribute:: name

OTel series name emitted; :func:registry_key derives the key.

.. attribute:: kind

One of lens’s gauge / counter / histogram / up_down_counter.

.. attribute:: unit

UCUM-ish unit string, or empty when dimensionless.

.. attribute:: description

Help text carried to the backend.

name: str#

None

kind: str#

‘gauge’

unit: str = <Multiline-String>#
description: str = <Multiline-String>#
property key: str#

Registry key recorded against.

class nemo_rl.telemetry.vocabulary.TeedMetric#

One Logger key mirrored into OTel, and how it is declared to lens.

.. attribute:: logger_key

Key as it appears in the dict handed to Logger.log_metrics.

.. attribute:: name

OTel series name emitted; :func:registry_key derives the key.

.. attribute:: kind

One of lens’s gauge / counter / histogram / up_down_counter.

.. attribute:: unit

UCUM-ish unit string, or empty when dimensionless.

.. attribute:: description

Help text carried to the backend.

logger_key: str#

None

name: str#

None

kind: str#

‘gauge’

unit: str = <Multiline-String>#
description: str = <Multiline-String>#
property key: str#

Registry key recorded against.

nemo_rl.telemetry.vocabulary._REGISTERED: dict[str, nemo_rl.telemetry.vocabulary.TeedMetric]#

None

nemo_rl.telemetry.vocabulary._FROZEN#

False

nemo_rl.telemetry.vocabulary.freeze_metrics() → None#

Close registration, once the rows have been handed to lens.

Called by ensure_metric_group_registered. lens takes the specs once per process, so a row declared after that is read into the recorded values but was never declared – lens drops it with a single warning and RL says nothing at all.

nemo_rl.telemetry.vocabulary._check_not_frozen(name: str) → None#
nemo_rl.telemetry.vocabulary.register_teed_metrics(
rows: Iterable[nemo_rl.telemetry.vocabulary.TeedMetric],
) → None#

Declare rows for teeing, from the module that logs their keys.

Raises:
  • ValueError – Two rows claim the same logger key or the same series name. Both would be silent otherwise: the first makes one row unreachable, and the second makes two rows record against one instrument.

  • RuntimeError – Registration is already closed – see :func:freeze_metrics.

nemo_rl.telemetry.vocabulary.teed_metrics() → tuple[nemo_rl.telemetry.vocabulary.TeedMetric, ...]#

Every row declared so far, in declaration order.

nemo_rl.telemetry.vocabulary._RECORDED: dict[str, nemo_rl.telemetry.vocabulary.RecordedMetric]#

None

nemo_rl.telemetry.vocabulary.register_recorded_metrics(
rows: Iterable[nemo_rl.telemetry.vocabulary.RecordedMetric],
) → None#

Declare rows from the module that records them.

Raises:
  • ValueError – Two rows claim the same series name with different definitions, which would otherwise have them share one instrument.

  • RuntimeError – Registration is already closed – see :func:freeze_metrics.

nemo_rl.telemetry.vocabulary.recorded_metrics() → tuple[nemo_rl.telemetry.vocabulary.RecordedMetric, ...]#

Every directly-recorded row declared so far, in declaration order.