uploader-bot/scripts/health_check.py

94 lines
3.0 KiB
Python

#!/usr/bin/env python3
import argparse
import asyncio
import json
import logging
from dataclasses import dataclass
from typing import Any, Dict, Optional, Tuple
import aiohttp
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
log = logging.getLogger("health_check")
@dataclass
class HealthReport:
base_url: str
alive: bool
ready: bool
health_status: int
info_status: int
metrics_status: int
details: Dict[str, Any]
async def fetch_json(session: aiohttp.ClientSession, url: str) -> Tuple[int, Dict[str, Any]]:
try:
async with session.get(url) as resp:
status = resp.status
try:
data = await resp.json(content_type=None)
except Exception:
text = await resp.text()
data = {"raw": text}
return status, data
except Exception as e:
return 0, {"error": str(e)}
async def probe(base_url: str, timeout: int = 8) -> HealthReport:
timeout_cfg = aiohttp.ClientTimeout(total=timeout)
async with aiohttp.ClientSession(timeout=timeout_cfg) as session:
details: Dict[str, Any] = {}
async def _g(path: str):
url = f"{base_url.rstrip('/')}{path}"
s, d = await fetch_json(session, url)
details[path] = {"status": s, "data": d}
return s, d
health_s, _ = await _g("/api/system/health")
info_s, _ = await _g("/api/system/info")
metrics_s, _ = await _g("/api/system/metrics")
live_s, _ = await _g("/api/system/live")
ready_s, _ = await _g("/api/system/ready")
alive = live_s in (200, 204)
ready = ready_s in (200, 204)
return HealthReport(
base_url=base_url,
alive=alive,
ready=ready,
health_status=health_s,
info_status=info_s,
metrics_status=metrics_s,
details=details,
)
def main() -> int:
ap = argparse.ArgumentParser(description="Проверка здоровья системы (health/info/metrics/ready/live)")
ap.add_argument("base_url", help="Базовый URL FastAPI, например http://localhost:8000")
ap.add_argument("-t", "--timeout", type=int, default=8)
ap.add_argument("--json", action="store_true", help="Вывод в JSON")
args = ap.parse_args()
report = asyncio.run(probe(args.base_url, timeout=args.timeout))
if args.json:
print(json.dumps(report.__dict__, ensure_ascii=False, indent=2))
else:
print(f"Health check for {report.base_url}")
print(f"- alive={report.alive} ready={report.ready}")
print(f"- /api/system/health: {report.health_status}")
print(f"- /api/system/info: {report.info_status}")
print(f"- /api/system/metrics: {report.metrics_status}")
# Код возврата: 0 если живой и готов, иначе 2
return 0 if (report.alive and report.ready) else 2
if __name__ == "__main__":
raise SystemExit(main())