zcbot/scripts/diag_toolfail_scan.py

43 lines
1.8 KiB
Python

"""跑 core.toolfail.scan_tool_failures,打印近 N 天工具失败聚集 TOP。
用法:.venv/Scripts/python.exe scripts/diag_toolfail_scan.py [days] [top]
"""
import os
import sys
from pathlib import Path
env = Path(__file__).resolve().parent.parent / ".env"
for line in env.read_text(encoding="utf-8").splitlines():
s = line.strip()
if s.startswith("ZCBOT_DB_URL=") and not s.startswith("#"):
os.environ["ZCBOT_DB_URL"] = s.split("=", 1)[1].strip()
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from core.toolfail import scan_tool_failures # noqa: E402
days = float(sys.argv[1]) if len(sys.argv) > 1 else 7
top = int(sys.argv[2]) if len(sys.argv) > 2 else 10
# 用低阈值,拿到完整聚集再自己排 —— 巡检默认 min_count=5/min_tasks=2
# scan 内部已按 (count_24h, count) 降序 = 近24h活跃在前
clusters = scan_tool_failures(days=days, min_count=3, min_tasks=1)
print(f"{days:g} 天:命中 {len(clusters)} 类聚集(阈值 count>=3, tasks>=1)\n")
hdr = f"{'#':>2} {'tool':<14} {'kind':<10} {'cnt':>5} {'24h':>4} {'tsk':>4} {'usr':>4} signature"
print(hdr)
print("-" * len(hdr))
for i, c in enumerate(clusters[:top], 1):
print(
f"{i:>2} {c['tool'][:14]:<14} {c['kind']:<10} {c['count']:>5} "
f"{c['count_24h']:>4} {c['task_count']:>4} {c['user_count']:>4} "
f"{c['signature'][:80]}"
)
print("\n===== 前 3 聚集详情 =====")
for i, c in enumerate(clusters[:3], 1):
print(f"\n--- #{i} [{c['tool']}/{c['kind']}] x{c['count']} "
f"(近24h {c['count_24h']}, task {c['task_count']}, user {c['user_count']}) ---")
print(f" 首次: {c['first_at']} 最近: {c['last_at']}")
print(f" daily(旧→新): {c['daily']}")
print(f" 签名: {c['signature']}")
print(f" 样例: {c['sample'][:500]}")