From 66a21e0bc3813249d9e4fe8dd420fca4dbfc0f32 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 30 Apr 2022 11:10:20 -0500 Subject: [PATCH] Add basic system health data to the recorder (#71086) --- .../components/recorder/run_history.py | 7 ++++ .../components/recorder/strings.json | 8 ++++ .../components/recorder/system_health.py | 24 ++++++++++++ .../components/recorder/translations/en.json | 8 ++++ .../components/recorder/test_system_health.py | 38 +++++++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 homeassistant/components/recorder/strings.json create mode 100644 homeassistant/components/recorder/system_health.py create mode 100644 homeassistant/components/recorder/translations/en.json create mode 100644 tests/components/recorder/test_system_health.py diff --git a/homeassistant/components/recorder/run_history.py b/homeassistant/components/recorder/run_history.py index 3a76eef3c83..783aff89c17 100644 --- a/homeassistant/components/recorder/run_history.py +++ b/homeassistant/components/recorder/run_history.py @@ -53,6 +53,13 @@ class RunHistory: """Return the time the recorder started recording states.""" return self._recording_start + @property + def first(self) -> RecorderRuns: + """Get the first run.""" + if runs_by_timestamp := self._run_history.runs_by_timestamp: + return next(iter(runs_by_timestamp.values())) + return self.current + @property def current(self) -> RecorderRuns: """Get the current run.""" diff --git a/homeassistant/components/recorder/strings.json b/homeassistant/components/recorder/strings.json new file mode 100644 index 00000000000..72fcf322c31 --- /dev/null +++ b/homeassistant/components/recorder/strings.json @@ -0,0 +1,8 @@ +{ + "system_health": { + "info": { + "oldest_recorder_run": "Oldest Run Start Time", + "current_recorder_run": "Current Run Start Time" + } + } +} diff --git a/homeassistant/components/recorder/system_health.py b/homeassistant/components/recorder/system_health.py new file mode 100644 index 00000000000..23fb760e898 --- /dev/null +++ b/homeassistant/components/recorder/system_health.py @@ -0,0 +1,24 @@ +"""Provide info to system health.""" + +from homeassistant.components import system_health +from homeassistant.core import HomeAssistant, callback + +from . import get_instance + + +@callback +def async_register( + hass: HomeAssistant, register: system_health.SystemHealthRegistration +) -> None: + """Register system health callbacks.""" + register.async_register_info(system_health_info) + + +async def system_health_info(hass: HomeAssistant): + """Get info for the info page.""" + instance = get_instance(hass) + run_history = instance.run_history + return { + "oldest_recorder_run": run_history.first.start, + "current_recorder_run": run_history.current.start, + } diff --git a/homeassistant/components/recorder/translations/en.json b/homeassistant/components/recorder/translations/en.json new file mode 100644 index 00000000000..a44ecd3c1d6 --- /dev/null +++ b/homeassistant/components/recorder/translations/en.json @@ -0,0 +1,8 @@ +{ + "system_health": { + "info": { + "current_recorder_run": "Current Run Start Time", + "oldest_recorder_run": "Oldest Run Start Time" + } + } +} \ No newline at end of file diff --git a/tests/components/recorder/test_system_health.py b/tests/components/recorder/test_system_health.py new file mode 100644 index 00000000000..75abc2b6ae1 --- /dev/null +++ b/tests/components/recorder/test_system_health.py @@ -0,0 +1,38 @@ +"""Test recorder system health.""" + +from unittest.mock import patch + +from homeassistant.components.recorder import get_instance +from homeassistant.core import HomeAssistant +from homeassistant.setup import async_setup_component + +from .common import async_wait_recording_done + +from tests.common import SetupRecorderInstanceT, get_system_health_info + + +async def test_recorder_system_health(hass, recorder_mock): + """Test recorder system health.""" + assert await async_setup_component(hass, "system_health", {}) + await async_wait_recording_done(hass) + info = await get_system_health_info(hass, "recorder") + instance = get_instance(hass) + assert info == { + "current_recorder_run": instance.run_history.current.start, + "oldest_recorder_run": instance.run_history.first.start, + } + + +async def test_recorder_system_health_crashed_recorder_runs_table( + hass: HomeAssistant, async_setup_recorder_instance: SetupRecorderInstanceT +): + """Test recorder system health with crashed recorder runs table.""" + with patch("homeassistant.components.recorder.run_history.RunHistory.load_from_db"): + assert await async_setup_component(hass, "system_health", {}) + instance = await async_setup_recorder_instance(hass) + await async_wait_recording_done(hass) + info = await get_system_health_info(hass, "recorder") + assert info == { + "current_recorder_run": instance.run_history.current.start, + "oldest_recorder_run": instance.run_history.current.start, + }