Files
YG_FT/scripts/ops_diagnostics.py
wuyongtao b28cfbc6fa feat: 更新后端平台模块、Compute引擎、前端组件及构建产物
- 更新 backend 平台 API、platform_store、compute_gateway sync
- 更新 compute agent/engine/adapter 及 API
- 更新 Docker 部署配置(app/compute)
- 新增 frontend/src/utils/ 工具模块
- 新增 scripts/ops_diagnostics.py 运维诊断脚本
- 新增 docs/2026-07-23-development-summary.md 开发总结
- 重构 frontend/dist 构建产物(新 hash)
- 更新前端多个视图组件及 API 模块

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 19:32:42 +08:00

105 lines
4.1 KiB
Python

from __future__ import annotations
import json
import os
import sys
import time
from typing import Any
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
def _json_request(url: str, token: str | None = None, timeout: float = 5.0) -> dict[str, Any]:
headers = {"Accept": "application/json"}
if token:
headers["X-Compute-Token"] = token
request = Request(url, headers=headers)
started = time.perf_counter()
try:
with urlopen(request, timeout=timeout) as response:
body = response.read().decode("utf-8", errors="replace")
data = json.loads(body) if body else {}
return {
"ok": 200 <= response.status < 300,
"status": response.status,
"duration_ms": int((time.perf_counter() - started) * 1000),
"data": data,
}
except HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")
return {
"ok": False,
"status": exc.code,
"duration_ms": int((time.perf_counter() - started) * 1000),
"error": body or str(exc),
}
except (URLError, TimeoutError, OSError) as exc:
return {
"ok": False,
"duration_ms": int((time.perf_counter() - started) * 1000),
"error": str(exc),
}
def _postgres_check(database_url: str | None) -> dict[str, Any]:
if not database_url:
return {"ok": False, "skipped": True, "error": "DATABASE_URL is not set"}
try:
import psycopg
except ImportError:
return {"ok": False, "skipped": True, "error": "psycopg is not installed"}
started = time.perf_counter()
try:
with psycopg.connect(database_url.replace("postgresql+psycopg://", "postgresql://"), connect_timeout=5) as conn:
with conn.cursor() as cursor:
cursor.execute(
"""
SELECT table_name
FROM information_schema.tables
WHERE table_schema='public'
AND table_name IN ('users','fine_tune_tasks','compute_nodes','compute_jobs','gpu_allocations')
ORDER BY table_name
"""
)
tables = [row[0] for row in cursor.fetchall()]
return {"ok": len(tables) >= 5, "duration_ms": int((time.perf_counter() - started) * 1000), "tables": tables}
except Exception as exc: # noqa: BLE001 - diagnostics should report instead of crashing
return {"ok": False, "duration_ms": int((time.perf_counter() - started) * 1000), "error": str(exc)}
def main() -> int:
route_prefix = os.getenv("ROUTE_PREFIX", "/modelTF").rstrip("/")
app_base_url = os.getenv("APP_BASE_URL", "http://localhost:17861").rstrip("/")
compute_base_url = os.getenv("COMPUTE_BASE_URL", "").rstrip("/")
compute_token = os.getenv("COMPUTE_SERVICE_TOKEN")
checks: list[dict[str, Any]] = [
{"name": "backend health", **_json_request(f"{app_base_url}{route_prefix}/health")},
{"name": "postgres schema", **_postgres_check(os.getenv("DATABASE_URL"))},
]
if compute_base_url:
checks.extend(
[
{
"name": "compute health",
**_json_request(f"{compute_base_url}{route_prefix}/v1/compute/health", compute_token),
},
{
"name": "compute gpus",
**_json_request(f"{compute_base_url}{route_prefix}/compute/resources/gpus", compute_token),
},
{
"name": "compute jobs",
**_json_request(f"{compute_base_url}{route_prefix}/compute/jobs", compute_token),
},
]
)
else:
checks.append({"name": "compute health", "ok": False, "skipped": True, "error": "COMPUTE_BASE_URL is not set"})
report = {"ok": all(item.get("ok") or item.get("skipped") for item in checks), "checks": checks}
print(json.dumps(report, ensure_ascii=False, indent=2))
return 0 if report["ok"] else 1
if __name__ == "__main__":
sys.exit(main())