89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Production smoke check for AI observability pages.
|
|
|
|
The goal is to catch broken observability pages quickly after UI, route,
|
|
schema, or deployment changes. It verifies the ten war-room pages return HTTP
|
|
200 and do not expose raw framework/database errors to the user.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import sys
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
|
|
PAGES = [
|
|
("/observability/overview", "總覽"),
|
|
("/observability/agent_orchestration", "Agent"),
|
|
("/observability/business_intel", "商業"),
|
|
("/observability/host_health", "主機"),
|
|
("/observability/ai_calls", "AI 呼叫"),
|
|
("/observability/budget", "預算"),
|
|
("/observability/promotion_review", "晉升"),
|
|
("/observability/rag_queries", "RAG"),
|
|
("/observability/quality_trend", "品質"),
|
|
("/observability/ppt_audit_history", "PPT"),
|
|
]
|
|
|
|
ERROR_NEEDLES = [
|
|
"Traceback",
|
|
"UndefinedError",
|
|
"ProgrammingError",
|
|
"Internal Server Error",
|
|
'relation "',
|
|
"relation "",
|
|
"查詢失敗:",
|
|
]
|
|
|
|
|
|
def fetch_page(base_url: str, path: str, timeout: int) -> tuple[int, str]:
|
|
request = urllib.request.Request(
|
|
base_url.rstrip("/") + path,
|
|
headers={"User-Agent": "momo-observability-smoke/1.0"},
|
|
)
|
|
with urllib.request.urlopen(request, timeout=timeout) as response:
|
|
html = response.read().decode("utf-8", "ignore")
|
|
return response.status, html
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Smoke check AI observability pages")
|
|
parser.add_argument("--base-url", default="https://mo.wooo.work")
|
|
parser.add_argument("--timeout", type=int, default=12)
|
|
args = parser.parse_args()
|
|
|
|
failed = False
|
|
print(f"Observability page smoke: {args.base_url.rstrip('/')}")
|
|
|
|
for path, label in PAGES:
|
|
try:
|
|
status, html = fetch_page(args.base_url, path, args.timeout)
|
|
except urllib.error.HTTPError as exc:
|
|
print(f"- {label}: HTTP {exc.code}, FAIL")
|
|
failed = True
|
|
continue
|
|
except Exception as exc:
|
|
print(f"- {label}: {type(exc).__name__}: {exc}, FAIL")
|
|
failed = True
|
|
continue
|
|
|
|
found = [needle for needle in ERROR_NEEDLES if needle in html]
|
|
if status != 200 or found:
|
|
print(f"- {label}: HTTP {status}, issues={found or 'bad_status'}, FAIL")
|
|
failed = True
|
|
else:
|
|
print(f"- {label}: HTTP {status}, issues=none")
|
|
|
|
if failed:
|
|
print("Observability page smoke: FAIL")
|
|
return 1
|
|
|
|
print("Observability page smoke: PASS")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|