@@ -437,16 +437,26 @@ class ProcessGroupResourceUsage:
437437 """Number of processes in the process group."""
438438
439439 net_rx_bytes : int | None = None
440- """Total network bytes received (excluding loopback)."""
440+ """Network bytes received since the previous snapshot (excluding loopback).
441+
442+ ``None`` on the first snapshot (no previous value to diff against).
443+ Note: this is host-wide (per network namespace), not process-group-scoped.
444+ """
441445
442446 net_tx_bytes : int | None = None
443- """Total network bytes transmitted (excluding loopback)."""
447+ """Network bytes transmitted since the previous snapshot (excluding loopback).
448+
449+ ``None`` on the first snapshot (no previous value to diff against).
450+ Note: this is host-wide (per network namespace), not process-group-scoped.
451+ """
444452
445453
446454def _collect_pgrp_stats (
447455 prev_cpu_usec : int | None = None ,
448456 prev_time_usec : int | None = None ,
449- ) -> tuple [ProcessGroupResourceUsage , int | None , int ]:
457+ prev_net_rx_bytes : int | None = None ,
458+ prev_net_tx_bytes : int | None = None ,
459+ ) -> tuple [ProcessGroupResourceUsage , int | None , int , int | None , int | None ]:
450460 """Collect all process-group stats.
451461
452462 Reads CPU, memory (RSS, PSS, private), disk IO from
@@ -459,16 +469,24 @@ def _collect_pgrp_stats(
459469 (used to compute ``cpu_percent``). ``None`` on the first call.
460470 prev_time_usec: Wall-clock µs (``time.monotonic()`` × 1e6) of the
461471 previous snapshot.
472+ prev_net_rx_bytes: Cumulative network RX bytes from the previous
473+ snapshot. ``None`` on the first call.
474+ prev_net_tx_bytes: Cumulative network TX bytes from the previous
475+ snapshot. ``None`` on the first call.
462476
463477 Returns:
464- A tuple of ``(usage, current_cpu_usec, current_time_usec)``.
478+ A tuple of
479+ ``(usage, current_cpu_usec, current_time_usec, current_net_rx_bytes, current_net_tx_bytes)``.
465480 ``current_cpu_usec`` is ``None`` when /proc could not be read.
481+ ``current_net_*_bytes`` are ``None`` when /proc/net/dev could not be read.
466482 """
467483 import time as _time
468484
469485 now_usec = int (_time .monotonic () * 1_000_000 )
470486 result = ProcessGroupResourceUsage (pid = os .getpid (), pgid = os .getpgrp ())
471487 current_cpu_usec : int | None = None
488+ current_net_rx_bytes : int | None = None
489+ current_net_tx_bytes : int | None = None
472490
473491 try :
474492 pgrp = _read_pgrp_stats ()
@@ -492,12 +510,21 @@ def _collect_pgrp_stats(
492510
493511 try :
494512 net = _read_network_bytes ()
495- result .net_rx_bytes = net .rx_bytes
496- result .net_tx_bytes = net .tx_bytes
513+ current_net_rx_bytes = net .rx_bytes
514+ current_net_tx_bytes = net .tx_bytes
515+ if prev_net_rx_bytes is not None and prev_net_tx_bytes is not None :
516+ result .net_rx_bytes = net .rx_bytes - prev_net_rx_bytes
517+ result .net_tx_bytes = net .tx_bytes - prev_net_tx_bytes
497518 except RuntimeError as e :
498519 _warn_once ("net_dev" , "%s" , e )
499520
500- return result , current_cpu_usec , now_usec
521+ return (
522+ result ,
523+ current_cpu_usec ,
524+ now_usec ,
525+ current_net_rx_bytes ,
526+ current_net_tx_bytes ,
527+ )
501528
502529
503530# ---------------------------------------------------------------------------
@@ -528,10 +555,23 @@ async def _loop() -> None:
528555 loop = asyncio .get_running_loop ()
529556 prev_cpu_usec : int | None = None
530557 prev_time_usec : int | None = None
558+ prev_net_rx_bytes : int | None = None
559+ prev_net_tx_bytes : int | None = None
531560 while running :
532561 try :
533- usage , prev_cpu_usec , prev_time_usec = await loop .run_in_executor (
534- None , _collect_pgrp_stats , prev_cpu_usec , prev_time_usec
562+ (
563+ usage ,
564+ prev_cpu_usec ,
565+ prev_time_usec ,
566+ prev_net_rx_bytes ,
567+ prev_net_tx_bytes ,
568+ ) = await loop .run_in_executor (
569+ None ,
570+ _collect_pgrp_stats ,
571+ prev_cpu_usec ,
572+ prev_time_usec ,
573+ prev_net_rx_bytes ,
574+ prev_net_tx_bytes ,
535575 )
536576 await callback (usage )
537577 except Exception :
0 commit comments