Files
FabledSteward/tests/plugins/docker/test_net_rates.py
T
bvandeusenandClaude Opus 5.5 613ed4e78b
CI / lint (push) Successful in 3s
CI / unit (push) Failing after 1m30s
CI / integration (push) Successful in 1m38s
CI / publish (push) Skipped
feat(traffic): each container's network rate, and each NFS mount's bytes, so a host's traffic has a sender (#6115)
Docker02's outbound traffic tops out the internet connection and Steward
couldn't say who sends it: a container's counters were kept only as a
running total, and NFS traffic belongs to no container.

- Docker ingest turns each running container's cumulative network counters
  into net_rx_bps / net_tx_bps on "<host>/<container>" (net_rates), counting
  from the stored row so a restart of Steward loses nothing; a container
  new, recreated or restarted has no rate until its next snapshot.
- Agent 1.25.0 reads the bytes sent and received per NFS mount from
  mountstats (already parsed for the delays) as tx_bps / rx_bps; Steward
  stores them as nfs_tx_bps / nfs_rx_bps on "<host>:<mount>".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:35:24 -04:00

38 lines
1.7 KiB
Python

"""net_rates: a container's bytes a second, from its cumulative network
counters against the last ones seen for it (#6115). Pure; no DB."""
from datetime import datetime, timedelta, timezone
from plugins.docker.ingest import net_rates
T0 = datetime(2026, 10, 19, 18, 0, tzinfo=timezone.utc)
def _c(name, rx, tx, cid="abc", status="running"):
return {"name": name, "container_id": cid, "status": status,
"net_rx_bytes": rx, "net_tx_bytes": tx}
def test_rates_count_from_the_stored_row_and_then_from_each_snapshot():
before = {"web": (T0, "abc", 1_000, 2_000)}
snaps = [(T0 + timedelta(seconds=10), [_c("web", 11_000, 52_000)]),
(T0 + timedelta(seconds=20), [_c("web", 11_000, 62_000)])]
assert net_rates(before, snaps) == [
(T0 + timedelta(seconds=10), "web", 1_000.0, 5_000.0),
(T0 + timedelta(seconds=20), "web", 0.0, 1_000.0),
]
def test_no_rate_for_a_new_recreated_or_restarted_container_until_its_next_snapshot():
before = {"db": (T0, "old", 100, 100), "app": (T0, "abc", 5_000, 5_000)}
t1, t2 = T0 + timedelta(seconds=10), T0 + timedelta(seconds=20)
snaps = [(t1, [_c("new", 10, 10), _c("db", 200, 200, cid="fresh"), _c("app", 10, 10)]),
(t2, [_c("new", 110, 210), _c("db", 300, 300, cid="fresh"), _c("app", 20, 30)])]
assert net_rates(before, snaps) == [
(t2, "new", 10.0, 20.0), (t2, "db", 10.0, 10.0), (t2, "app", 1.0, 2.0)]
def test_stopped_containers_and_missing_counters_are_skipped():
before = {"web": (T0, "abc", 0, 0), "old": (T0, "abc", 0, 0)}
snaps = [(T0 + timedelta(seconds=10), [_c("web", None, None), _c("old", 9, 9, status="exited")])]
assert net_rates(before, snaps) == []