191 lines
8.9 KiB
Python
191 lines
8.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Add detailed logging to filtered_flow_view.py to trace button lifecycle
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
def add_debug_prints_to_filtered_flow_view():
|
|
"""Add comprehensive logging to track button issues"""
|
|
|
|
view_path = Path("analyzer/tui/textual/widgets/filtered_flow_view.py")
|
|
|
|
if not view_path.exists():
|
|
print("❌ filtered_flow_view.py not found")
|
|
return False
|
|
|
|
# Read current content
|
|
with open(view_path, 'r') as f:
|
|
content = f.read()
|
|
|
|
# Check if debug prints already added
|
|
if "🔍 DEBUG:" in content:
|
|
print("⚠️ Debug prints already added")
|
|
return True
|
|
|
|
# Create backup
|
|
backup_path = view_path.with_suffix('.py.debug_backup')
|
|
with open(backup_path, 'w') as f:
|
|
f.write(content)
|
|
print(f"📁 Backup created: {backup_path}")
|
|
|
|
# Add debug imports at the top
|
|
debug_imports = '''
|
|
import time
|
|
import traceback
|
|
|
|
def debug_log(message):
|
|
"""Debug logging with timestamp"""
|
|
timestamp = time.strftime("%H:%M:%S.%f")[:-3]
|
|
print(f"[{timestamp}] 🔍 DEBUG: {message}")
|
|
|
|
def debug_button_state(frame_type_buttons, phase):
|
|
"""Log current button state"""
|
|
debug_log(f"=== BUTTON STATE - {phase} ===")
|
|
debug_log(f"Total buttons in dict: {len(frame_type_buttons)}")
|
|
for name, btn in frame_type_buttons.items():
|
|
if hasattr(btn, 'parent') and btn.parent:
|
|
parent_info = f"parent: {btn.parent.__class__.__name__}"
|
|
else:
|
|
parent_info = "NO PARENT"
|
|
debug_log(f" {name}: {btn.__class__.__name__} ({parent_info})")
|
|
debug_log("=" * 40)
|
|
'''
|
|
|
|
# Insert debug imports after the existing imports
|
|
lines = content.split('\n')
|
|
insert_index = 0
|
|
|
|
# Find where to insert (after imports but before class definition)
|
|
for i, line in enumerate(lines):
|
|
if line.startswith('class FilteredFlowView'):
|
|
insert_index = i
|
|
break
|
|
|
|
# Insert debug functions
|
|
debug_lines = debug_imports.strip().split('\n')
|
|
for j, debug_line in enumerate(debug_lines):
|
|
lines.insert(insert_index + j, debug_line)
|
|
|
|
# Now add debug prints to key methods
|
|
|
|
# 1. Add to __init__
|
|
init_debug = ''' debug_log("FilteredFlowView.__init__ called")'''
|
|
|
|
# 2. Add to compose method
|
|
compose_debug = ''' debug_log("compose() - Creating filter bar and buttons")
|
|
debug_button_state(self.frame_type_buttons, "BEFORE_COMPOSE")'''
|
|
|
|
compose_end_debug = ''' debug_log("compose() - All widgets created")
|
|
debug_button_state(self.frame_type_buttons, "AFTER_COMPOSE")'''
|
|
|
|
# 3. Add to on_mount method
|
|
mount_debug = ''' debug_log("on_mount() - Initializing view")
|
|
debug_button_state(self.frame_type_buttons, "BEFORE_MOUNT_SETUP")'''
|
|
|
|
mount_end_debug = ''' debug_log("on_mount() - Initialization complete")
|
|
debug_button_state(self.frame_type_buttons, "AFTER_MOUNT_COMPLETE")'''
|
|
|
|
# 4. Add to refresh_frame_types method
|
|
refresh_start_debug = ''' debug_log("refresh_frame_types() - Starting refresh")
|
|
debug_button_state(self.frame_type_buttons, "BEFORE_REFRESH")
|
|
|
|
# Log throttling decision
|
|
import time
|
|
current_time = time.time()
|
|
debug_log(f"Refresh timing - current: {current_time}, last: {self._last_refresh_time}, throttle: {self._refresh_throttle_seconds}")'''
|
|
|
|
refresh_throttle_debug = ''' debug_log("refresh_frame_types() - THROTTLED, skipping refresh")
|
|
return # Skip refresh if called too recently'''
|
|
|
|
refresh_frame_types_debug = ''' debug_log(f"Frame types detected: {frame_types}")
|
|
|
|
# If no frame types yet, skip button update
|
|
if not frame_types:
|
|
debug_log("refresh_frame_types() - No frame types, skipping")
|
|
return'''
|
|
|
|
refresh_before_remove_debug = ''' debug_log("refresh_frame_types() - About to remove/recreate buttons")
|
|
debug_button_state(self.frame_type_buttons, "BEFORE_BUTTON_REMOVAL")'''
|
|
|
|
refresh_after_create_debug = ''' debug_log("refresh_frame_types() - Buttons recreated")
|
|
debug_button_state(self.frame_type_buttons, "AFTER_BUTTON_CREATION")'''
|
|
|
|
# Apply the debug additions
|
|
modified_content = '\n'.join(lines)
|
|
|
|
# Insert debug prints using string replacement
|
|
replacements = [
|
|
('def __init__(self, analyzer: \'EthernetAnalyzer\', **kwargs):\n super().__init__(**kwargs)',
|
|
'def __init__(self, analyzer: \'EthernetAnalyzer\', **kwargs):\n debug_log("FilteredFlowView.__init__ called")\n super().__init__(**kwargs)'),
|
|
|
|
('def compose(self):\n """Create the filter bar and flow grid"""',
|
|
'def compose(self):\n """Create the filter bar and flow grid"""\n debug_log("compose() - Creating filter bar and buttons")\n debug_button_state(self.frame_type_buttons, "BEFORE_COMPOSE")'),
|
|
|
|
('yield self.flow_table',
|
|
'yield self.flow_table\n debug_log("compose() - All widgets created")\n debug_button_state(self.frame_type_buttons, "AFTER_COMPOSE")'),
|
|
|
|
('def on_mount(self):\n """Initialize the view"""',
|
|
'def on_mount(self):\n """Initialize the view"""\n debug_log("on_mount() - Initializing view")\n debug_button_state(self.frame_type_buttons, "BEFORE_MOUNT_SETUP")'),
|
|
|
|
('self._update_button_highlighting()',
|
|
'self._update_button_highlighting()\n debug_log("on_mount() - Initialization complete")\n debug_button_state(self.frame_type_buttons, "AFTER_MOUNT_COMPLETE")'),
|
|
|
|
('def refresh_frame_types(self):\n """Update frame type button counts and reorder by count (highest to left)"""',
|
|
'def refresh_frame_types(self):\n """Update frame type button counts and reorder by count (highest to left)"""\n debug_log("refresh_frame_types() - Starting refresh")\n debug_button_state(self.frame_type_buttons, "BEFORE_REFRESH")'),
|
|
|
|
('if current_time - self._last_refresh_time < self._refresh_throttle_seconds:\n return # Skip refresh if called too recently',
|
|
'if current_time - self._last_refresh_time < self._refresh_throttle_seconds:\n debug_log("refresh_frame_types() - THROTTLED, skipping refresh")\n return # Skip refresh if called too recently'),
|
|
|
|
('# If no frame types yet, skip button update\n if not frame_types:\n return',
|
|
'# If no frame types yet, skip button update\n if not frame_types:\n debug_log("refresh_frame_types() - No frame types, skipping")\n return'),
|
|
|
|
('# Order changed, need to recreate buttons\n try:',
|
|
'# Order changed, need to recreate buttons\n debug_log("refresh_frame_types() - About to remove/recreate buttons")\n debug_button_state(self.frame_type_buttons, "BEFORE_BUTTON_REMOVAL")\n try:'),
|
|
|
|
('# Update button highlighting\n self._update_button_highlighting()',
|
|
'# Update button highlighting\n self._update_button_highlighting()\n debug_log("refresh_frame_types() - Buttons recreated")\n debug_button_state(self.frame_type_buttons, "AFTER_BUTTON_CREATION")')
|
|
]
|
|
|
|
for old, new in replacements:
|
|
if old in modified_content:
|
|
modified_content = modified_content.replace(old, new)
|
|
print(f"✅ Added debug to: {old.split('\\n')[0][:50]}...")
|
|
else:
|
|
print(f"⚠️ Could not find: {old.split('\\n')[0][:50]}...")
|
|
|
|
# Write the modified content
|
|
with open(view_path, 'w') as f:
|
|
f.write(modified_content)
|
|
|
|
print(f"✅ Debug prints added to {view_path}")
|
|
return True
|
|
|
|
def main():
|
|
print("🔧 Adding Debug Prints to Track Button Lifecycle")
|
|
print("=" * 60)
|
|
|
|
success = add_debug_prints_to_filtered_flow_view()
|
|
|
|
if success:
|
|
print("\n✅ Debug prints added successfully!")
|
|
print("\n🚀 Now run the app and watch the console output:")
|
|
print(" python debug_streamlens.py")
|
|
print("\n📊 You'll see detailed logs showing:")
|
|
print(" • When buttons are created")
|
|
print(" • When refresh_frame_types() is called")
|
|
print(" • Button parent relationships")
|
|
print(" • Throttling decisions")
|
|
print(" • Button removal/recreation")
|
|
print("\n🔍 Look for patterns like:")
|
|
print(" • Buttons created but losing parents")
|
|
print(" • Refresh called too frequently")
|
|
print(" • Button removal without recreation")
|
|
print("\n💡 To remove debug prints later:")
|
|
print(" • Restore from .debug_backup file")
|
|
else:
|
|
print("\n❌ Failed to add debug prints")
|
|
|
|
if __name__ == "__main__":
|
|
main() |