diff --git a/frigate/stats/util.py b/frigate/stats/util.py index 20f9cc2837..6d26d16a62 100644 --- a/frigate/stats/util.py +++ b/frigate/stats/util.py @@ -236,6 +236,15 @@ def skipped_percent(skipped_fps: float, camera_fps: float, enabled: bool) -> flo return round(skipped_fps / camera_fps * 100, 1) +def get_go2rtc_pid(cpu_usages: dict[str, dict[str, Any]]) -> int | None: + """Find the pid of the running go2rtc process in the cpu usages.""" + for pid, usage in cpu_usages.items(): + if usage.get("cmdline", "").split(" ")[0].endswith("/go2rtc"): + return int(pid) + + return None + + def stats_snapshot( config: FrigateConfig, stats_tracking: StatsTrackingTypes, @@ -356,6 +365,14 @@ def stats_snapshot( stats["service"]["storage"]["/dev/shm"] = calculate_shm_requirements(config) + cpu_usages = stats.get("cpu_usages", {}) + + # go2rtc is supervised by s6, so its pid changes when s6 restarts it + go2rtc_pid = get_go2rtc_pid(cpu_usages) + + if go2rtc_pid is not None: + stats_tracking["processes"]["go2rtc"] = go2rtc_pid + stats["processes"] = {} for name, pid in stats_tracking["processes"].items(): stats["processes"][name] = { @@ -364,7 +381,6 @@ def stats_snapshot( # Embed cpu/mem stats into detectors, cameras, and processes # so history consumers don't need the full cpu_usages dict - cpu_usages = stats.get("cpu_usages", {}) for det_stats in stats["detectors"].values(): pid_str = str(det_stats.get("pid", "")) diff --git a/frigate/test/test_go2rtc_pid_stats.py b/frigate/test/test_go2rtc_pid_stats.py new file mode 100644 index 0000000000..9f0c5b763b --- /dev/null +++ b/frigate/test/test_go2rtc_pid_stats.py @@ -0,0 +1,26 @@ +"""Tests for resolving the go2rtc pid from cpu usages.""" + +import unittest + +from frigate.stats.util import get_go2rtc_pid + + +class TestGo2rtcPid(unittest.TestCase): + def test_finds_go2rtc_by_binary_path(self): + cpu_usages = { + "frigate.full_system": {"cpu": "1.0", "mem": "2.0"}, + "100": {"cmdline": "ffmpeg -i rtsp://127.0.0.1:8554/go2rtc_cam"}, + "200": { + "cmdline": "/usr/local/go2rtc/bin/go2rtc -config=/dev/shm/go2rtc.yaml" + }, + "300": {"cmdline": "frigate.recording"}, + } + + self.assertEqual(get_go2rtc_pid(cpu_usages), 200) + + def test_finds_custom_go2rtc_binary(self): + self.assertEqual(get_go2rtc_pid({"42": {"cmdline": "/config/go2rtc"}}), 42) + + def test_returns_none_when_go2rtc_is_not_running(self): + self.assertIsNone(get_go2rtc_pid({"100": {"cmdline": "ffmpeg -i x"}})) + self.assertIsNone(get_go2rtc_pid({}))