|
1 | 1 | from synapse.client.taps import Tap |
2 | 2 |
|
3 | 3 | from rich.console import Console |
4 | | -from rich.pretty import pprint |
5 | 4 | from rich.table import Table |
| 5 | +from rich.live import Live |
| 6 | +from rich.text import Text |
| 7 | + |
| 8 | +import time |
| 9 | + |
| 10 | + |
| 11 | +class TapHealthMonitor: |
| 12 | + """Health monitor for streaming tap data with real-time statistics display.""" |
| 13 | + |
| 14 | + def __init__(self, console: Console): |
| 15 | + self.console = console |
| 16 | + self.message_count = 0 |
| 17 | + self.total_bytes = 0 |
| 18 | + self.start_time = None |
| 19 | + |
| 20 | + def start(self): |
| 21 | + """Start the monitoring session.""" |
| 22 | + self.start_time = time.time() |
| 23 | + self.message_count = 0 |
| 24 | + self.total_bytes = 0 |
| 25 | + |
| 26 | + def update(self, message_size: int) -> Text: |
| 27 | + """Update statistics with a new message and return formatted display text.""" |
| 28 | + current_time = time.time() |
| 29 | + self.message_count += 1 |
| 30 | + self.total_bytes += message_size |
| 31 | + |
| 32 | + # Calculate stats |
| 33 | + elapsed_time = current_time - self.start_time |
| 34 | + msgs_per_sec = self.message_count / elapsed_time if elapsed_time > 0 else 0 |
| 35 | + bandwidth_bps = self.total_bytes / elapsed_time if elapsed_time > 0 else 0 |
| 36 | + |
| 37 | + # Format bandwidth |
| 38 | + bandwidth_str = self._format_bandwidth(bandwidth_bps) |
| 39 | + |
| 40 | + # Create formatted display text |
| 41 | + return self._create_display_text( |
| 42 | + self.message_count, msgs_per_sec, bandwidth_str, message_size |
| 43 | + ) |
| 44 | + |
| 45 | + def _format_bandwidth(self, bandwidth_bps: float) -> str: |
| 46 | + """Format bandwidth with appropriate units.""" |
| 47 | + if bandwidth_bps >= 1024 * 1024: |
| 48 | + return f"{bandwidth_bps / (1024 * 1024):.2f} MB/s" |
| 49 | + elif bandwidth_bps >= 1024: |
| 50 | + return f"{bandwidth_bps / 1024:.2f} KB/s" |
| 51 | + else: |
| 52 | + return f"{bandwidth_bps:.1f} B/s" |
| 53 | + |
| 54 | + def _create_display_text( |
| 55 | + self, msg_count: int, rate: float, bandwidth: str, latest_size: int |
| 56 | + ) -> Text: |
| 57 | + """Create styled text for the live display.""" |
| 58 | + stats_text = Text() |
| 59 | + stats_text.append("Messages: ", style="bold") |
| 60 | + stats_text.append(f"{msg_count:,}", style="cyan") |
| 61 | + stats_text.append(" | msgs/sec: ", style="bold") |
| 62 | + stats_text.append(f"{rate:.1f}/s", style="green") |
| 63 | + stats_text.append(" | Bandwidth: ", style="bold") |
| 64 | + stats_text.append(bandwidth, style="yellow") |
| 65 | + stats_text.append(" | Latest: ", style="bold") |
| 66 | + stats_text.append(f"{latest_size:,} bytes", style="magenta") |
| 67 | + stats_text.append(" | Runtime: ", style="bold") |
| 68 | + stats_text.append(f"{time.time() - self.start_time:.1f}s", style="blue") |
| 69 | + return stats_text |
6 | 70 |
|
7 | 71 |
|
8 | 72 | def add_commands(subparsers): |
@@ -48,9 +112,26 @@ def stream_taps(args): |
48 | 112 |
|
49 | 113 | console = Console() |
50 | 114 | console.print(f"[bold cyan]Streaming tap:[/] [green]{args.tap_name}[/]") |
| 115 | + console.print("[dim]Press Ctrl+C to stop[/]\n") |
51 | 116 |
|
52 | | - for message in tap.stream(): |
53 | | - message_size = len(str(message)) |
54 | | - console.print(f"[bold]Message Size:[/] [cyan]{message_size} bytes[/]") |
55 | | - pprint(message, expand_all=False) |
56 | | - console.print("---") |
| 117 | + # Initialize health monitor |
| 118 | + monitor = TapHealthMonitor(console) |
| 119 | + monitor.start() |
| 120 | + |
| 121 | + # Create initial display |
| 122 | + initial_text = Text("Waiting for messages...", style="dim") |
| 123 | + |
| 124 | + try: |
| 125 | + with Live(initial_text, console=console, refresh_per_second=10) as live: |
| 126 | + for message in tap.stream(): |
| 127 | + message_size = len(message) |
| 128 | + |
| 129 | + # Update statistics and get formatted display |
| 130 | + stats_text = monitor.update(message_size) |
| 131 | + |
| 132 | + # Update the live display |
| 133 | + live.update(stats_text) |
| 134 | + except KeyboardInterrupt: |
| 135 | + pass |
| 136 | + finally: |
| 137 | + tap.disconnect() |
0 commit comments