nemo_gym.telemetry.concurrency
nemo_gym.telemetry.concurrency
The live state of Gym’s concurrency limits: the configured limit, the slots in use, and who is waiting.
A queue-wait duration shows that work waited, not why.
A dashboard that shows “limit 100, active 100, queued 75” for each limit answers why:
the limit is full and work is piling up behind it.
MeteredSemaphore is a drop-in asyncio.BoundedSemaphore that keeps those numbers,
and the process observer exports them, by limit:
gym.concurrency.limit: the configured number of slots.gym.concurrency.active: slots held right now.gym.concurrency.available: slots free right now,limit - active.gym.concurrency.queue_depth: callers waiting for a slot right now.gym.concurrency.admission_timeouts_total: waits that ran out of the limit’s admission timeout. Reported only for a limit that has an admission timeout, because no other limit can time out.gym.concurrency.admission_cancelled_total: waits cancelled before a slot was free, for example because the caller’s own request was cancelled.
Every point carries nemo.gym.concurrency.component (ConcurrencyComponent),
nemo.gym.concurrency.limit_name (a name the code chose for what the limit bounds, such as upstream_requests),
and nemo.gym.server.name when the limit belongs to a server.
All three are bounded: no rollout, request, or sandbox ID is ever an attribute.
Limits with the same attributes in one process are summed.
A component without a configured limit creates no MeteredSemaphore, so it reports no series at all rather than a limit of zero.
Acquiring and releasing cost a few integer updates and no OpenTelemetry call.
The exporter’s background thread reads the totals through observable instruments,
which exist only while the process observer runs, that is, while metrics are exported.
Module Contents
Classes
Functions
Data
ADMISSION_CANCELLED_INSTRUMENT
API
Bases: BoundedSemaphore
An asyncio.BoundedSemaphore that counts its slots in use and its waiters for export.
Use it wherever a component has a configured concurrency limit; async with, acquire,
and release behave as on the base class.
Parameters:
The configured number of slots, at least one.
ConcurrencyComponent — The kind of component that owns the limit.
A fixed name for what the limit bounds, such as rollouts or upstream_requests.
The owning server’s configured name, or None outside a server.
How long one caller may wait for a slot before acquire raises
TimeoutError, or None to wait indefinitely. Pass the timeout here rather than wrapping
acquire in asyncio.wait_for, which this class would count as a cancellation.
Slots held right now.
How long one caller may wait for a slot, or None to wait indefinitely.
The metric attributes this limit reports under.
The configured number of slots.
Callers waiting for a slot right now.
Take a slot, waiting for one if all are held.
Raises:
TimeoutError: No slot became free withinadmission_timeout_s.
Return a slot; raises ValueError when no slot is held, as asyncio.BoundedSemaphore does.
Bases: NamedTuple
Bases: NamedTuple
Sum the live limits that share attributes. A garbage-collected limit no longer reports.
Create the gym.concurrency.* instruments on meter. The process observer calls this once per meter.