Skip to content

Conversation

@bryancall
Copy link
Contributor

@bryancall bryancall commented Feb 2, 2026

Summary

A Python tool that displays ATS metrics inline in iTerm2 using imgcat with live updates and multi-host comparison.

Features:

  • Real-time graphs of RPS, latency, cache hit rate, connections
  • Support for 1-4 hosts with different line styles for comparison
  • Collects metrics via JSONRPC Unix socket (batch collection)
  • Dark theme optimized for terminal display
  • Keyboard navigation between metric pages (4 pages)
  • Configurable refresh interval and history window

Requirements:

  • Python 3 with matplotlib
  • iTerm2 (or compatible terminal for inline images)
  • SSH access to remote ATS hosts

Usage:

traffic_grapher.py ats-server1.example.com
traffic_grapher.py ats{1..4}.example.com --interval 2

Test plan

  • Tested with 1, 2, 3, and 4 hosts
  • Verified all 4 metric pages display correctly
  • Confirmed keyboard navigation (h/l, left/right arrows)
  • Tested with --save-png for offline verification

Screenshot

A Python tool that displays ATS metrics inline in iTerm2 using imgcat
with live updates and multi-host comparison.

Features:
- Real-time graphs of RPS, latency, cache hit rate, connections
- Support for 1-4 hosts with different line styles for comparison
- Collects metrics via JSONRPC Unix socket (batch collection)
- Dark theme optimized for terminal display
- Keyboard navigation between metric pages (4 pages)
- Configurable refresh interval and history window

Requirements:
- Python 3 with matplotlib
- iTerm2 (or compatible terminal for inline images)
- SSH access to remote ATS hosts

Usage:
  traffic_grapher.py ats-server1.example.com
  traffic_grapher.py ats{1..4}.example.com --interval 2
@bryancall bryancall self-assigned this Feb 2, 2026
@bryancall bryancall added this to the 10.2.0 milestone Feb 2, 2026
@bryancall bryancall added the Tools label Feb 2, 2026
@bryancall bryancall requested a review from Copilot February 2, 2026 20:41
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

A Python-based traffic monitoring tool that visualizes real-time ATS (Apache Traffic Server) metrics using inline terminal graphics. The tool collects metrics via JSONRPC Unix socket and renders them as time-series graphs directly in iTerm2, supporting multi-host comparison with keyboard-driven navigation.

Changes:

  • New traffic_grapher.py script with real-time metrics visualization
  • Support for 1-4 hosts with distinct line styles for comparison
  • Four pre-configured dashboard pages covering traffic, cache, TLS/HTTP2, and network metrics
  • Dark theme optimized for terminal display with configurable refresh and history

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +325 to +328
# Default path (adjust for your installation)
# Note: awk runs locally to avoid SSH quote escaping issues
METRIC_COMMAND_REMOTE = "/opt/edge/trafficserver/10.0/bin/traffic_ctl metric get {key}"
METRIC_COMMAND_LOCAL = "/opt/edge/trafficserver/10.0/bin/traffic_ctl metric get {key} | awk '{{print $2}}'"
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded installation paths make the tool less portable. Consider making these configurable via command-line arguments or environment variables to support different TrafficServer installations.

Suggested change
# Default path (adjust for your installation)
# Note: awk runs locally to avoid SSH quote escaping issues
METRIC_COMMAND_REMOTE = "/opt/edge/trafficserver/10.0/bin/traffic_ctl metric get {key}"
METRIC_COMMAND_LOCAL = "/opt/edge/trafficserver/10.0/bin/traffic_ctl metric get {key} | awk '{{print $2}}'"
# Default path can be overridden via the TRAFFIC_CTL_PATH environment variable.
# Note: awk runs locally to avoid SSH quote escaping issues
TRAFFIC_CTL_PATH = os.environ.get("TRAFFIC_CTL_PATH", "/opt/edge/trafficserver/10.0/bin/traffic_ctl")
METRIC_COMMAND_REMOTE = f"{TRAFFIC_CTL_PATH} metric get {{key}}"
METRIC_COMMAND_LOCAL = f"{TRAFFIC_CTL_PATH} metric get {{key}} | awk '{{print $2}}'"

