94 lines
No EOL
2.8 KiB
Python
94 lines
No EOL
2.8 KiB
Python
import statistics
|
|
|
|
class MtrHop:
|
|
def __init__(self, idx):
|
|
self.idx = idx
|
|
self.host = '???'
|
|
self.timings = []
|
|
self.received_count = 0
|
|
|
|
class MtrParser:
|
|
def __init__(self):
|
|
self.hops = {}
|
|
|
|
def update(self, line):
|
|
parts = line.strip().split()
|
|
if len(parts) < 3:
|
|
return
|
|
|
|
type, idx_str, value = parts[0], parts[1], parts[2]
|
|
|
|
if type not in ('h', 'd', 'p'):
|
|
return
|
|
|
|
try:
|
|
idx = int(idx_str)
|
|
except ValueError:
|
|
return
|
|
|
|
if idx not in self.hops:
|
|
self.hops[idx] = MtrHop(idx)
|
|
|
|
hop = self.hops[idx]
|
|
if type == 'h':
|
|
hop.host = value
|
|
elif type == 'p':
|
|
hop.received_count += 1
|
|
try:
|
|
hop.timings.append(float(value) / 1000.0)
|
|
except ValueError:
|
|
pass
|
|
|
|
def render_table(self):
|
|
if not self.hops:
|
|
return ""
|
|
|
|
sorted_hops = sorted(self.hops.values(), key=lambda h: h.idx)
|
|
|
|
if len(sorted_hops) >= 2 and sorted_hops[-1].host == sorted_hops[-2].host:
|
|
sorted_hops.pop(-1)
|
|
|
|
col_widths = {'host': 43, 'loss': 7, 'snt': 5, 'last': 7, 'avg': 7, 'best': 7, 'wrst': 7, 'stdev': 7}
|
|
header = (
|
|
f"{'Host':<{col_widths['host']}}"
|
|
f"{'Loss%':>{col_widths['loss']}}"
|
|
f"{'Snt':>{col_widths['snt']}}"
|
|
f"{'Last':>{col_widths['last']}}"
|
|
f"{'Avg':>{col_widths['avg']}}"
|
|
f"{'Best':>{col_widths['best']}}"
|
|
f"{'Wrst':>{col_widths['wrst']}}"
|
|
f"{'StDev':>{col_widths['stdev']}}\n"
|
|
)
|
|
output = header
|
|
|
|
for hop in sorted_hops:
|
|
received = hop.received_count
|
|
loss_percent = 0.0
|
|
|
|
if received > 0:
|
|
last, avg, best, worst, stdev = (
|
|
hop.timings[-1],
|
|
statistics.mean(hop.timings),
|
|
min(hop.timings),
|
|
max(hop.timings),
|
|
statistics.stdev(hop.timings) if received > 1 else 0.0,
|
|
)
|
|
else:
|
|
last, avg, best, worst, stdev = 0.0, 0.0, 0.0, 0.0, 0.0
|
|
|
|
host_str = f" {hop.idx:d}.|-- {hop.host}"
|
|
loss_str = f"{loss_percent:.1f}%"
|
|
|
|
row = (
|
|
f"{host_str:<{col_widths['host']}}"
|
|
f"{loss_str:>{col_widths['loss']}}"
|
|
f"{hop.received_count:>{col_widths['snt']}}"
|
|
f"{last:>{col_widths['last']}.1f}"
|
|
f"{avg:>{col_widths['avg']}.1f}"
|
|
f"{best:>{col_widths['best']}.1f}"
|
|
f"{worst:>{col_widths['wrst']}.1f}"
|
|
f"{stdev:>{col_widths['stdev']}.1f}\n"
|
|
)
|
|
output += row
|
|
|
|
return output |