From aa0d8cb1b95705a09c0d0318a7e5f2a13e300883 Mon Sep 17 00:00:00 2001 From: Guilherme Costa Date: Fri, 23 Oct 2026 16:30:08 +0100 Subject: [PATCH] fix(network): stop scan and unchanged-state lines flooding the INFO log --- BlocksScreen/lib/network/worker.py | 15 ++++++++++++--- tests/network/test_worker_unit.py | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/BlocksScreen/lib/network/worker.py b/BlocksScreen/lib/network/worker.py index 351e4ba0..07ca0347 100644 --- a/BlocksScreen/lib/network/worker.py +++ b/BlocksScreen/lib/network/worker.py @@ -133,6 +133,8 @@ def __init__(self) -> None: self._stale_logged_gen = -1 # Wi-Fi FAILED count, latched by the StateChanged listener. self._wifi_failures = 0 + # Last logged state minus signal: an unchanged snapshot logs at DEBUG only. + self._last_state_key: tuple | None = None self._asyncio_loop: asyncio.AbstractEventLoop = asyncio.new_event_loop() self._asyncio_thread = threading.Thread( @@ -1021,14 +1023,20 @@ async def _build_current_state(self) -> NetworkState: carrier, vlans = await asyncio.gather( self._has_ethernet_carrier(), self._get_active_vlans() ) - logger.info( - "state: conn=%s ssid='%s' ip=%s wifi=%s eth=%s hotspot=%s sig=%d", + state_key = ( connectivity.name, current_ssid, current_ip or "-", wifi_enabled, eth_connected, hotspot_enabled, + ) + changed = state_key != self._last_state_key + self._last_state_key = state_key + logger.log( + logging.INFO if changed else logging.DEBUG, + "state: conn=%s ssid='%s' ip=%s wifi=%s eth=%s hotspot=%s sig=%d", + *state_key, signal, ) return NetworkState( @@ -1294,7 +1302,8 @@ async def _scan_networks_once(self) -> None: seen_ssids.add(info.ssid) networks.sort(key=lambda n: (-n.network_status, -n.signal_strength)) - logger.info("scan: %d visible of %d AP(s)", len(networks), len(ap_paths)) + # Counts drift on every periodic scan: INFO here flooded the field logs. + logger.debug("scan: %d visible of %d AP(s)", len(networks), len(ap_paths)) self.networks_scanned.emit(networks) async def _request_scan_if_allowed(self) -> None: diff --git a/tests/network/test_worker_unit.py b/tests/network/test_worker_unit.py index f87f2e9d..00a10801 100644 --- a/tests/network/test_worker_unit.py +++ b/tests/network/test_worker_unit.py @@ -74,6 +74,7 @@ def _make_worker(qapp, *, running=True, with_wifi=True, with_wired=False): w._rediscover_gen = 0 w._stale_logged_gen = -1 w._wifi_failures = 0 + w._last_state_key = None w._system_bus = MagicMock(name="mock_system_bus") w._primary_wifi_path = ( "/org/freedesktop/NetworkManager/Devices/2" if with_wifi else "" @@ -120,6 +121,7 @@ def _bare_worker(qapp): w._rediscover_gen = 0 w._stale_logged_gen = -1 w._wifi_failures = 0 + w._last_state_key = None w._system_bus = None w._primary_wifi_path = "" w._primary_wifi_iface = "" @@ -157,6 +159,7 @@ def _make(qapp, *, running=True, wifi=True, wired=True): w._rediscover_gen = 0 w._stale_logged_gen = -1 w._wifi_failures = 0 + w._last_state_key = None w._system_bus = MagicMock(name="mock_bus") w._primary_wifi_path = "/org/freedesktop/NetworkManager/Devices/2" if wifi else "" w._primary_wifi_iface = "wlan0" if wifi else "" @@ -947,6 +950,25 @@ async def test_connected_state(self, qapp): assert state.wifi_enabled is True assert state.current_ssid == "" + @pytest.mark.asyncio + async def test_unchanged_state_logs_at_debug(self, qapp, caplog): + w = _make_worker(qapp) + w._nm = _ProxyFactory(AsyncProxyMock(connectivity=4, wireless_enabled=True)) + w._get_current_ssid = AsyncMock(return_value="BLOCKS") + w._get_current_ip = AsyncMock(return_value="192.168.1.151") + w._is_ethernet_connected = AsyncMock(return_value=False) + w._has_ethernet_carrier = AsyncMock(return_value=False) + w._get_active_vlans = AsyncMock(return_value=[]) + signals = iter([(67, "wpa-psk"), (68, "wpa-psk"), (68, "wpa-psk")]) + w._wifi_signal_and_security = AsyncMock(side_effect=lambda _: next(signals)) + with caplog.at_level(logging.DEBUG, logger=_worker_mod.logger.name): + await w._build_current_state() + await w._build_current_state() # only the signal moved + w._get_current_ip = AsyncMock(return_value="192.168.1.152") + await w._build_current_state() + levels = [r.levelno for r in caplog.records if r.msg.startswith("state:")] + assert levels == [logging.INFO, logging.DEBUG, logging.INFO] + @pytest.mark.asyncio async def test_connected_with_ssid_gets_signal_and_security(self, qapp): w = _make_worker(qapp)