Files
awoooi/apps/api/scripts/audit_ux_sentry.py
OG T d9a6f9d066 feat(api): Sentry Session Replay UX 自動監控
Phase 19 UX 監控 - 善用 Sentry Session Replay:
- SentryService: 新增 list_replays, get_ux_audit_summary
- 偵測: 憤怒點擊 (Rage Clicks) + 死亡點擊 (Dead Clicks)
- 偵測: 有錯誤的 Session Replay
- 偵測: UI 相關錯誤 (TypeError/render)
- API: GET /api/v1/errors/ux-audit 端點
- 腳本: audit_ux_sentry.py CLI 工具

統帥回饋: "AI都要全自動化!" 

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-29 01:48:59 +08:00

123 lines
3.6 KiB
Python
Raw Permalink 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
"""
Sentry UX Audit Script
======================
使用 Sentry Session Replay + Error Data 自動審計 UI/UX 問題
執行方式:
cd apps/api
python scripts/audit_ux_sentry.py
輸出:
- 有錯誤的 Session Replay
- 憤怒點擊 (Rage Clicks) 統計
- 死亡點擊 (Dead Clicks) 統計
- UI 相關錯誤列表
版本: v1.0
建立: 2026-03-29 (台北時區)
建立者: Claude Code (Phase 19 UX 監控)
"""
import asyncio
import json
import sys
from pathlib import Path
# 添加專案路徑
sys.path.insert(0, str(Path(__file__).parent.parent))
from src.services.sentry_service import SentryService
async def main():
"""執行 UX 審計"""
print("=" * 60)
print("AWOOOI UX Audit via Sentry Session Replay")
print("=" * 60)
print()
service = SentryService()
# 檢查連線
projects = await service.list_projects()
if not projects:
print("❌ 無法連線 Sentry API請檢查:")
print(" - SENTRY_SELF_HOSTED_URL")
print(" - SENTRY_AUTH_TOKEN")
print(" - SENTRY_ORG")
return
print(f"✅ Sentry 連線成功,找到 {len(projects)} 個專案")
print()
# 取得 UX 審計摘要
print("📊 執行 UX 審計...")
print("-" * 60)
summary = await service.get_ux_audit_summary()
# 輸出摘要
print()
print("🔍 UX 問題摘要:")
print(f" 有錯誤的 Replay 數: {summary['replays_with_errors']}")
print(f" 憤怒點擊 (Rage Clicks): {summary['rage_clicks']}")
print(f" 死亡點擊 (Dead Clicks): {summary['dead_clicks']}")
print(f" UI 錯誤數: {summary['ui_errors']}")
print()
# 輸出詳情
if summary["details"]:
print("📝 問題詳情:")
print("-" * 60)
for i, detail in enumerate(summary["details"][:15], 1): # 最多 15 筆
detail_type = detail.get("type", "unknown")
if detail_type == "replay_with_errors":
print(f"{i}. 🎥 Replay 有 {detail.get('error_count', 0)} 個錯誤")
print(f" URL: {detail.get('url', 'N/A')}")
urls = detail.get("urls", [])
if urls:
print(f" 訪問頁面: {', '.join(urls[:2])}")
print()
elif detail_type == "ui_error":
print(f"{i}. 🐛 UI Error: {detail.get('title', 'N/A')[:60]}...")
print(f" 發生次數: {detail.get('count', 0)}")
print(f" URL: {detail.get('url', 'N/A')}")
print()
else:
print("✨ 太棒了!目前沒有檢測到明顯的 UX 問題")
print()
# 總結與建議
print("=" * 60)
total_issues = (
summary["replays_with_errors"] +
summary["ui_errors"]
)
if total_issues > 10:
print("🔴 UX 健康度: 差 - 需要立即處理")
print(" 建議: 優先修復 UI Error然後檢視 Rage Click Replay")
elif total_issues > 3:
print("🟡 UX 健康度: 普通 - 有改善空間")
print(" 建議: 逐一檢視問題 Replay 找出根因")
else:
print("🟢 UX 健康度: 良好")
print(" 建議: 持續監控,設置 Alert 自動通知")
print()
print("💡 查看完整 Session Replay:")
print(f" {service.base_url}/organizations/{service.org}/replays/")
print()
# 輸出 JSON (供 CI 使用)
json_output = Path(__file__).parent / "ux_audit_result.json"
with open(json_output, "w") as f:
json.dump(summary, f, indent=2, ensure_ascii=False)
print(f"📄 JSON 結果已保存: {json_output}")
if __name__ == "__main__":
asyncio.run(main())