Spaces:
Runtime error
Runtime error
| """ | |
| Enhanced visualization engine for ARF Demo | |
| """ | |
| import plotly.graph_objects as go | |
| import plotly.express as px | |
| import numpy as np | |
| import pandas as pd | |
| from typing import Dict, List, Any, Optional | |
| import logging | |
| logger = logging.getLogger(__name__) | |
| class EnhancedVisualizationEngine: | |
| """Enhanced visualization engine with multiple chart types""" | |
| def __init__(self): | |
| self.color_palette = { | |
| "primary": "#3b82f6", | |
| "success": "#10b981", | |
| "warning": "#f59e0b", | |
| "danger": "#ef4444", | |
| "info": "#8b5cf6", | |
| "dark": "#1e293b", | |
| "light": "#f8fafc" | |
| } | |
| def create_executive_dashboard(self, data: Optional[Dict] = None) -> go.Figure: | |
| """Create executive dashboard with ROI visualization""" | |
| if data is None: | |
| data = {"roi_multiplier": 5.2} | |
| roi_multiplier = data.get("roi_multiplier", 5.2) | |
| # Create a multi-panel executive dashboard | |
| fig = go.Figure() | |
| # Main ROI gauge | |
| fig.add_trace(go.Indicator( | |
| mode="number+gauge", | |
| value=roi_multiplier, | |
| title={"text": "<b>ROI Multiplier</b><br>Investment Return"}, | |
| domain={'x': [0.25, 0.75], 'y': [0.6, 1]}, | |
| gauge={ | |
| 'axis': {'range': [0, 10], 'tickwidth': 1}, | |
| 'bar': {'color': self.color_palette["success"]}, | |
| 'steps': [ | |
| {'range': [0, 2], 'color': '#e5e7eb'}, | |
| {'range': [2, 4], 'color': '#d1d5db'}, | |
| {'range': [4, 6], 'color': '#10b981'}, | |
| {'range': [6, 10], 'color': '#059669'} | |
| ], | |
| 'threshold': { | |
| 'line': {'color': "black", 'width': 4}, | |
| 'thickness': 0.75, | |
| 'value': roi_multiplier | |
| } | |
| } | |
| )) | |
| # Add secondary metrics as subplots | |
| fig.add_trace(go.Indicator( | |
| mode="number", | |
| value=85, | |
| title={"text": "MTTR Reduction"}, | |
| number={'suffix': "%", 'font': {'size': 24}}, | |
| domain={'x': [0.1, 0.4], 'y': [0.2, 0.5]} | |
| )) | |
| fig.add_trace(go.Indicator( | |
| mode="number", | |
| value=94, | |
| title={"text": "Detection Accuracy"}, | |
| number={'suffix': "%", 'font': {'size': 24}}, | |
| domain={'x': [0.6, 0.9], 'y': [0.2, 0.5]} | |
| )) | |
| fig.update_layout( | |
| height=700, | |
| paper_bgcolor="rgba(0,0,0,0)", | |
| plot_bgcolor="rgba(0,0,0,0)", | |
| font={'family': "Arial, sans-serif"}, | |
| margin=dict(t=50, b=50, l=50, r=50) | |
| ) | |
| return fig | |
| def create_telemetry_plot(self, scenario_name: str, anomaly_detected: bool = True) -> go.Figure: | |
| """Create telemetry plot for a scenario""" | |
| # Generate realistic telemetry data | |
| time_points = np.arange(0, 100, 1) | |
| # Different patterns for different scenarios | |
| if "Cache" in scenario_name: | |
| base_data = 100 + 50 * np.sin(time_points * 0.2) | |
| noise = np.random.normal(0, 8, 100) | |
| metric_name = "Cache Hit Rate (%)" | |
| normal_range = (70, 95) | |
| elif "Database" in scenario_name: | |
| base_data = 70 + 30 * np.sin(time_points * 0.15) | |
| noise = np.random.normal(0, 6, 100) | |
| metric_name = "Connection Pool Usage" | |
| normal_range = (20, 60) | |
| elif "Memory" in scenario_name: | |
| base_data = 50 + 40 * np.sin(time_points * 0.1) | |
| noise = np.random.normal(0, 10, 100) | |
| metric_name = "Memory Usage (%)" | |
| normal_range = (40, 80) | |
| else: | |
| base_data = 80 + 20 * np.sin(time_points * 0.25) | |
| noise = np.random.normal(0, 5, 100) | |
| metric_name = "System Load" | |
| normal_range = (50, 90) | |
| data = base_data + noise | |
| fig = go.Figure() | |
| if anomaly_detected: | |
| # Normal operation | |
| fig.add_trace(go.Scatter( | |
| x=time_points[:70], | |
| y=data[:70], | |
| mode='lines', | |
| name='Normal Operation', | |
| line=dict(color=self.color_palette["primary"], width=3), | |
| fill='tozeroy', | |
| fillcolor='rgba(59, 130, 246, 0.1)' | |
| )) | |
| # Anomaly period | |
| fig.add_trace(go.Scatter( | |
| x=time_points[70:], | |
| y=data[70:], | |
| mode='lines', | |
| name='Anomaly Detected', | |
| line=dict(color=self.color_palette["danger"], width=3, dash='dash'), | |
| fill='tozeroy', | |
| fillcolor='rgba(239, 68, 68, 0.1)' | |
| )) | |
| # Add detection point | |
| fig.add_vline( | |
| x=70, | |
| line_dash="dash", | |
| line_color=self.color_palette["success"], | |
| annotation_text="ARF Detection", | |
| annotation_position="top" | |
| ) | |
| else: | |
| # All normal | |
| fig.add_trace(go.Scatter( | |
| x=time_points, | |
| y=data, | |
| mode='lines', | |
| name=metric_name, | |
| line=dict(color=self.color_palette["primary"], width=3), | |
| fill='tozeroy', | |
| fillcolor='rgba(59, 130, 246, 0.1)' | |
| )) | |
| # Add normal range | |
| fig.add_hrect( | |
| y0=normal_range[0], | |
| y1=normal_range[1], | |
| fillcolor="rgba(16, 185, 129, 0.1)", | |
| opacity=0.2, | |
| line_width=0, | |
| annotation_text="Normal Range", | |
| annotation_position="top left" | |
| ) | |
| fig.update_layout( | |
| title=f"📈 {metric_name} - Live Telemetry", | |
| xaxis_title="Time (minutes)", | |
| yaxis_title=metric_name, | |
| height=300, | |
| margin=dict(l=20, r=20, t=50, b=20), | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| legend=dict( | |
| orientation="h", | |
| yanchor="bottom", | |
| y=1.02, | |
| xanchor="right", | |
| x=1 | |
| ) | |
| ) | |
| return fig | |
| def create_impact_gauge(self, scenario_name: str) -> go.Figure: | |
| """Create business impact gauge""" | |
| impact_map = { | |
| "Cache Miss Storm": {"revenue": 8500, "severity": "critical"}, | |
| "Database Connection Pool Exhaustion": {"revenue": 4200, "severity": "high"}, | |
| "Kubernetes Memory Leak": {"revenue": 5500, "severity": "high"}, | |
| "API Rate Limit Storm": {"revenue": 3800, "severity": "medium"}, | |
| "Network Partition": {"revenue": 12000, "severity": "critical"}, | |
| "Storage I/O Saturation": {"revenue": 6800, "severity": "high"} | |
| } | |
| impact = impact_map.get(scenario_name, {"revenue": 5000, "severity": "medium"}) | |
| fig = go.Figure(go.Indicator( | |
| mode="gauge+number", | |
| value=impact["revenue"], | |
| title={'text': "💰 Hourly Revenue Risk", 'font': {'size': 16}}, | |
| number={'prefix': "$", 'font': {'size': 28}}, | |
| gauge={ | |
| 'axis': {'range': [0, 15000], 'tickwidth': 1}, | |
| 'bar': {'color': self._get_severity_color(impact["severity"])}, | |
| 'steps': [ | |
| {'range': [0, 3000], 'color': '#10b981'}, | |
| {'range': [3000, 7000], 'color': '#f59e0b'}, | |
| {'range': [7000, 15000], 'color': '#ef4444'} | |
| ], | |
| 'threshold': { | |
| 'line': {'color': "black", 'width': 4}, | |
| 'thickness': 0.75, | |
| 'value': impact["revenue"] | |
| } | |
| } | |
| )) | |
| fig.update_layout( | |
| height=300, | |
| margin=dict(l=20, r=20, t=50, b=20), | |
| paper_bgcolor='rgba(0,0,0,0)' | |
| ) | |
| return fig | |
| def create_agent_performance_chart(self) -> go.Figure: | |
| """Create agent performance comparison chart""" | |
| agents = ["Detection", "Recall", "Decision"] | |
| accuracy = [98.7, 92.0, 94.0] | |
| speed = [45, 30, 60] # seconds | |
| confidence = [99.8, 92.0, 94.0] | |
| fig = go.Figure(data=[ | |
| go.Bar(name='Accuracy (%)', x=agents, y=accuracy, | |
| marker_color=self.color_palette["primary"]), | |
| go.Bar(name='Speed (seconds)', x=agents, y=speed, | |
| marker_color=self.color_palette["success"]), | |
| go.Bar(name='Confidence (%)', x=agents, y=confidence, | |
| marker_color=self.color_palette["info"]) | |
| ]) | |
| fig.update_layout( | |
| title="🤖 Agent Performance Metrics", | |
| barmode='group', | |
| height=400, | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| legend=dict( | |
| orientation="h", | |
| yanchor="bottom", | |
| y=1.02, | |
| xanchor="right", | |
| x=1 | |
| ) | |
| ) | |
| return fig | |
| def create_timeline_comparison(self) -> go.Figure: | |
| """Create timeline comparison chart""" | |
| phases = ["Detection", "Analysis", "Decision", "Execution", "Recovery"] | |
| manual_times = [300, 1800, 1200, 1800, 3600] # seconds | |
| arf_times = [45, 30, 60, 720, 0] | |
| # Convert to minutes for readability | |
| manual_times_min = [t/60 for t in manual_times] | |
| arf_times_min = [t/60 for t in arf_times] | |
| fig = go.Figure() | |
| fig.add_trace(go.Bar( | |
| name='Manual Process', | |
| x=phases, | |
| y=manual_times_min, | |
| marker_color=self.color_palette["danger"], | |
| text=[f"{t:.0f}m" for t in manual_times_min], | |
| textposition='auto' | |
| )) | |
| fig.add_trace(go.Bar( | |
| name='ARF Autonomous', | |
| x=phases, | |
| y=arf_times_min, | |
| marker_color=self.color_palette["success"], | |
| text=[f"{t:.0f}m" for t in arf_times_min], | |
| textposition='auto' | |
| )) | |
| total_manual = sum(manual_times_min) | |
| total_arf = sum(arf_times_min) | |
| fig.update_layout( | |
| title=f"⏰ Incident Timeline Comparison<br>" | |
| f"<span style='font-size: 14px; color: #6b7280'>" | |
| f"Total: {total_manual:.0f}m manual vs {total_arf:.0f}m ARF " | |
| f"({((total_manual - total_arf) / total_manual * 100):.0f}% faster)</span>", | |
| barmode='group', | |
| height=400, | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| legend=dict( | |
| orientation="h", | |
| yanchor="bottom", | |
| y=1.02, | |
| xanchor="right", | |
| x=1 | |
| ), | |
| yaxis_title="Time (minutes)" | |
| ) | |
| return fig | |
| def create_roi_simulation_chart(self, roi_data: Dict) -> go.Figure: | |
| """Create ROI simulation chart""" | |
| scenarios = ["Worst Case", "Base Case", "Best Case"] | |
| roi_values = [ | |
| roi_data.get("worst_case", 4.0), | |
| roi_data.get("base_case", 5.2), | |
| roi_data.get("best_case", 6.5) | |
| ] | |
| fig = go.Figure(go.Bar( | |
| x=scenarios, | |
| y=roi_values, | |
| marker_color=[ | |
| self.color_palette["warning"], | |
| self.color_palette["success"], | |
| self.color_palette["primary"] | |
| ], | |
| text=[f"{v:.1f}×" for v in roi_values], | |
| textposition='auto' | |
| )) | |
| fig.update_layout( | |
| title="📊 ROI Simulation Scenarios", | |
| yaxis_title="ROI Multiplier", | |
| height=400, | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| yaxis=dict(range=[0, max(roi_values) * 1.2]) | |
| ) | |
| # Add industry average line | |
| fig.add_hline( | |
| y=5.2, | |
| line_dash="dash", | |
| line_color="gray", | |
| annotation_text="Industry Average", | |
| annotation_position="top right" | |
| ) | |
| return fig | |
| def create_learning_graph(self, graph_type: str = "patterns") -> go.Figure: | |
| """Create learning engine visualization""" | |
| if graph_type == "patterns": | |
| return self._create_pattern_graph() | |
| elif graph_type == "dependencies": | |
| return self._create_dependency_graph() | |
| else: | |
| return self._create_action_graph() | |
| def _create_pattern_graph(self) -> go.Figure: | |
| """Create pattern recognition graph""" | |
| nodes = ["Cache Miss", "DB Pool", "Memory Leak", "API Limit", "Network"] | |
| connections = [ | |
| ("Cache Miss", "DB Pool", 0.85), | |
| ("DB Pool", "Memory Leak", 0.72), | |
| ("Memory Leak", "API Limit", 0.65), | |
| ("API Limit", "Network", 0.58), | |
| ("Cache Miss", "Network", 0.45) | |
| ] | |
| fig = go.Figure() | |
| # Add nodes | |
| for node in nodes: | |
| fig.add_trace(go.Scatter( | |
| x=[np.random.random()], | |
| y=[np.random.random()], | |
| mode='markers+text', | |
| name=node, | |
| marker=dict(size=30, color=self.color_palette["primary"]), | |
| text=[node], | |
| textposition="top center" | |
| )) | |
| # Add edges | |
| for src, dst, weight in connections: | |
| fig.add_trace(go.Scatter( | |
| x=[np.random.random(), np.random.random()], | |
| y=[np.random.random(), np.random.random()], | |
| mode='lines', | |
| line=dict(width=weight * 5, color='gray'), | |
| showlegend=False | |
| )) | |
| fig.update_layout( | |
| title="🧠 RAG Memory - Incident Pattern Graph", | |
| height=500, | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| showlegend=False, | |
| xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), | |
| yaxis=dict(showgrid=False, zeroline=False, showticklabels=False) | |
| ) | |
| return fig | |
| def _create_dependency_graph(self) -> go.Figure: | |
| """Create system dependency graph""" | |
| fig = go.Figure(go.Sunburst( | |
| labels=["System", "Cache", "Database", "API", "User Service", "Payment"], | |
| parents=["", "System", "System", "System", "API", "API"], | |
| values=[100, 30, 40, 30, 15, 15], | |
| marker=dict(colors=px.colors.sequential.Blues) | |
| )) | |
| fig.update_layout( | |
| title="🔗 System Dependency Map", | |
| height=500, | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)' | |
| ) | |
| return fig | |
| def _create_action_graph(self) -> go.Figure: | |
| """Create action-outcome graph""" | |
| actions = ["Scale Cache", "Restart DB", "Limit API", "Monitor Memory"] | |
| success_rates = [87, 92, 78, 85] | |
| fig = go.Figure(go.Bar( | |
| x=actions, | |
| y=success_rates, | |
| marker_color=self.color_palette["success"], | |
| text=[f"{rate}%" for rate in success_rates], | |
| textposition='auto' | |
| )) | |
| fig.update_layout( | |
| title="🎯 Action Success Rates", | |
| yaxis_title="Success Rate (%)", | |
| height=400, | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| yaxis=dict(range=[0, 100]) | |
| ) | |
| return fig | |
| def _get_severity_color(self, severity: str) -> str: | |
| """Get color for severity level""" | |
| color_map = { | |
| "critical": self.color_palette["danger"], | |
| "high": self.color_palette["warning"], | |
| "medium": self.color_palette["info"], | |
| "low": self.color_palette["success"] | |
| } | |
| return color_map.get(severity.lower(), self.color_palette["info"]) |