#!/usr/bin/env python3 """ NewAPI 周度评估报告 — 汇总观测数据,输出评估结论 每周日 18:00 由 cron 触发,输出可读报告(非静默,始终输出) 评估维度:可用性 / 延迟 / 路由一致性 替代 omniroute-weekly-report.py(OmniRoute 已于 2026-09-02 关停) """ import json import os import statistics from datetime import datetime, timezone, timedelta STATE_DIR = os.path.expanduser("~/.hermes/newapi-observe") LOG = os.path.join(STATE_DIR, "observations.jsonl") # 评估阈值 LATENCY_WARN_MS = 8000 # 平均延迟超 8s 警告 SUCCESS_RATE_MIN = 0.90 # 成功率低于 90% 警告 def load_observations(days=7): if not os.path.exists(LOG): return [] cutoff = datetime.now(timezone.utc) - timedelta(days=days) obs = [] with open(LOG) as f: for line in f: try: d = json.loads(line) ts = datetime.fromisoformat(d["ts"]) if ts >= cutoff: obs.append(d) except Exception: continue return obs def main(): obs = load_observations(7) n = len(obs) print(f"=== NewAPI 周度评估(最近 7 天)===") print(f"观测次数: {n}") print(f"生成时间: {datetime.now(timezone.utc).isoformat()}") print() if n == 0: print("⚠️ 无观测数据(cron 可能在观测脚本切换期间未运行)") return # 1. 服务可用性 svc_ok = sum(1 for o in obs if o.get("service") == "ok") svc_rate = svc_ok / n print(f"【服务可用性】 {svc_ok}/{n} = {svc_rate*100:.1f}%") # 2. 按模型统计 by_model = {} for o in obs: for t in o.get("tests", []): m = t["model"] if m not in by_model: by_model[m] = {"ok": 0, "total": 0, "latencies": []} by_model[m]["total"] += 1 if t["ok"]: by_model[m]["ok"] += 1 by_model[m]["latencies"].append(t["latency_ms"]) print(f"\n【按模型表现】") for m, d in sorted(by_model.items()): rate = d["ok"] / d["total"] * 100 if d["total"] else 0 if d["latencies"]: avg = statistics.mean(d["latencies"]) p95 = sorted(d["latencies"])[int(len(d["latencies"])*0.95)] if len(d["latencies"]) > 1 else d["latencies"][0] else: avg = p95 = 0 status = "✅" if rate >= SUCCESS_RATE_MIN*100 and avg < LATENCY_WARN_MS else "⚠️" print(f" {status} {m}: {d['ok']}/{d['total']} = {rate:.0f}%, 平均 {avg:.0f}ms, P95 {p95:.0f}ms") # 3. 总体评估 total_tests = sum(d["total"] for d in by_model.values()) total_ok = sum(d["ok"] for d in by_model.values()) overall_rate = total_ok / total_tests * 100 if total_tests else 0 print(f"\n【总体】 {total_ok}/{total_tests} = {overall_rate:.1f}%") if overall_rate < SUCCESS_RATE_MIN*100: print("⚠️ 建议: 检查 NewAPI 上游 channel 健康度") else: print("✅ 评估: NewAPI 表现健康,可作为本地主网关") if __name__ == "__main__": main()