petter2025 commited on
Commit
fe961b9
·
verified ·
1 Parent(s): cd0e1e1

Update core/visualizations.py

Browse files
Files changed (1) hide show
  1. core/visualizations.py +422 -212
core/visualizations.py CHANGED
@@ -1,258 +1,468 @@
1
  """
2
- Enhanced investor-grade visualizations - FIXED VERSION
3
  """
4
-
5
  import plotly.graph_objects as go
6
  import plotly.express as px
7
- import pandas as pd
8
  import numpy as np
9
- from plotly.subplots import make_subplots
10
- from datetime import datetime
11
- from typing import Dict, Optional, List
 
 
12
 
13
- from core.data_models import IncidentScenario
14
 
15
  class EnhancedVisualizationEngine:
16
- """Interactive, investor-grade visualizations"""
17
 
18
  def __init__(self):
19
- self.color_palette = px.colors.qualitative.Set3
20
- self.theme = {
21
- "background": "rgba(0,0,0,0)",
22
- "grid": "rgba(200,200,200,0.1)",
23
- "critical": "#FF6B6B",
24
- "warning": "#FFE66D",
25
- "success": "#4ECDC4",
26
- "info": "#45B7D1"
27
  }
28
 
29
- def create_interactive_timeline(self, scenario: IncidentScenario) -> go.Figure:
30
- """Create truly interactive timeline with annotations"""
 
 
 
 
 
 
31
  fig = go.Figure()
32
 
33
- # Create timeline events
34
- events = [
35
- {"time": "T-5m", "event": "📉 Cache hit rate drops below 20%", "type": "problem"},
36
- {"time": "T-4m", "event": "⚠️ Database load exceeds 90%", "type": "alert"},
37
- {"time": "T-3m", "event": "🤖 ARF detects pattern", "type": "detection"},
38
- {"time": "T-2m", "event": "🧠 Analysis complete", "type": "analysis"},
39
- {"time": "T-1m", "event": "⚡ Healing executed", "type": "action"},
40
- {"time": "T-0m", "event": "✅ System recovered", "type": "recovery"}
41
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- # Color mapping
44
- color_map = {
45
- "problem": self.theme["critical"],
46
- "alert": self.theme["warning"],
47
- "detection": self.theme["info"],
48
- "analysis": "#9B59B6",
49
- "action": self.theme["success"],
50
- "recovery": "#2ECC71"
51
- }
 
 
 
 
 
 
 
52
 
53
- # Add events
54
- for event in events:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  fig.add_trace(go.Scatter(
56
- x=[event["time"]],
57
- y=[1],
58
- mode='markers+text',
59
- marker=dict(
60
- size=20,
61
- color=color_map[event["type"]],
62
- symbol='circle',
63
- line=dict(width=2, color='white')
64
- ),
65
- text=[event["event"]],
66
- textposition="top center",
67
- hoverinfo='text',
68
- name=event["type"].capitalize(),
69
- hovertemplate="<b>%{text}</b><br>Click for details<extra></extra>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  ))
71
 
72
- # Add connecting line
73
- fig.add_trace(go.Scatter(
74
- x=[e["time"] for e in events],
75
- y=[1] * len(events),
76
- mode='lines',
77
- line=dict(color='gray', width=2, dash='dash'),
78
- hoverinfo='none',
79
- showlegend=False
80
- ))
 
81
 
82
  fig.update_layout(
83
- title="<b>Interactive Incident Timeline</b><br><sup>Click events for details</sup>",
84
- height=450,
85
- paper_bgcolor=self.theme["background"],
86
- plot_bgcolor=self.theme["background"],
87
- hovermode='closest',
88
- clickmode='event+select',
89
- yaxis=dict(
90
- showticklabels=False,
91
- range=[0.5, 1.5],
92
- gridcolor=self.theme["grid"]
93
- ),
94
- xaxis=dict(
95
- gridcolor=self.theme["grid"]
96
- ),
97
- showlegend=True,
98
  legend=dict(
99
- yanchor="top",
100
- y=0.99,
101
- xanchor="left",
102
- x=0.01
 
103
  )
104
  )
105
 
106
  return fig
107
 
108
- def create_executive_dashboard(self, user_roi: Optional[Dict] = None) -> go.Figure:
109
- """Create comprehensive executive dashboard - FIXED VERSION"""
110
- # FIX: Handle None or empty user_roi
111
- if user_roi is None:
112
- user_roi = {}
113
-
114
- # Get ROI value safely
115
- roi_value = user_roi.get('roi_multiplier', 5.2)
116
-
117
- # If roi_value is a string with "×", convert it
118
- if isinstance(roi_value, str):
119
- if "×" in roi_value:
120
- try:
121
- roi_value = float(roi_value.replace("×", ""))
122
- except:
123
- roi_value = 5.2
124
- else:
125
- try:
126
- roi_value = float(roi_value)
127
- except:
128
- roi_value = 5.2
129
-
130
- fig = make_subplots(
131
- rows=2, cols=2,
132
- subplot_titles=(
133
- '<b>Cost Transformation</b>',
134
- '<b>Team Capacity Shift</b>',
135
- '<b>MTTR Comparison</b>',
136
- '<b>ROI Analysis</b>'
137
- ),
138
- vertical_spacing=0.2,
139
- horizontal_spacing=0.15
 
 
 
 
 
 
140
  )
141
 
142
- # 1. Cost Transformation
143
- cost_labels = ['Without ARF', 'With ARF Enterprise', 'Net Savings']
144
- cost_values = [2.96, 1.0, 1.96] # In millions
145
-
146
- fig.add_trace(
147
- go.Bar(
148
- x=cost_labels,
149
- y=cost_values,
150
- marker_color=[self.theme["critical"], self.theme["success"], '#45B7D1'],
151
- text=[f'${v}M' for v in cost_values],
152
- textposition='auto',
153
- name='Annual Cost',
154
- hovertemplate="<b>%{x}</b><br>Cost: $%{y}M<extra></extra>"
155
- ),
156
- row=1, col=1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  )
158
 
159
- # 2. Team Capacity Shift
160
- activities = ['Firefighting', 'Innovation', 'Strategic Work']
161
- before = [60, 20, 20]
162
- after = [10, 60, 30]
163
-
164
- fig.add_trace(
165
- go.Bar(
166
- x=activities,
167
- y=before,
168
- name='Before ARF',
169
- marker_color=self.theme["critical"],
170
- opacity=0.7,
171
- hovertemplate="Before: %{y}%%<extra></extra>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  ),
173
- row=1, col=2
174
  )
175
 
176
- fig.add_trace(
177
- go.Bar(
178
- x=activities,
179
- y=after,
180
- name='After ARF Enterprise',
181
- marker_color=self.theme["success"],
182
- opacity=0.7,
183
- hovertemplate="After: %{y}%%<extra></extra>"
184
- ),
185
- row=1, col=2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  )
187
 
188
- # 3. MTTR Comparison
189
- mttr_methods = ['Manual', 'Traditional', 'ARF OSS', 'ARF Enterprise']
190
- mttr_times = [120, 45, 25, 8]
191
-
192
- fig.add_trace(
193
- go.Bar(
194
- x=mttr_methods,
195
- y=mttr_times,
196
- marker_color=[self.theme["critical"], '#FFE66D', '#45B7D1', self.theme["success"]],
197
- text=[f'{t} min' for t in mttr_times],
198
- textposition='auto',
199
- name='MTTR',
200
- hovertemplate="<b>%{x}</b><br>Resolution: %{y} min<extra></extra>"
201
- ),
202
- row=2, col=1
203
  )
204
 
205
- # 4. ROI Gauge
206
- fig.add_trace(
207
- go.Indicator(
208
- mode="gauge+number+delta",
209
- value=roi_value,
210
- title={'text': "<b>ROI Multiplier</b>", 'font': {'size': 16}},
211
- delta={'reference': 1.0, 'increasing': {'color': self.theme["success"]}},
212
- gauge={
213
- 'axis': {'range': [0, 10], 'tickwidth': 1},
214
- 'bar': {'color': self.theme["success"]},
215
- 'steps': [
216
- {'range': [0, 2], 'color': 'lightgray'},
217
- {'range': [2, 4], 'color': 'gray'},
218
- {'range': [4, 6], 'color': 'lightgreen'},
219
- {'range': [6, 10], 'color': self.theme["success"]}
220
- ],
221
- 'threshold': {
222
- 'line': {'color': "red", 'width': 4},
223
- 'thickness': 0.75,
224
- 'value': roi_value
225
- }
226
- }
227
- ),
228
- row=2, col=2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  )
230
 
231
- # Update layout
 
 
 
 
 
 
 
 
 
 
232
  fig.update_layout(
233
- height=700,
234
- showlegend=True,
235
- paper_bgcolor=self.theme["background"],
236
- plot_bgcolor=self.theme["background"],
237
- title_text="<b>Executive Business Dashboard</b>",
238
- barmode='group',
239
- legend=dict(
240
- yanchor="top",
241
- y=0.99,
242
- xanchor="left",
243
- x=0.01,
244
- bgcolor='rgba(255,255,255,0.9)'
245
- )
246
  )
247
 
248
- # Update axes
249
- fig.update_xaxes(title_text="Cost Model", row=1, col=1, gridcolor=self.theme["grid"])
250
- fig.update_yaxes(title_text="Annual Cost ($M)", row=1, col=1, gridcolor=self.theme["grid"])
 
 
 
251
 
252
- fig.update_xaxes(title_text="Activity", row=1, col=2, gridcolor=self.theme["grid"])
253
- fig.update_yaxes(title_text="Time Allocation (%)", row=1, col=2, gridcolor=self.theme["grid"])
 
 
 
 
 
254
 
255
- fig.update_xaxes(title_text="Resolution Method", row=2, col=1, gridcolor=self.theme["grid"])
256
- fig.update_yaxes(title_text="Minutes to Resolve", row=2, col=1, gridcolor=self.theme["grid"])
 
 
 
 
 
 
257
 
258
- return fig
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ Enhanced visualization engine for ARF Demo
3
  """
 
4
  import plotly.graph_objects as go
5
  import plotly.express as px
 
6
  import numpy as np
7
+ import pandas as pd
8
+ from typing import Dict, List, Any, Optional
9
+ import logging
10
+
11
+ logger = logging.getLogger(__name__)
12
 
 
13
 
14
  class EnhancedVisualizationEngine:
15
+ """Enhanced visualization engine with multiple chart types"""
16
 
17
  def __init__(self):
18
+ self.color_palette = {
19
+ "primary": "#3b82f6",
20
+ "success": "#10b981",
21
+ "warning": "#f59e0b",
22
+ "danger": "#ef4444",
23
+ "info": "#8b5cf6",
24
+ "dark": "#1e293b",
25
+ "light": "#f8fafc"
26
  }
27
 
28
+ def create_executive_dashboard(self, data: Optional[Dict] = None) -> go.Figure:
29
+ """Create executive dashboard with ROI visualization"""
30
+ if data is None:
31
+ data = {"roi_multiplier": 5.2}
32
+
33
+ roi_multiplier = data.get("roi_multiplier", 5.2)
34
+
35
+ # Create a multi-panel executive dashboard
36
  fig = go.Figure()
37
 
38
+ # Main ROI gauge
39
+ fig.add_trace(go.Indicator(
40
+ mode="number+gauge",
41
+ value=roi_multiplier,
42
+ title={"text": "<b>ROI Multiplier</b><br>Investment Return"},
43
+ domain={'x': [0.25, 0.75], 'y': [0.6, 1]},
44
+ gauge={
45
+ 'axis': {'range': [0, 10], 'tickwidth': 1},
46
+ 'bar': {'color': self.color_palette["success"]},
47
+ 'steps': [
48
+ {'range': [0, 2], 'color': '#e5e7eb'},
49
+ {'range': [2, 4], 'color': '#d1d5db'},
50
+ {'range': [4, 6], 'color': '#10b981'},
51
+ {'range': [6, 10], 'color': '#059669'}
52
+ ],
53
+ 'threshold': {
54
+ 'line': {'color': "black", 'width': 4},
55
+ 'thickness': 0.75,
56
+ 'value': roi_multiplier
57
+ }
58
+ }
59
+ ))
60
 
61
+ # Add secondary metrics as subplots
62
+ fig.add_trace(go.Indicator(
63
+ mode="number",
64
+ value=85,
65
+ title={"text": "MTTR Reduction"},
66
+ number={'suffix': "%", 'font': {'size': 24}},
67
+ domain={'x': [0.1, 0.4], 'y': [0.2, 0.5]}
68
+ ))
69
+
70
+ fig.add_trace(go.Indicator(
71
+ mode="number",
72
+ value=94,
73
+ title={"text": "Detection Accuracy"},
74
+ number={'suffix': "%", 'font': {'size': 24}},
75
+ domain={'x': [0.6, 0.9], 'y': [0.2, 0.5]}
76
+ ))
77
 
78
+ fig.update_layout(
79
+ height=700,
80
+ paper_bgcolor="rgba(0,0,0,0)",
81
+ plot_bgcolor="rgba(0,0,0,0)",
82
+ font={'family': "Arial, sans-serif"},
83
+ margin=dict(t=50, b=50, l=50, r=50)
84
+ )
85
+
86
+ return fig
87
+
88
+ def create_telemetry_plot(self, scenario_name: str, anomaly_detected: bool = True) -> go.Figure:
89
+ """Create telemetry plot for a scenario"""
90
+ # Generate realistic telemetry data
91
+ time_points = np.arange(0, 100, 1)
92
+
93
+ # Different patterns for different scenarios
94
+ if "Cache" in scenario_name:
95
+ base_data = 100 + 50 * np.sin(time_points * 0.2)
96
+ noise = np.random.normal(0, 8, 100)
97
+ metric_name = "Cache Hit Rate (%)"
98
+ normal_range = (70, 95)
99
+ elif "Database" in scenario_name:
100
+ base_data = 70 + 30 * np.sin(time_points * 0.15)
101
+ noise = np.random.normal(0, 6, 100)
102
+ metric_name = "Connection Pool Usage"
103
+ normal_range = (20, 60)
104
+ elif "Memory" in scenario_name:
105
+ base_data = 50 + 40 * np.sin(time_points * 0.1)
106
+ noise = np.random.normal(0, 10, 100)
107
+ metric_name = "Memory Usage (%)"
108
+ normal_range = (40, 80)
109
+ else:
110
+ base_data = 80 + 20 * np.sin(time_points * 0.25)
111
+ noise = np.random.normal(0, 5, 100)
112
+ metric_name = "System Load"
113
+ normal_range = (50, 90)
114
+
115
+ data = base_data + noise
116
+
117
+ fig = go.Figure()
118
+
119
+ if anomaly_detected:
120
+ # Normal operation
121
  fig.add_trace(go.Scatter(
122
+ x=time_points[:70],
123
+ y=data[:70],
124
+ mode='lines',
125
+ name='Normal Operation',
126
+ line=dict(color=self.color_palette["primary"], width=3),
127
+ fill='tozeroy',
128
+ fillcolor='rgba(59, 130, 246, 0.1)'
129
+ ))
130
+
131
+ # Anomaly period
132
+ fig.add_trace(go.Scatter(
133
+ x=time_points[70:],
134
+ y=data[70:],
135
+ mode='lines',
136
+ name='Anomaly Detected',
137
+ line=dict(color=self.color_palette["danger"], width=3, dash='dash'),
138
+ fill='tozeroy',
139
+ fillcolor='rgba(239, 68, 68, 0.1)'
140
+ ))
141
+
142
+ # Add detection point
143
+ fig.add_vline(
144
+ x=70,
145
+ line_dash="dash",
146
+ line_color=self.color_palette["success"],
147
+ annotation_text="ARF Detection",
148
+ annotation_position="top"
149
+ )
150
+ else:
151
+ # All normal
152
+ fig.add_trace(go.Scatter(
153
+ x=time_points,
154
+ y=data,
155
+ mode='lines',
156
+ name=metric_name,
157
+ line=dict(color=self.color_palette["primary"], width=3),
158
+ fill='tozeroy',
159
+ fillcolor='rgba(59, 130, 246, 0.1)'
160
  ))
161
 
162
+ # Add normal range
163
+ fig.add_hrect(
164
+ y0=normal_range[0],
165
+ y1=normal_range[1],
166
+ fillcolor="rgba(16, 185, 129, 0.1)",
167
+ opacity=0.2,
168
+ line_width=0,
169
+ annotation_text="Normal Range",
170
+ annotation_position="top left"
171
+ )
172
 
173
  fig.update_layout(
174
+ title=f"📈 {metric_name} - Live Telemetry",
175
+ xaxis_title="Time (minutes)",
176
+ yaxis_title=metric_name,
177
+ height=300,
178
+ margin=dict(l=20, r=20, t=50, b=20),
179
+ plot_bgcolor='rgba(0,0,0,0)',
180
+ paper_bgcolor='rgba(0,0,0,0)',
 
 
 
 
 
 
 
 
181
  legend=dict(
182
+ orientation="h",
183
+ yanchor="bottom",
184
+ y=1.02,
185
+ xanchor="right",
186
+ x=1
187
  )
188
  )
189
 
190
  return fig
191
 
192
+ def create_impact_gauge(self, scenario_name: str) -> go.Figure:
193
+ """Create business impact gauge"""
194
+ impact_map = {
195
+ "Cache Miss Storm": {"revenue": 8500, "severity": "critical"},
196
+ "Database Connection Pool Exhaustion": {"revenue": 4200, "severity": "high"},
197
+ "Kubernetes Memory Leak": {"revenue": 5500, "severity": "high"},
198
+ "API Rate Limit Storm": {"revenue": 3800, "severity": "medium"},
199
+ "Network Partition": {"revenue": 12000, "severity": "critical"},
200
+ "Storage I/O Saturation": {"revenue": 6800, "severity": "high"}
201
+ }
202
+
203
+ impact = impact_map.get(scenario_name, {"revenue": 5000, "severity": "medium"})
204
+
205
+ fig = go.Figure(go.Indicator(
206
+ mode="gauge+number",
207
+ value=impact["revenue"],
208
+ title={'text': "💰 Hourly Revenue Risk", 'font': {'size': 16}},
209
+ number={'prefix': "$", 'font': {'size': 28}},
210
+ gauge={
211
+ 'axis': {'range': [0, 15000], 'tickwidth': 1},
212
+ 'bar': {'color': self._get_severity_color(impact["severity"])},
213
+ 'steps': [
214
+ {'range': [0, 3000], 'color': '#10b981'},
215
+ {'range': [3000, 7000], 'color': '#f59e0b'},
216
+ {'range': [7000, 15000], 'color': '#ef4444'}
217
+ ],
218
+ 'threshold': {
219
+ 'line': {'color': "black", 'width': 4},
220
+ 'thickness': 0.75,
221
+ 'value': impact["revenue"]
222
+ }
223
+ }
224
+ ))
225
+
226
+ fig.update_layout(
227
+ height=300,
228
+ margin=dict(l=20, r=20, t=50, b=20),
229
+ paper_bgcolor='rgba(0,0,0,0)'
230
  )
231
 
232
+ return fig
233
+
234
+ def create_agent_performance_chart(self) -> go.Figure:
235
+ """Create agent performance comparison chart"""
236
+ agents = ["Detection", "Recall", "Decision"]
237
+ accuracy = [98.7, 92.0, 94.0]
238
+ speed = [45, 30, 60] # seconds
239
+ confidence = [99.8, 92.0, 94.0]
240
+
241
+ fig = go.Figure(data=[
242
+ go.Bar(name='Accuracy (%)', x=agents, y=accuracy,
243
+ marker_color=self.color_palette["primary"]),
244
+ go.Bar(name='Speed (seconds)', x=agents, y=speed,
245
+ marker_color=self.color_palette["success"]),
246
+ go.Bar(name='Confidence (%)', x=agents, y=confidence,
247
+ marker_color=self.color_palette["info"])
248
+ ])
249
+
250
+ fig.update_layout(
251
+ title="🤖 Agent Performance Metrics",
252
+ barmode='group',
253
+ height=400,
254
+ plot_bgcolor='rgba(0,0,0,0)',
255
+ paper_bgcolor='rgba(0,0,0,0)',
256
+ legend=dict(
257
+ orientation="h",
258
+ yanchor="bottom",
259
+ y=1.02,
260
+ xanchor="right",
261
+ x=1
262
+ )
263
  )
264
 
265
+ return fig
266
+
267
+ def create_timeline_comparison(self) -> go.Figure:
268
+ """Create timeline comparison chart"""
269
+ phases = ["Detection", "Analysis", "Decision", "Execution", "Recovery"]
270
+ manual_times = [300, 1800, 1200, 1800, 3600] # seconds
271
+ arf_times = [45, 30, 60, 720, 0]
272
+
273
+ # Convert to minutes for readability
274
+ manual_times_min = [t/60 for t in manual_times]
275
+ arf_times_min = [t/60 for t in arf_times]
276
+
277
+ fig = go.Figure()
278
+
279
+ fig.add_trace(go.Bar(
280
+ name='Manual Process',
281
+ x=phases,
282
+ y=manual_times_min,
283
+ marker_color=self.color_palette["danger"],
284
+ text=[f"{t:.0f}m" for t in manual_times_min],
285
+ textposition='auto'
286
+ ))
287
+
288
+ fig.add_trace(go.Bar(
289
+ name='ARF Autonomous',
290
+ x=phases,
291
+ y=arf_times_min,
292
+ marker_color=self.color_palette["success"],
293
+ text=[f"{t:.0f}m" for t in arf_times_min],
294
+ textposition='auto'
295
+ ))
296
+
297
+ total_manual = sum(manual_times_min)
298
+ total_arf = sum(arf_times_min)
299
+
300
+ fig.update_layout(
301
+ title=f"⏰ Incident Timeline Comparison<br>"
302
+ f"<span style='font-size: 14px; color: #6b7280'>"
303
+ f"Total: {total_manual:.0f}m manual vs {total_arf:.0f}m ARF "
304
+ f"({((total_manual - total_arf) / total_manual * 100):.0f}% faster)</span>",
305
+ barmode='group',
306
+ height=400,
307
+ plot_bgcolor='rgba(0,0,0,0)',
308
+ paper_bgcolor='rgba(0,0,0,0)',
309
+ legend=dict(
310
+ orientation="h",
311
+ yanchor="bottom",
312
+ y=1.02,
313
+ xanchor="right",
314
+ x=1
315
  ),
316
+ yaxis_title="Time (minutes)"
317
  )
318
 
319
+ return fig
320
+
321
+ def create_roi_simulation_chart(self, roi_data: Dict) -> go.Figure:
322
+ """Create ROI simulation chart"""
323
+ scenarios = ["Worst Case", "Base Case", "Best Case"]
324
+ roi_values = [
325
+ roi_data.get("worst_case", 4.0),
326
+ roi_data.get("base_case", 5.2),
327
+ roi_data.get("best_case", 6.5)
328
+ ]
329
+
330
+ fig = go.Figure(go.Bar(
331
+ x=scenarios,
332
+ y=roi_values,
333
+ marker_color=[
334
+ self.color_palette["warning"],
335
+ self.color_palette["success"],
336
+ self.color_palette["primary"]
337
+ ],
338
+ text=[f"{v:.1f}×" for v in roi_values],
339
+ textposition='auto'
340
+ ))
341
+
342
+ fig.update_layout(
343
+ title="📊 ROI Simulation Scenarios",
344
+ yaxis_title="ROI Multiplier",
345
+ height=400,
346
+ plot_bgcolor='rgba(0,0,0,0)',
347
+ paper_bgcolor='rgba(0,0,0,0)',
348
+ yaxis=dict(range=[0, max(roi_values) * 1.2])
349
  )
350
 
351
+ # Add industry average line
352
+ fig.add_hline(
353
+ y=5.2,
354
+ line_dash="dash",
355
+ line_color="gray",
356
+ annotation_text="Industry Average",
357
+ annotation_position="top right"
 
 
 
 
 
 
 
 
358
  )
359
 
360
+ return fig
361
+
362
+ def create_learning_graph(self, graph_type: str = "patterns") -> go.Figure:
363
+ """Create learning engine visualization"""
364
+ if graph_type == "patterns":
365
+ return self._create_pattern_graph()
366
+ elif graph_type == "dependencies":
367
+ return self._create_dependency_graph()
368
+ else:
369
+ return self._create_action_graph()
370
+
371
+ def _create_pattern_graph(self) -> go.Figure:
372
+ """Create pattern recognition graph"""
373
+ nodes = ["Cache Miss", "DB Pool", "Memory Leak", "API Limit", "Network"]
374
+ connections = [
375
+ ("Cache Miss", "DB Pool", 0.85),
376
+ ("DB Pool", "Memory Leak", 0.72),
377
+ ("Memory Leak", "API Limit", 0.65),
378
+ ("API Limit", "Network", 0.58),
379
+ ("Cache Miss", "Network", 0.45)
380
+ ]
381
+
382
+ fig = go.Figure()
383
+
384
+ # Add nodes
385
+ for node in nodes:
386
+ fig.add_trace(go.Scatter(
387
+ x=[np.random.random()],
388
+ y=[np.random.random()],
389
+ mode='markers+text',
390
+ name=node,
391
+ marker=dict(size=30, color=self.color_palette["primary"]),
392
+ text=[node],
393
+ textposition="top center"
394
+ ))
395
+
396
+ # Add edges
397
+ for src, dst, weight in connections:
398
+ fig.add_trace(go.Scatter(
399
+ x=[np.random.random(), np.random.random()],
400
+ y=[np.random.random(), np.random.random()],
401
+ mode='lines',
402
+ line=dict(width=weight * 5, color='gray'),
403
+ showlegend=False
404
+ ))
405
+
406
+ fig.update_layout(
407
+ title="🧠 RAG Memory - Incident Pattern Graph",
408
+ height=500,
409
+ plot_bgcolor='rgba(0,0,0,0)',
410
+ paper_bgcolor='rgba(0,0,0,0)',
411
+ showlegend=False,
412
+ xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
413
+ yaxis=dict(showgrid=False, zeroline=False, showticklabels=False)
414
  )
415
 
416
+ return fig
417
+
418
+ def _create_dependency_graph(self) -> go.Figure:
419
+ """Create system dependency graph"""
420
+ fig = go.Figure(go.Sunburst(
421
+ labels=["System", "Cache", "Database", "API", "User Service", "Payment"],
422
+ parents=["", "System", "System", "System", "API", "API"],
423
+ values=[100, 30, 40, 30, 15, 15],
424
+ marker=dict(colors=px.colors.sequential.Blues)
425
+ ))
426
+
427
  fig.update_layout(
428
+ title="🔗 System Dependency Map",
429
+ height=500,
430
+ plot_bgcolor='rgba(0,0,0,0)',
431
+ paper_bgcolor='rgba(0,0,0,0)'
 
 
 
 
 
 
 
 
 
432
  )
433
 
434
+ return fig
435
+
436
+ def _create_action_graph(self) -> go.Figure:
437
+ """Create action-outcome graph"""
438
+ actions = ["Scale Cache", "Restart DB", "Limit API", "Monitor Memory"]
439
+ success_rates = [87, 92, 78, 85]
440
 
441
+ fig = go.Figure(go.Bar(
442
+ x=actions,
443
+ y=success_rates,
444
+ marker_color=self.color_palette["success"],
445
+ text=[f"{rate}%" for rate in success_rates],
446
+ textposition='auto'
447
+ ))
448
 
449
+ fig.update_layout(
450
+ title="🎯 Action Success Rates",
451
+ yaxis_title="Success Rate (%)",
452
+ height=400,
453
+ plot_bgcolor='rgba(0,0,0,0)',
454
+ paper_bgcolor='rgba(0,0,0,0)',
455
+ yaxis=dict(range=[0, 100])
456
+ )
457
 
458
+ return fig
459
+
460
+ def _get_severity_color(self, severity: str) -> str:
461
+ """Get color for severity level"""
462
+ color_map = {
463
+ "critical": self.color_palette["danger"],
464
+ "high": self.color_palette["warning"],
465
+ "medium": self.color_palette["info"],
466
+ "low": self.color_palette["success"]
467
+ }
468
+ return color_map.get(severity.lower(), self.color_palette["info"])