import datetime
import glob
import sys

base = sys.argv[1]
threshold_ms = float(sys.argv[2]) if len(sys.argv) > 2 else 1000


def rows(path):
    out = []
    for line in open(path):
        c = line.split()
        if len(c) >= 4 and c[0].count(":") == 2:
            out.append(c)
    return out


def fmt(t):
    return datetime.datetime.fromtimestamp(t).strftime("%H:%M:%S.%f")[:-3]


stalls = []
for f in glob.glob(f"{base}/out/tx.*"):
    for line in open(f):
        c = line.split()
        us = int(c[2])
        end = int(c[4]) + int(c[5]) / 1e6
        if us / 1000 > threshold_ms:
            stalls.append((end - us / 1e6, end, us / 1000))

primary = rows(f"{base}/samples.txt")
standby = rows(f"{base}/samples_standby.txt")


def window(samples, st, en):
    return [x for x in samples if st <= x[0] <= en]


def summarise(samples, cols):
    counts = {}
    for x in samples:
        key = " ".join(x[i] for i in cols)
        counts[key] = counts.get(key, 0) + 1
    return ", ".join(f"{k} x{v}" for k, v in sorted(counts.items(), key=lambda kv: -kv[1])[:4])


print(f"stalls over {threshold_ms:.0f} ms: {len(stalls)}")
for s, e, ms in sorted(stalls):
    st, en = fmt(s + 0.1), fmt(e - 0.05)
    p = window(primary, st, en)
    sb = window(standby, st, en)
    print(f"  {fmt(s)} {ms:.0f}ms primary_samples={len(p)} standby_samples={len(sb)}")
    print(f"    primary (unsent unwritten unflushed walsender syncrep client): {summarise(p, [1, 2, 3, 4, 5, 6])}")
    print(f"    standby (walreceiver startup): {summarise(sb, [3, 4])}")
