Skip to content

Log capture health so a video outage points at a layer - #108

Merged
leandropineda merged 4 commits into
mainfrom
feat/video-health-counters
Jul 30, 2026
Merged

Log capture health so a video outage points at a layer#108
leandropineda merged 4 commits into
mainfrom
feat/video-health-counters

Conversation

@leandropineda

@leandropineda leandropineda commented Jul 29, 2026

Copy link
Copy Markdown
Member

Stacked on #107. Last of the video train.

When video stops, nothing in the logs says whether the camera went away, the platform never asked for a stream, or frames were captured and lost downstream — diagnosing it meant attaching to a running process.

The capture thread logs one line per minute:

Capture health: grabbed=1800 served=60 stale=0 reopens=0 in the last 60s

No line at all → the platform never loaded the camera module. grabbed=0 → stream unreachable. Grabbed but not served → the streamer isn't consuming. Served with nothing visible → MQTT side. The same signals are exposed as OTEL counters next to the existing publish instruments, so they surface through the Prometheus endpoint connector-python already ships.

Also adds the Camera streaming README section the train was missing: the video extra, how to register a camera, the OPENCV_FFMPEG_CAPTURE_OPTIONS line RTSP deployments need (rtsp_transport;tcp|timeout;3000000 — without a timeout a dead stream waits on OpenCV's 30s watchdog), and a table of every setting the train introduced (stale_frame_seconds, api_preference, REOPEN_BACKOFF_SECONDS, HEALTH_LOG_SECONDS). Documented here rather than in #105 so all the knobs land in one place; happy to move it if you'd rather each PR carried its own.

Tests: 1 new case. Suite green (151), flake8/black clean.

@miguelgarcia miguelgarcia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this one. LGTM

@leandropineda
leandropineda force-pushed the feat/video-health-counters branch from ef4dc55 to 1b830c5 Compare July 29, 2026 22:41
@leandropineda
leandropineda force-pushed the fix/video-frame-staleness branch 2 times, most recently from a489c23 to ec99000 Compare July 29, 2026 22:51
@leandropineda
leandropineda force-pushed the feat/video-health-counters branch 2 times, most recently from 42fe0e3 to 559e0cd Compare July 29, 2026 22:55
Base automatically changed from fix/video-frame-staleness to main July 29, 2026 23:01
When video stops there is nothing in the logs to say whether the camera
went away, the platform never asked for a stream, or frames were captured
and lost downstream. Diagnosing it meant attaching to a running process.

The capture thread now logs one line per minute -- grabbed, served, stale,
reopens -- and the same signals are exposed as OTEL counters next to the
existing publish instruments, so they surface through the Prometheus
endpoint connector-python already ships.

Tests: 1 new case in test_video.py.
The README never mentioned video: not the extra to install, not how to
register a camera, and not the OPENCV_FFMPEG_CAPTURE_OPTIONS that decide how
quickly a dead stream is noticed. Covers the settings the video train adds
(stale_frame_seconds, api_preference, the reopen backoff and the health log)
in one place, next to the metrics section that now carries the new counters.
Two limitations worth stating where the code is, not only in review
threads: the platform's per-camera rate/quality arrives in cameras_config
via modules/set_state and is still ignored, and the drain loop races
through non-live sources because grab() does not block on them.
@leandropineda
leandropineda force-pushed the feat/video-health-counters branch from 559e0cd to 874fef7 Compare July 29, 2026 23:02
The test set stale_frame_seconds to 0.0 and expected the next read to be
withheld, but the check is age > window and the capture thread was still
refreshing the frame: on a coarse clock the age landed at exactly 0.0, so
the frame was served and the assertion saw 2 instead of 1 (Windows 3.12).

The capture thread is stopped first, then the buffered frame is aged past
the window explicitly. 30 consecutive runs pass.
@leandropineda
leandropineda merged commit 9a65d6c into main Jul 30, 2026
24 checks passed
@leandropineda
leandropineda deleted the feat/video-health-counters branch July 30, 2026 00:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants