diff --git a/app/main.py b/app/main.py index 4a8cf27..b7dd60f 100644 --- a/app/main.py +++ b/app/main.py @@ -22,6 +22,8 @@ OMNIROUTE_URL = os.environ.get("OMNIROUTE_URL", "http://192.168.1.101:20128") OMNIROUTE_KEY = os.environ.get("OMNIROUTE_API_KEY", "") ARENA_CACHE_TEXT = os.environ.get("ARENA_CACHE_TEXT", "/data/arena_text.json") ARENA_CACHE_AGENT = os.environ.get("ARENA_CACHE_AGENT", "/data/arena_agent.json") +# Сколько последних проверок показывать сегментами в колонке Uptime. +HISTORY_LIMIT = int(os.environ.get("HISTORY_LIMIT", "40")) # ─── DB setup ─────────────────────────────────────────────────────────────── @@ -352,7 +354,7 @@ def model_stats(db: sqlite3.Connection, model_id: str, hours: int = 24) -> dict: ).fetchone() rows = db.execute( - "SELECT ok FROM checks WHERE model_id=? AND checked_at > ?", + "SELECT ok FROM checks WHERE model_id=? AND checked_at > ? ORDER BY checked_at ASC", (model_id, cutoff) ).fetchall() @@ -360,12 +362,16 @@ def model_stats(db: sqlite3.Connection, model_id: str, hours: int = 24) -> dict: success = sum(1 for r in rows if r["ok"]) pct = round(100 * success / total) if total else None + # История последних проверок (старые → новые) для сегментной витрины. + history = [bool(r["ok"]) for r in rows][-HISTORY_LIMIT:] + return { "last_ok": bool(last["ok"]) if last else None, "last_latency_ms": last["latency_ms"] if last else None, "last_checked": last["checked_at"] if last else None, "uptime_pct": pct, "checks_count": total, + "history": history, } @@ -499,8 +505,16 @@ def api_check(model_id: str): (model_id, now, int(ok), latency), ) db.commit() + stats = model_stats(db, model_id) db.close() - return {"model_id": model_id, "ok": ok, "latency_ms": latency, "checked_at": now} + return { + "model_id": model_id, + "ok": ok, + "latency_ms": latency, + "checked_at": now, + "history": stats["history"], + "uptime_pct": stats["uptime_pct"], + } @app.get("/", response_class=HTMLResponse) diff --git a/app/static/index.html b/app/static/index.html index 6cb0edb..8ab1bca 100644 --- a/app/static/index.html +++ b/app/static/index.html @@ -134,11 +134,17 @@ .uptime-low { color: var(--red); } .uptime-none { color: var(--border); } - .uptime-bar-wrap { display: flex; align-items: center; gap: 6px; } - .uptime-bar { - width: 60px; height: 6px; background: var(--border); border-radius: 3px; overflow: hidden; + .uptime-segs { + display: flex; align-items: center; gap: 2px; flex-wrap: nowrap; } - .uptime-bar-fill { height: 100%; border-radius: 3px; transition: width .3s; } + .uptime-seg { + width: 4px; height: 14px; border-radius: 1px; background: var(--border); + flex-shrink: 0; + } + .uptime-seg.ok { background: var(--green); } + .uptime-seg.fail { background: var(--red); } + .uptime-seg.empty { background: transparent; border: 1px dashed var(--border); box-sizing: border-box; } + .uptime-segs .uptime { margin-left: 6px; } .check-btn { background: none; border: 1px solid var(--border); border-radius: 4px; @@ -234,13 +240,28 @@ function statusCell(ok) { return `