Copilot uses AI. Check for mistakes.
Comment on lines +565 to +566
# Default JSONRPC socket path (adjust for your installation)
JSONRPC_SOCKET_PATH = "/opt/edge/trafficserver/10.0/var/trafficserver/jsonrpc20.sock"
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded socket path should be configurable via command-line argument or environment variable to support different TrafficServer installations.

Suggested change
# Default JSONRPC socket path (adjust for your installation)
JSONRPC_SOCKET_PATH = "/opt/edge/trafficserver/10.0/var/trafficserver/jsonrpc20.sock"
# Default JSONRPC socket path (can be overridden via environment variable)
JSONRPC_SOCKET_PATH = os.environ.get(
"TRAFFICSERVER_JSONRPC_SOCKET",
"/opt/edge/trafficserver/10.0/var/trafficserver/jsonrpc20.sock",
)

Copilot uses AI. Check for mistakes.
# Build SSH command - hostname is passed directly, we add "ssh" prefix
# Encode script as base64 to avoid quoting issues
script_b64 = base64.b64encode(script.encode()).decode()
cmd = f"ssh {self.hostname} \"echo '{script_b64}' | base64 -d | python3\""
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Command injection vulnerability. The hostname is passed directly into a shell command without validation or escaping. Validate or sanitize hostname before use in shell commands.

Copilot uses AI. Check for mistakes.
Comment on lines +595 to +601
# Build SSH command - hostname is passed directly, we add "ssh" prefix
# Encode script as base64 to avoid quoting issues
script_b64 = base64.b64encode(script.encode()).decode()
cmd = f"ssh {self.hostname} \"echo '{script_b64}' | base64 -d | python3\""

try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=10)
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using shell=True with user-controlled input (hostname) creates a security risk. Consider using subprocess.run with a list of arguments instead of a shell string.

Suggested change
# Build SSH command - hostname is passed directly, we add "ssh" prefix
# Encode script as base64 to avoid quoting issues
script_b64 = base64.b64encode(script.encode()).decode()
cmd = f"ssh {self.hostname} \"echo '{script_b64}' | base64 -d | python3\""
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=10)
# Run the JSONRPC collection script on the remote host via SSH.
# Pass the script via stdin to avoid shell invocation and quoting issues.
cmd = ["ssh", self.hostname, "python3"]
try:
result = subprocess.run(cmd, input=script, capture_output=True, text=True, timeout=10)

Copilot uses AI. Check for mistakes.

# Estimate from rows/cols (typical cell: 9x18 pixels)
return (cols * 9, rows * 18)
except:
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bare except clause catches all exceptions including SystemExit and KeyboardInterrupt. Specify explicit exception types like 'except (OSError, IOError):' instead.

Suggested change
except:
except (OSError, io.UnsupportedOperation, struct.error, ValueError):

Copilot uses AI. Check for mistakes.
return 'up'
elif ch3 == b'B':
return 'down'
except:
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bare except clause catches all exceptions including SystemExit and KeyboardInterrupt. Specify explicit exception types like 'except OSError:' instead.

Suggested change
except:
except (OSError, IOError):

Copilot uses AI. Check for mistakes.
key = parts[0]
try:
value = float(parts[1])
except:
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bare except clause catches all exceptions including SystemExit and KeyboardInterrupt. Specify explicit exception types like 'except (ValueError, TypeError):' instead.

Suggested change
except:
except (ValueError, TypeError):

Copilot uses AI. Check for mistakes.
if ZoneInfo and tz_name != "UTC":
try:
self.tz = ZoneInfo(tz_name)
except:
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bare except clause catches all exceptions including SystemExit and KeyboardInterrupt. Specify explicit exception types like 'except Exception:' instead.

Suggested change
except:
except Exception:

Copilot uses AI. Check for mistakes.
def _get_raw_value(self) -> Optional[float]:
"""Run the command and return the raw numeric value."""
try:
result = subprocess.run(self.command, shell=True, capture_output=True, text=True, timeout=5)
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using shell=True with commands that include remote host prefixes could be vulnerable to command injection. Consider validating the command or using shell=False with proper argument parsing.

Copilot uses AI. Check for mistakes.
@bryancall bryancall requested a review from cmcfarlen February 2, 2026 22:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant