#!/usr/bin/env python3 # -*- coding: utf-8 -*- r'''分析 2 小时长测数据(列格式:时间戳 \t 状态码 \t 毫秒)。 上一版解析写错了 —— 它把任何 3 位数字都当状态码, 于是毫秒(921、968…)也被算成状态码,可用率算出来只有 84.8%, 是**假数字**。这里改成按列位置取。 ''' from __future__ import annotations import sys from collections import Counter from pathlib import Path path = Path(sys.argv[1] if len(sys.argv) > 1 else "/root/long2h_health.tsv") if not path.is_file(): print(" 文件不存在: %s" % path) raise SystemExit(0) rows = [] bad = 0 for line in path.read_text(encoding="utf-8", errors="replace").splitlines(): line = line.strip() if not line: continue parts = line.split("\t") if len(parts) < 3: bad += 1 continue stamp, code, ms = parts[0], parts[1].strip(), parts[2].strip() try: rows.append((stamp, code, float(ms))) except ValueError: bad += 1 print(" 样本 %d 条(解析不了 %d 条)" % (len(rows), bad)) if not rows: raise SystemExit(0) print(" 时间范围: %s -> %s" % (rows[0][0], rows[-1][0])) codes = Counter(c for _s, c, _m in rows) total = len(rows) ok = codes.get("200", 0) print() print(" ── HTTP 状态分布 ──") for c, n in codes.most_common(): print(" %-6s %4d 次 %5.1f%%" % (c, n, n * 100.0 / total)) print(" " + "-" * 30) print(" 可用率: %d/%d = %.2f%%" % (ok, total, ok * 100.0 / total)) # 只看成功的耗时(失败的那些耗时没有意义) good = sorted(m for _s, c, m in rows if c == "200") if good: def p(q): return good[min(int(len(good) * q), len(good) - 1)] print() print(" ── 成功请求耗时(毫秒)──") print(" 最小 %.0f 中位 %.0f P90 %.0f P99 %.0f 最大 %.0f" % (good[0], good[len(good) // 2], p(0.9), p(0.99), good[-1])) # 如果还有第 4 列及以后(连接数之类),也统计一下 extra_cols = set() for line in path.read_text(encoding="utf-8", errors="replace").splitlines(): p = line.strip().split("\t") if len(p) > 3: extra_cols.add(len(p)) if extra_cols: print() print(" (文件里还有更多列,最多 %d 列)" % max(extra_cols)) fails = [(s, c, m) for s, c, m in rows if c != "200"] print() if fails: print(" ── 失败样本(共 %d 条)──" % len(fails)) for s, c, m in fails[:15]: print(" %s HTTP %-5s %.0fms" % (s, c, m)) if len(fails) > 15: print(" … 还有 %d 条" % (len(fails) - 15)) # 失败时间分布(按 10 分钟分桶) print() print(" ── 失败时刻分布(按小时)──") hours = Counter(s.split(" ")[1].split(":")[0] if " " in s else s[:2] for s, _c, _m in fails) for h in sorted(hours): print(" %s 点 %d 次" % (h, hours[h])) else: print(" ✓ 全程没有非 200 —— 2 小时 100% 可用")