mirror of
https://github.com/thatmattlove/hyperglass.git
synced 2026-04-17 21:38:27 +00:00
fix(plugins): improve MikroTik traceroute output deduplication
- Add IPv6 address pattern matching alongside IPv4 - Extract SENT count from traceroute lines to prioritize complete data - Keep lines with highest SENT count (final results) instead of first occurrence - Maintain original hop order while using best data for each IP - Prefer non-timeout results when SENT counts are equal Fixes issues where IPv4 showed early results (SENT=1) instead of final (SENT=3) and IPv6 showed all intermediate steps instead of final consolidated results.
This commit is contained in:
parent
5ace4fdf97
commit
716687db63
1 changed files with 37 additions and 25 deletions
|
|
@ -35,8 +35,7 @@ class MikrotikGarbageOutput(OutputPlugin):
|
||||||
lines = raw_output.splitlines()
|
lines = raw_output.splitlines()
|
||||||
cleaned_lines = []
|
cleaned_lines = []
|
||||||
found_header = False
|
found_header = False
|
||||||
unique_hops = {}
|
hop_data = {} # IP -> (line, sent_count)
|
||||||
hop_order = []
|
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
stripped = line.strip()
|
stripped = line.strip()
|
||||||
|
|
@ -60,34 +59,47 @@ class MikrotikGarbageOutput(OutputPlugin):
|
||||||
found_header = True
|
found_header = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Only include data lines after we've found the header
|
# Only process data lines after we've found the header
|
||||||
if found_header and stripped:
|
if found_header and stripped:
|
||||||
# Try to extract IP address from the line to deduplicate
|
# Try to extract IP address (IPv4 or IPv6) from the line
|
||||||
ip_match = re.match(r'^(\d+\.\d+\.\d+\.\d+)', stripped)
|
ipv4_match = re.match(r'^(\d+\.\d+\.\d+\.\d+)', stripped)
|
||||||
if ip_match:
|
ipv6_match = re.match(r'^([0-9a-fA-F:]+)', stripped) if not ipv4_match else None
|
||||||
ip = ip_match.group(1)
|
|
||||||
if ip not in unique_hops:
|
if ipv4_match or ipv6_match:
|
||||||
unique_hops[ip] = line
|
ip = ipv4_match.group(1) if ipv4_match else ipv6_match.group(1)
|
||||||
hop_order.append(ip)
|
|
||||||
else:
|
# Extract the SENT count from the line (look for pattern like "0% 3" or "100% 2")
|
||||||
# Keep the line with better data (non-timeout over timeout)
|
sent_match = re.search(r'\s+(\d+)%\s+(\d+)\s+', stripped)
|
||||||
if "timeout" not in stripped and "timeout" in unique_hops[ip]:
|
sent_count = int(sent_match.group(2)) if sent_match else 0
|
||||||
unique_hops[ip] = line
|
|
||||||
|
# Keep the line with the highest SENT count (most complete data)
|
||||||
|
if ip not in hop_data or sent_count > hop_data[ip][1]:
|
||||||
|
hop_data[ip] = (line, sent_count)
|
||||||
|
elif sent_count == hop_data[ip][1] and "timeout" not in stripped and "timeout" in hop_data[ip][0]:
|
||||||
|
# If SENT counts are equal, prefer non-timeout over timeout
|
||||||
|
hop_data[ip] = (line, sent_count)
|
||||||
elif "100%" in stripped and "timeout" in stripped:
|
elif "100%" in stripped and "timeout" in stripped:
|
||||||
# This is likely a timeout line without IP - skip standalone timeout lines
|
# Skip standalone timeout lines without IP
|
||||||
continue
|
continue
|
||||||
else:
|
|
||||||
# Keep any other data lines that might be relevant
|
|
||||||
cleaned_lines.append(line)
|
|
||||||
|
|
||||||
# Reconstruct the output
|
# Reconstruct the output with only the best results
|
||||||
if found_header and (unique_hops or any("timeout" not in line for line in cleaned_lines[1:] if line.strip())):
|
if found_header and hop_data:
|
||||||
result_lines = [cleaned_lines[0]] # Header
|
result_lines = [cleaned_lines[0]] # Header
|
||||||
result_lines.extend(unique_hops[ip] for ip in hop_order)
|
|
||||||
# Add any non-IP lines that weren't already included
|
# Sort by the order IPs first appeared, but use the best data for each
|
||||||
for line in cleaned_lines[1:]:
|
seen_ips = []
|
||||||
if line not in result_lines and not any(ip in line for ip in hop_order):
|
for line in lines:
|
||||||
result_lines.append(line)
|
stripped = line.strip()
|
||||||
|
if found_header:
|
||||||
|
ipv4_match = re.match(r'^(\d+\.\d+\.\d+\.\d+)', stripped)
|
||||||
|
ipv6_match = re.match(r'^([0-9a-fA-F:]+)', stripped) if not ipv4_match else None
|
||||||
|
|
||||||
|
if ipv4_match or ipv6_match:
|
||||||
|
ip = ipv4_match.group(1) if ipv4_match else ipv6_match.group(1)
|
||||||
|
if ip not in seen_ips and ip in hop_data:
|
||||||
|
seen_ips.append(ip)
|
||||||
|
result_lines.append(hop_data[ip][0])
|
||||||
|
|
||||||
return "\n".join(result_lines)
|
return "\n".join(result_lines)
|
||||||
|
|
||||||
return raw_output
|
return raw_output
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue