diff --git a/modules/mtr_parser.py b/modules/mtr_parser.py new file mode 100644 index 0000000..8298b6c --- /dev/null +++ b/modules/mtr_parser.py @@ -0,0 +1,94 @@ +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 \ No newline at end of file