"""Integration: the covering series index on plugin_metrics (#5490), built after boot against Postgres. It replaces the plain series index, a later boot only checks, and a day of one series is then read from the index alone.""" from __future__ import annotations import asyncio import logging import os import pytest pytestmark = pytest.mark.integration @pytest.fixture def app(): if not os.environ.get("STEWARD_DATABASE_URL"): pytest.skip("needs Postgres") from steward.app import create_app return create_app(testing=False) def test_the_series_index_is_built_once_and_replaces_the_plain_one(app): from sqlalchemy import text from steward.core.metric_index import REPLACES, SERIES_INDEX, ensure_series_index log = logging.getLogger("test") async def _indexes(): async with app.db_sessionmaker() as s: return dict((await s.execute(text( "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'plugin_metrics'"))).all()) async def _go(): first = await ensure_series_index(app._db_engine, log) got = await _indexes() assert SERIES_INDEX in got and REPLACES not in got assert "INCLUDE (value)" in got[SERIES_INDEX] assert await ensure_series_index(app._db_engine, log) == "present" assert first in ("built", "present") # One series over a day is answered from the index alone. async with app.db_sessionmaker() as s: await s.execute(text("SET enable_seqscan = off")) await s.execute(text("SET enable_bitmapscan = off")) plan = "\n".join(r[0] for r in (await s.execute(text( "EXPLAIN SELECT date_trunc('hour', recorded_at), avg(value) FROM plugin_metrics " "WHERE source_module = 'host_agent' AND resource_name = 'x' " "AND metric_name = 'cpu_pct' AND recorded_at >= now() - interval '1 day' " "GROUP BY 1"))).all()) assert f"Index Only Scan using {SERIES_INDEX}" in plan, plan asyncio.run(_go())