Files
FabledSteward/tests/integration/test_monitor_history.py
T
bvandeusenandClaude Opus 5.5 c6fc02def5
CI / lint (push) Successful in 3s
CI / integration (push) Successful in 1m3s
CI / unit (push) Successful in 1m22s
CI / publish (push) Successful in 1m22s
feat(monitors): a monitor's page reads as a page — response time over 24h, labelled actions, how long, not "ago"; the add form says what each type checks (#5214)
Monitor page: a response-time chart for the last day with failed checks
marked; Edit / Pause / Delete as labelled buttons; the state tile says
"for 29m" instead of "for at least 29m 25s ago"; the check strip fills
its card; no failures is one line, not an empty box; Settings names the
type, target and the actual global interval, with readable field names.

Add monitor: a line under the fields says what the selected type checks
and when it counts as up; Name says it defaults to the target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 15:57:09 -04:00

47 lines
1.6 KiB
Python

"""Integration: a monitor's response-time history averages its checks per
bucket and counts the failed ones (#5214). Two checks share a bucket and must
merge (lesson #5262). Requires STEWARD_DATABASE_URL."""
from __future__ import annotations
import asyncio
import os
import uuid
from datetime import datetime, timedelta, timezone
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_response_history_averages_a_bucket_and_counts_its_failures(app):
from steward.models.monitors import Monitor, MonitorResult
from steward.monitors.service import response_history
now = datetime.now(timezone.utc)
width = 24 * 3600 // 96 # 15 minutes
start = datetime.fromtimestamp((int(now.timestamp()) // width - 2) * width, timezone.utc)
mid = str(uuid.uuid4())
def r(secs, up, ms):
return MonitorResult(monitor_id=mid, checked_at=start + timedelta(seconds=secs), is_up=up, response_ms=ms)
async def go():
async with app.db_sessionmaker() as s:
async with s.begin():
s.add(Monitor(id=mid, name=f"m-{mid[:8]}", type="tcp", target="10.9.9.9"))
async with s.begin():
s.add_all([r(10, True, 10.0), r(70, True, 30.0), r(130, False, None)])
async with s.begin():
return await response_history(s, mid, now)
got = asyncio.run(go())
assert got == [{"at": int(start.timestamp() * 1000), "ms": 20.0, "down": 1}]