diff --git a/homeassistant/components/recorder/core.py b/homeassistant/components/recorder/core.py index 716e3a19d09..2ba07e42f49 100644 --- a/homeassistant/components/recorder/core.py +++ b/homeassistant/components/recorder/core.py @@ -12,6 +12,7 @@ import threading import time from typing import Any, TypeVar, cast +from awesomeversion import AwesomeVersion from lru import LRU # pylint: disable=no-name-in-module from sqlalchemy import create_engine, event as sqlalchemy_event, exc, func, select from sqlalchemy.engine import Engine @@ -159,6 +160,7 @@ class Recorder(threading.Thread): self.db_url = uri self.db_max_retries = db_max_retries self.db_retry_wait = db_retry_wait + self.engine_version: AwesomeVersion | None = None self.async_db_ready: asyncio.Future[bool] = asyncio.Future() self.async_recorder_ready = asyncio.Event() self._queue_watch = threading.Event() @@ -1009,12 +1011,13 @@ class Recorder(threading.Thread): ) -> None: """Dbapi specific connection settings.""" assert self.engine is not None - setup_connection_for_dialect( + if version := setup_connection_for_dialect( self, self.engine.dialect.name, dbapi_connection, not self._completed_first_database_setup, - ) + ): + self.engine_version = version self._completed_first_database_setup = True if self.db_url == SQLITE_URL_PREFIX or ":memory:" in self.db_url: diff --git a/homeassistant/components/recorder/strings.json b/homeassistant/components/recorder/strings.json index b475b29a16a..9b616372adf 100644 --- a/homeassistant/components/recorder/strings.json +++ b/homeassistant/components/recorder/strings.json @@ -3,7 +3,9 @@ "info": { "oldest_recorder_run": "Oldest Run Start Time", "current_recorder_run": "Current Run Start Time", - "estimated_db_size": "Estimated Database Size (MiB)" + "estimated_db_size": "Estimated Database Size (MiB)", + "database_engine": "Database Engine", + "database_version": "Database Version" } } } diff --git a/homeassistant/components/recorder/system_health/__init__.py b/homeassistant/components/recorder/system_health/__init__.py index 3250aecf356..8ba68a1649b 100644 --- a/homeassistant/components/recorder/system_health/__init__.py +++ b/homeassistant/components/recorder/system_health/__init__.py @@ -44,17 +44,32 @@ def _get_db_stats(instance: Recorder, database_name: str) -> dict[str, Any]: return db_stats +@callback +def _async_get_db_engine_info(instance: Recorder) -> dict[str, Any]: + """Get database engine info.""" + db_engine_info: dict[str, Any] = {} + if dialect_name := instance.dialect_name: + db_engine_info["database_engine"] = dialect_name.value + if engine_version := instance.engine_version: + db_engine_info["database_version"] = str(engine_version) + return db_engine_info + + async def system_health_info(hass: HomeAssistant) -> dict[str, Any]: """Get info for the info page.""" instance = get_instance(hass) + run_history = instance.run_history database_name = URL(instance.db_url).path.lstrip("/") + db_engine_info = _async_get_db_engine_info(instance) db_stats: dict[str, Any] = {} + if instance.async_db_ready.done(): db_stats = await instance.async_add_executor_job( _get_db_stats, instance, database_name ) - return { - "oldest_recorder_run": run_history.first.start, - "current_recorder_run": run_history.current.start, - } | db_stats + db_runs = { + "oldest_recorder_run": run_history.first.start, + "current_recorder_run": run_history.current.start, + } + return db_runs | db_stats | db_engine_info diff --git a/homeassistant/components/recorder/translations/en.json b/homeassistant/components/recorder/translations/en.json index fb802ff7ff9..c9ceffc7397 100644 --- a/homeassistant/components/recorder/translations/en.json +++ b/homeassistant/components/recorder/translations/en.json @@ -2,6 +2,8 @@ "system_health": { "info": { "current_recorder_run": "Current Run Start Time", + "database_engine": "Database Engine", + "database_version": "Database Version", "estimated_db_size": "Estimated Database Size (MiB)", "oldest_recorder_run": "Oldest Run Start Time" } diff --git a/homeassistant/components/recorder/util.py b/homeassistant/components/recorder/util.py index b010ddfa853..843f0e4b185 100644 --- a/homeassistant/components/recorder/util.py +++ b/homeassistant/components/recorder/util.py @@ -396,8 +396,9 @@ def setup_connection_for_dialect( dialect_name: str, dbapi_connection: Any, first_connection: bool, -) -> None: +) -> AwesomeVersion | None: """Execute statements needed for dialect connection.""" + version: AwesomeVersion | None = None if dialect_name == SupportedDialect.SQLITE: if first_connection: old_isolation = dbapi_connection.isolation_level @@ -465,6 +466,8 @@ def setup_connection_for_dialect( else: _fail_unsupported_dialect(dialect_name) + return version + def end_incomplete_runs(session: Session, start_time: datetime) -> None: """End any incomplete recorder runs.""" diff --git a/tests/components/recorder/test_system_health.py b/tests/components/recorder/test_system_health.py index 8a8d9ea4e80..80997b9df36 100644 --- a/tests/components/recorder/test_system_health.py +++ b/tests/components/recorder/test_system_health.py @@ -24,6 +24,8 @@ async def test_recorder_system_health(hass, recorder_mock): "current_recorder_run": instance.run_history.current.start, "oldest_recorder_run": instance.run_history.first.start, "estimated_db_size": ANY, + "database_engine": SupportedDialect.SQLITE.value, + "database_version": ANY, } @@ -46,6 +48,8 @@ async def test_recorder_system_health_alternate_dbms(hass, recorder_mock, dialec "current_recorder_run": instance.run_history.current.start, "oldest_recorder_run": instance.run_history.first.start, "estimated_db_size": "1.00 MiB", + "database_engine": dialect_name.value, + "database_version": ANY, } @@ -62,4 +66,6 @@ async def test_recorder_system_health_crashed_recorder_runs_table( "current_recorder_run": instance.run_history.current.start, "oldest_recorder_run": instance.run_history.current.start, "estimated_db_size": ANY, + "database_engine": SupportedDialect.SQLITE.value, + "database_version": ANY, }