Developer Referencewebrtc_utils
SystemMonitor
Periodically samples CPU and memory usage via psutil.
The latest sample is exposed on cpu_percent, mem_total, and
mem_used; the optional async on_timer callback fires once per period
with the current timestamp. psutil calls run in a worker thread so
sampling never blocks the event loop.
Attributes
attributeperiod= max(1, int(period))attributeenabled= enabledattributestop_event= asyncio.Event()attributetaskOptional[asyncio.Task]= Noneattributecpu_percentfloat= 0attributemem_totalint= 0attributemem_usedint= 0attributeon_timerOptional[Callable[[float], Awaitable[None]]]= NoneFunctions
func__init__(self, period=1, enabled=True)Source Code
def __init__(self, period: int = 1, enabled: bool = True):
self.period = max(1, int(period))
self.enabled = enabled
self.stop_event = asyncio.Event()
self.task: Optional[asyncio.Task] = None
self.cpu_percent: float = 0
self.mem_total: int = 0
self.mem_used: int = 0
self.on_timer: Optional[Callable[[float], Awaitable[None]]] = Noneparamselfparamperiodint= 1paramenabledbool= TrueReturns
Nonefuncstart(self) -> NoneStarts the sampling task; no-op when disabled.
Source Code
def start(self) -> None:
"""Starts the sampling task; no-op when disabled."""
if not self.enabled:
return
self.stop_event.clear()
self.task = asyncio.create_task(self._monitor_loop())
logger_system.info("System monitor started")paramselfReturns
Nonefunc_get_system_metrics(self) -> Tuple[float, int, int]Returns (cpu_percent, mem_total_bytes, mem_used_bytes); blocking.
Source Code
def _get_system_metrics(self) -> Tuple[float, int, int]:
"""Returns `(cpu_percent, mem_total_bytes, mem_used_bytes)`; blocking."""
cpu = psutil.cpu_percent()
mem = psutil.virtual_memory()
return cpu, mem.total, mem.usedparamselfReturns
typing.Tuple[float, int, int]func_monitor_loop(self) -> NoneSamples until stopped.
Source Code
async def _monitor_loop(self) -> None:
"""Samples until stopped."""
try:
while not self.stop_event.is_set():
self.cpu_percent, self.mem_total, self.mem_used = await asyncio.to_thread(
self._get_system_metrics
)
if self.on_timer:
await self.on_timer(time.time())
try:
await asyncio.wait_for(self.stop_event.wait(), timeout=self.period)
except asyncio.TimeoutError:
pass
except asyncio.CancelledError:
pass
except Exception as e:
logger_system.error(f"System monitor error: {e}", exc_info=True)
finally:
logger_system.debug("System monitor loop exited")paramselfReturns
Nonefuncstop(self) -> NoneSignals the loop to exit and waits for the task to finish.
Source Code
async def stop(self) -> None:
"""Signals the loop to exit and waits for the task to finish."""
self.stop_event.set()
if self.task:
await self.task
logger_system.info("System monitor stopped")paramselfReturns
None