mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 11:20:43 +00:00
90 lines
2.9 KiB
Python
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% 可用")
|