Skip to content

Commit 638065f

Browse files
committed
Throttle hardware-trigger wait logs
Reduce log flooding when waiting for hardware triggers by adding throttled logging. Changes in dlclivegui/services/multi_camera_controller.py: - Import time. - Add a new _log_interval_while_waiting_for_trigger_s attribute to SingleCameraWorker. - Replace the direct LOGGER.debug call for expected trigger wait timeouts with a call to _log_trigger_wait_throttled. - Implement _log_trigger_wait_throttled to suppress repeated timeout messages, emit a consolidated debug message, and report how many repeated logs were suppressed. This prevents high-frequency expected poll-timeout logs (common in trigger-waiting modes) from overwhelming the logs.
1 parent f4f502f commit 638065f

1 file changed

Lines changed: 33 additions & 5 deletions

File tree

dlclivegui/services/multi_camera_controller.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import copy
66
import logging
7+
import time
78
from dataclasses import dataclass
89
from threading import Event, Lock
910

@@ -50,6 +51,7 @@ def __init__(self, camera_id: str, settings: CameraSettings):
5051
self._max_consecutive_errors = 5
5152
self._retry_delay = 0.1
5253
self._trigger_timeout_delay = 0.05
54+
self._log_interval_while_waiting_for_trigger_s = 2.0
5355

5456
# Performance logs
5557
self._timing = WorkerTimingStats(
@@ -121,11 +123,7 @@ def run(self) -> None:
121123
# "no trigger pulse arrived during this poll interval".
122124
# This is expected and should not count as a camera failure.
123125
if bool(getattr(self._backend, "waits_for_hardware_trigger", False)):
124-
LOGGER.debug(
125-
"[Worker %s] waiting for hardware trigger: %s",
126-
self._camera_id,
127-
exc,
128-
)
126+
self._log_trigger_wait_throttled(exc)
129127
consecutive_errors = 0
130128

131129
if self._stop_event.wait(self._trigger_timeout_delay):
@@ -275,6 +273,36 @@ def _timing_for_camera(self, camera_id: str) -> WorkerTimingStats:
275273
self._timing_per_cam[camera_id] = timing
276274
return timing
277275

276+
def _log_trigger_wait_throttled(self, exc: BaseException) -> None:
277+
"""Log hardware-trigger wait timeouts at a controlled rate.
278+
279+
In trigger-waiting modes, read timeouts are expected polling misses.
280+
Without throttling, the log can be flooded at ~10-20 messages/sec/camera.
281+
"""
282+
now = time.monotonic()
283+
284+
if now - self._last_trigger_wait_log < self._trigger_wait_log_interval:
285+
self._trigger_wait_suppressed_count += 1
286+
return
287+
288+
suppressed = self._trigger_wait_suppressed_count
289+
self._trigger_wait_suppressed_count = 0
290+
self._last_trigger_wait_log = now
291+
292+
if suppressed:
293+
LOGGER.debug(
294+
"[Worker %s] waiting for hardware trigger: %s (suppressed %d repeated timeout logs)",
295+
self._camera_id,
296+
exc,
297+
suppressed,
298+
)
299+
else:
300+
LOGGER.debug(
301+
"[Worker %s] waiting for hardware trigger: %s",
302+
self._camera_id,
303+
exc,
304+
)
305+
278306
def start(self, camera_settings: list[CameraSettings]) -> None:
279307
"""Start multiple cameras; accepts dataclasses, pydantic models, or dicts."""
280308
if self._running:

0 commit comments

Comments
 (0)