Files
ykxmz/_build/analyze_2h.py
T

90 lines
2.9 KiB
Python

#!/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% 可用")