test(observability): add production page smoke check
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
This commit is contained in:
@@ -60,6 +60,14 @@ Guard 會檢查:
|
||||
|
||||
### 2. Production 10 頁 HTTP 巡檢
|
||||
|
||||
建議使用 repo 內建腳本:
|
||||
|
||||
```bash
|
||||
python3 scripts/check_observability_pages.py
|
||||
```
|
||||
|
||||
或透過 quick review 選單執行第 7 項。
|
||||
|
||||
```bash
|
||||
python3 - <<'PY'
|
||||
import urllib.request
|
||||
|
||||
88
scripts/check_observability_pages.py
Normal file
88
scripts/check_observability_pages.py
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/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())
|
||||
@@ -16,6 +16,7 @@ NC='\033[0m' # No Color
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CODE_REVIEW_SCRIPT="$PROJECT_ROOT/scripts/code_review.py"
|
||||
OBSERVABILITY_UI_GUARD="$PROJECT_ROOT/scripts/check_observability_ui.py"
|
||||
OBSERVABILITY_PAGE_SMOKE="$PROJECT_ROOT/scripts/check_observability_pages.py"
|
||||
|
||||
# 顯示標題
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
@@ -53,6 +54,16 @@ run_observability_ui_guard() {
|
||||
python3 "$OBSERVABILITY_UI_GUARD"
|
||||
}
|
||||
|
||||
run_observability_page_smoke() {
|
||||
if [ ! -f "$OBSERVABILITY_PAGE_SMOKE" ]; then
|
||||
echo -e "${RED}❌ AI觀測台頁面巡檢不存在: $OBSERVABILITY_PAGE_SMOKE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}🌐 開始 AI觀測台 10頁線上巡檢...${NC}"
|
||||
python3 "$OBSERVABILITY_PAGE_SMOKE"
|
||||
}
|
||||
|
||||
# 顯示選單
|
||||
if [ $# -eq 0 ]; then
|
||||
echo -e "${YELLOW}請選擇操作:${NC}"
|
||||
@@ -62,8 +73,9 @@ if [ $# -eq 0 ]; then
|
||||
echo "4) 安全檢查 (Security Review)"
|
||||
echo "5) 效能檢查 (Performance Review)"
|
||||
echo "6) AI觀測台 UI/UX 防回歸檢查"
|
||||
echo "7) AI觀測台 10頁線上巡檢"
|
||||
echo ""
|
||||
read -p "請輸入選項 (1-6): " choice
|
||||
read -p "請輸入選項 (1-7): " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
@@ -96,6 +108,9 @@ if [ $# -eq 0 ]; then
|
||||
6)
|
||||
run_observability_ui_guard
|
||||
;;
|
||||
7)
|
||||
run_observability_page_smoke
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ 無效選項${NC}"
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user