tabbed frametype filtering
This commit is contained in:
277
interactive_debug.py
Normal file
277
interactive_debug.py
Normal file
@@ -0,0 +1,277 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Interactive debugging for StreamLens button issues
|
||||
Run this and interact with the live app while monitoring button states
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
from pathlib import Path
|
||||
|
||||
# Add analyzer to path
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from analyzer.tui.textual.app_v2 import StreamLensAppV2
|
||||
from analyzer.analysis.core import EthernetAnalyzer
|
||||
from textual_state_visualizer import TextualStateMonitor, TextualStateWebServer
|
||||
|
||||
class InteractiveDebugger:
|
||||
"""Interactive debugger that monitors button states in real-time"""
|
||||
|
||||
def __init__(self):
|
||||
self.analyzer = None
|
||||
self.app = None
|
||||
self.monitor = None
|
||||
self.web_server = None
|
||||
self.monitoring = False
|
||||
|
||||
def setup_analyzer_with_data(self):
|
||||
"""Create analyzer with some sample data"""
|
||||
from analyzer.models.flow_stats import FlowStats, FrameTypeStats
|
||||
|
||||
self.analyzer = EthernetAnalyzer()
|
||||
|
||||
# Add sample flows to trigger button updates
|
||||
flow1 = FlowStats(src_ip="192.168.1.1", dst_ip="192.168.1.2")
|
||||
flow1.frame_types["CH10-Data"] = FrameTypeStats("CH10-Data", count=1500)
|
||||
flow1.frame_types["UDP"] = FrameTypeStats("UDP", count=800)
|
||||
self.analyzer.flows["flow1"] = flow1
|
||||
|
||||
flow2 = FlowStats(src_ip="192.168.1.3", dst_ip="192.168.1.4")
|
||||
flow2.frame_types["PTP-Sync"] = FrameTypeStats("PTP-Sync", count=600)
|
||||
flow2.frame_types["PTP-Signaling"] = FrameTypeStats("PTP-Signaling", count=300)
|
||||
self.analyzer.flows["flow2"] = flow2
|
||||
|
||||
print("📊 Sample data added to analyzer:")
|
||||
print(" Flow 1: CH10-Data(1500), UDP(800)")
|
||||
print(" Flow 2: PTP-Sync(600), PTP-Signaling(300)")
|
||||
|
||||
def start_debugging(self):
|
||||
"""Start the app with full debugging enabled"""
|
||||
print("🚀 Starting StreamLens with interactive debugging...")
|
||||
|
||||
# Setup analyzer
|
||||
self.setup_analyzer_with_data()
|
||||
|
||||
# Create app
|
||||
self.app = StreamLensAppV2(analyzer=self.analyzer)
|
||||
|
||||
# Start state monitoring
|
||||
self.monitor = TextualStateMonitor(self.app)
|
||||
self.monitor.start_monitoring(interval=0.5) # Monitor every 500ms
|
||||
|
||||
# Start web interface
|
||||
self.web_server = TextualStateWebServer(self.monitor, port=8080)
|
||||
self.web_server.start()
|
||||
|
||||
print("🌐 Web debugging interface: http://localhost:8080")
|
||||
print("📱 Starting StreamLens app...")
|
||||
print()
|
||||
print("🔧 DEBUGGING COMMANDS (while app is running):")
|
||||
print(" Ctrl+D,T - Print widget tree to console")
|
||||
print(" Ctrl+D,F - Show focused widget")
|
||||
print(" Ctrl+D,W - Start additional web debugger")
|
||||
print()
|
||||
print("🧪 INTERACTIVE TESTING:")
|
||||
print(" 1. Watch the web interface in your browser")
|
||||
print(" 2. Try loading a PCAP file in the app")
|
||||
print(" 3. Watch for button changes in real-time")
|
||||
print(" 4. Use keyboard shortcuts to debug instantly")
|
||||
print()
|
||||
print("📊 The web interface will show:")
|
||||
print(" - Real-time widget tree")
|
||||
print(" - Button count and properties")
|
||||
print(" - State changes as they happen")
|
||||
print(" - Focus tracking")
|
||||
print()
|
||||
|
||||
# Run the app
|
||||
try:
|
||||
self.app.run()
|
||||
except KeyboardInterrupt:
|
||||
print("\n🛑 App stopped by user")
|
||||
finally:
|
||||
self.cleanup()
|
||||
|
||||
def cleanup(self):
|
||||
"""Clean up debugging resources"""
|
||||
print("\n🧹 Cleaning up debugging...")
|
||||
if self.monitor:
|
||||
self.monitor.stop_monitoring()
|
||||
if self.web_server:
|
||||
self.web_server.stop()
|
||||
|
||||
def create_vscode_debug_config():
|
||||
"""Create VS Code debug configuration"""
|
||||
vscode_config = {
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug StreamLens Interactive",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/interactive_debug.py",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": False,
|
||||
"env": {
|
||||
"PYTHONPATH": "${workspaceFolder}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Debug StreamLens Button Issues",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/debug_button_issues.py",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": False,
|
||||
"env": {
|
||||
"PYTHONPATH": "${workspaceFolder}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Create .vscode directory if it doesn't exist
|
||||
vscode_dir = Path(".vscode")
|
||||
vscode_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Write launch.json
|
||||
import json
|
||||
launch_json = vscode_dir / "launch.json"
|
||||
with open(launch_json, 'w') as f:
|
||||
json.dump(vscode_config, f, indent=4)
|
||||
|
||||
print(f"✅ Created VS Code debug configuration: {launch_json}")
|
||||
|
||||
def create_breakpoint_helper():
|
||||
"""Create a helper script with strategic breakpoints"""
|
||||
|
||||
breakpoint_script = '''
|
||||
# Add these breakpoints to key locations for debugging
|
||||
|
||||
# 1. In filtered_flow_view.py - refresh_frame_types method
|
||||
def refresh_frame_types(self):
|
||||
"""Update frame type button counts and reorder by count (highest to left)"""
|
||||
import pdb; pdb.set_trace() # BREAKPOINT: Start of refresh
|
||||
|
||||
# Throttle button refresh to prevent race conditions
|
||||
import time
|
||||
current_time = time.time()
|
||||
if current_time - self._last_refresh_time < self._refresh_throttle_seconds:
|
||||
print(f"🚫 Refresh throttled (last: {self._last_refresh_time}, current: {current_time})")
|
||||
return # Skip refresh if called too recently
|
||||
|
||||
print(f"🔄 Starting refresh_frame_types at {current_time}")
|
||||
self._last_refresh_time = current_time
|
||||
|
||||
# Get all detected frame types with their total packet counts
|
||||
frame_types = self._get_all_frame_types()
|
||||
print(f"📊 Frame types found: {frame_types}")
|
||||
|
||||
# If no frame types yet, skip button update
|
||||
if not frame_types:
|
||||
print("⚠️ No frame types, skipping button update")
|
||||
return
|
||||
|
||||
# BREAKPOINT: Before button removal/creation
|
||||
import pdb; pdb.set_trace()
|
||||
|
||||
# Rest of method...
|
||||
|
||||
# 2. In filtered_flow_view.py - compose method
|
||||
def compose(self):
|
||||
"""Create the filter bar and flow grid"""
|
||||
import pdb; pdb.set_trace() # BREAKPOINT: Widget creation
|
||||
|
||||
# Filter button bar at top
|
||||
with Horizontal(id="filter-bar"):
|
||||
# Overview button (hotkey 1) - compact format
|
||||
overview_btn = Button("1.Overview", id="btn-overview", classes="-active")
|
||||
self.frame_type_buttons["Overview"] = overview_btn
|
||||
print(f"✅ Created overview button: {overview_btn}")
|
||||
yield overview_btn
|
||||
|
||||
# Create predefined frame type buttons at initialization
|
||||
hotkeys = ['2', '3', '4', '5', '6', '7', '8', '9', '0']
|
||||
for i, frame_type in enumerate(self.predefined_frame_types):
|
||||
if i < len(hotkeys):
|
||||
# Start with 0 count - will be updated during data refresh
|
||||
btn = FrameTypeButton(frame_type, hotkeys[i], 0)
|
||||
self.frame_type_buttons[frame_type] = btn
|
||||
print(f"✅ Created predefined button {i+1}: {btn} for {frame_type}")
|
||||
yield btn
|
||||
|
||||
# BREAKPOINT: After all buttons created
|
||||
import pdb; pdb.set_trace()
|
||||
|
||||
# 3. Strategic print statements for tracking
|
||||
def debug_button_lifecycle():
|
||||
"""Add this to track button lifecycle"""
|
||||
|
||||
def log_button_state(self, phase):
|
||||
print(f"\\n🔍 BUTTON STATE - {phase}:")
|
||||
print(f" Buttons dict: {len(self.frame_type_buttons)} entries")
|
||||
for name, btn in self.frame_type_buttons.items():
|
||||
if hasattr(btn, 'parent'):
|
||||
parent_status = "has parent" if btn.parent else "NO PARENT"
|
||||
else:
|
||||
parent_status = "no parent attr"
|
||||
print(f" {name}: {btn} ({parent_status})")
|
||||
'''
|
||||
|
||||
with open("debugging_breakpoints.py", 'w') as f:
|
||||
f.write(breakpoint_script)
|
||||
|
||||
print("✅ Created debugging_breakpoints.py with strategic breakpoint locations")
|
||||
|
||||
def main():
|
||||
print("🔧 StreamLens Interactive Debugging Setup")
|
||||
print("=" * 60)
|
||||
|
||||
# Create VS Code configuration
|
||||
create_vscode_debug_config()
|
||||
|
||||
# Create breakpoint helper
|
||||
create_breakpoint_helper()
|
||||
|
||||
print("\n🎯 RECOMMENDED DEBUGGING APPROACH:")
|
||||
print("\n1. **VS Code Debugging**:")
|
||||
print(" - Open this project in VS Code")
|
||||
print(" - Use F5 to start 'Debug StreamLens Interactive'")
|
||||
print(" - Set breakpoints in filtered_flow_view.py")
|
||||
print(" - Step through button creation/refresh logic")
|
||||
|
||||
print("\n2. **Interactive Monitoring**:")
|
||||
print(" - Run: python interactive_debug.py")
|
||||
print(" - Open http://localhost:8080 in browser")
|
||||
print(" - Load a PCAP file and watch real-time changes")
|
||||
|
||||
print("\n3. **Strategic Breakpoints**:")
|
||||
print(" - Add breakpoints at:")
|
||||
print(" • filtered_flow_view.py:142 (compose method)")
|
||||
print(" • filtered_flow_view.py:219 (refresh_frame_types method)")
|
||||
print(" • filtered_flow_view.py:171 (on_mount method)")
|
||||
|
||||
print("\n4. **Live Console Debugging**:")
|
||||
print(" - While app runs, press Ctrl+D,T for widget tree")
|
||||
print(" - Check button parent relationships")
|
||||
print(" - Monitor refresh timing")
|
||||
|
||||
print("\n🔍 KEY THINGS TO CHECK:")
|
||||
print(" ✓ Are buttons created in compose()?")
|
||||
print(" ✓ Do buttons have parents after creation?")
|
||||
print(" ✓ What triggers refresh_frame_types()?")
|
||||
print(" ✓ Are buttons removed during refresh?")
|
||||
print(" ✓ What's the order of operations?")
|
||||
|
||||
choice = input("\n❓ Start interactive debugging now? (y/N): ").lower().strip()
|
||||
|
||||
if choice in ['y', 'yes']:
|
||||
debugger = InteractiveDebugger()
|
||||
debugger.start_debugging()
|
||||
else:
|
||||
print("\n📝 Setup complete! Use VS Code or run interactive_debug.py when ready.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user