Files
ewoooc/scripts/check_observability_pages.py
OoO e7d567c6be
Some checks failed
CD Pipeline / deploy (push) Failing after 4m55s
test(observability): assert page content markers
2026-05-05 15:53:39 +08:00

118 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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"),
]
EXPECTED_MARKERS = {
"/observability/overview": ["觀測台總覽", "主機健康", "AI 呼叫"],
"/observability/agent_orchestration": ["Agent 編排矩陣", "LLM", "MCP", "RAG"],
"/observability/business_intel": ["商業面 × AI", "AI", "競品"],
"/observability/host_health": ["主機健康", "Ollama", "AutoHeal"],
"/observability/ai_calls": ["AI 呼叫", "Provider", "RAG"],
"/observability/budget": ["預算控管", "force", "throttle"],
"/observability/promotion_review": ["RAG 晉升審核", "Promotion", "ai_insights"],
"/observability/rag_queries": ["RAG 召回詳情", "最近 50", "hits"],
"/observability/quality_trend": ["反饋趨勢", "Caller", "蒸餾"],
"/observability/ppt_audit_history": ["PPT 視覺審核", "AiderHeal", "audit"],
}
MIN_HTML_BYTES = 2500
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]
missing_markers = [
marker for marker in EXPECTED_MARKERS.get(path, [])
if marker not in html
]
too_small = len(html.encode("utf-8")) < MIN_HTML_BYTES
if status != 200 or found or missing_markers or too_small:
issues = []
if status != 200:
issues.append("bad_status")
if found:
issues.extend(found)
if missing_markers:
issues.append(f"missing_markers={missing_markers}")
if too_small:
issues.append(f"html_too_small={len(html.encode('utf-8'))}B")
print(f"- {label}: HTTP {status}, issues={issues}, 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())