""" Statistics and Monitoring Display Module This module provides a visual dashboard for viewing application statistics, performance metrics, and system information. """ import panel as pn import param from utils.app_context import AppContext from utils.performance_monitor import performance_monitor class StatsDisplay(param.Parameterized): """ Reactive statistics dashboard that displays real-time application metrics. Uses Panel's param.depends to automatically update when state changes. """ # Refresh trigger refresh_trigger = param.Integer(default=0) def __init__(self, context: AppContext, **params): super().__init__(**params) self.context = context @param.depends('refresh_trigger') def _state_stats_panel(self): """Display state statistics (reactive to refresh trigger).""" stats = self.context.state.get_stats() html_content = f"""

State Statistics

Event Lists: {self.context.state.event_data_count}
Light Curves: {self.context.state.light_curve_count}
Timeseries: {self.context.state.timeseries_count}
Total Additions: {stats.get('total_additions', 0)}
Total Removals: {stats.get('total_removals', 0)}
Evictions (LRU): {stats.get('total_evictions', 0)}
Last Operation: {self.context.state.last_operation or 'None'}
""" return pn.pane.HTML(html_content, sizing_mode='stretch_width') @param.depends('refresh_trigger') def _memory_stats_panel(self): """Display memory statistics (reactive to refresh trigger).""" mem_info = self.context.state.get_system_memory_info() if not mem_info: return pn.pane.Markdown("*Memory information unavailable*") # Convert MB to GB total_gb = mem_info.get('total_mb', 0) / 1024 available_gb = mem_info.get('available_mb', 0) / 1024 limit_gb = mem_info.get('allocated_limit_mb', 0) / 1024 app_usage_gb = self.context.state.memory_usage_mb / 1024 html_content = f"""

Memory Usage

Total System RAM: {total_gb:.2f} GB
Available: {available_gb:.2f} GB
App Limit (80%): {limit_gb:.2f} GB
Current App Usage: {app_usage_gb:.3f} GB
""" return pn.pane.HTML(html_content, sizing_mode='stretch_width') @param.depends('refresh_trigger') def _performance_stats_panel(self): """Display performance statistics (reactive to refresh trigger).""" summary = performance_monitor.get_summary() html_content = f"""

Performance Metrics

Total Operations: {summary.get('total_operations', 0)}
Unique Operations: {summary.get('unique_operations', 0)}
Avg Duration: {summary.get('avg_duration_ms', 0):.2f} ms
Success Rate: {summary.get('success_rate', 0):.1f}%
Most Frequent: {summary.get('most_frequent') or 'N/A'}
Slowest Operation: {summary.get('slowest') or 'N/A'}
""" return pn.pane.HTML(html_content, sizing_mode='stretch_width') @param.depends('refresh_trigger') def _recent_operations_panel(self): """Display recent operations list (reactive to refresh trigger).""" recent = performance_monitor.get_recent_operations(limit=10) if not recent: return pn.pane.Markdown("*No recent operations*") rows = "" for op in reversed(recent): # Most recent first status_icon = "[OK]" if op.success else "[X]" status_color = "#28a745" if op.success else "#dc3545" time_str = op.start_time.strftime("%H:%M:%S") rows += f""" {status_icon} {time_str} {op.operation_name} {op.duration_ms:.2f} ms """ html_content = f"""

Recent Operations

{rows}
Status Time Operation Duration
""" return pn.pane.HTML(html_content, sizing_mode='stretch_width') def view(self): """Create the complete stats dashboard view.""" # Refresh button refresh_button = pn.widgets.Button( name="Refresh Stats", button_type="primary", width=200 ) def on_refresh(event): self.refresh_trigger += 1 refresh_button.on_click(on_refresh) # Create layout (no duplicate header - header is set in sidebar.py) dashboard = pn.Column( pn.Row(refresh_button, align='center'), pn.layout.Divider(), self._state_stats_panel, self._memory_stats_panel, self._performance_stats_panel, self._recent_operations_panel, sizing_mode='stretch_width' ) return dashboard def create_stats_dashboard(context: AppContext): """ Factory function to create the stats dashboard. Args: context: Application context Returns: Panel dashboard component """ stats_display = StatsDisplay(context) return stats_display.view()