""" WebSocket Debug Tap Monitors all WebSocket emissions at the Flask-SocketIO level to confirm events are being sent. This helps distinguish between backend emission issues vs proxy/transport issues. """ import time from typing import Dict, Any from flask_socketio import SocketIO class WebSocketDebugTap: """Debug tap that monitors all WebSocket emissions.""" def __init__(self): self.emission_log = [] self.original_emit = None def install_tap(self, socketio: SocketIO): """Install the debug tap on a SocketIO instance.""" self.original_emit = socketio.emit def debug_emit(*args, **kwargs): # Log the emission attempt emission_data = { 'timestamp': time.time(), 'args': args, 'kwargs': kwargs, 'event': args[0] if args else 'unknown', 'room': kwargs.get('room', 'broadcast') } self.emission_log.append(emission_data) # Print debug info event_name = args[0] if args else 'unknown' room = kwargs.get('room', 'broadcast') print(f"🔍 WEBSOCKET TAP: Emitting '{event_name}' to room '{room}' at {time.time()}") # Call the original emit result = self.original_emit(*args, **kwargs) print(f"🔍 WEBSOCKET TAP: Emission '{event_name}' completed, result: {result}") return result # Replace the emit method socketio.emit = debug_emit print(f"✅ WebSocket debug tap installed on SocketIO instance") def get_recent_emissions(self, limit: int = 10) -> list: """Get recent WebSocket emissions.""" return self.emission_log[-limit:] def clear_log(self): """Clear the emission log.""" self.emission_log.clear() # Global debug tap instance _debug_tap = WebSocketDebugTap() def get_websocket_debug_tap() -> WebSocketDebugTap: """Get the global WebSocket debug tap.""" return _debug_tap