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>
47 lines
1.6 KiB
Python
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}]
|