Spaces:
Sleeping
Sleeping
File size: 5,097 Bytes
5ada319 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
from typing import List, Dict, Any, Optional
import json
from pydantic import BaseModel
from loguru import logger
# Mocking Blaxel SDK for now as it's a hypothetical or external dependency not in requirements
# In a real scenario, we would import: from blaxel import Scene, Node, Edge, Animation
# We will generate a Plotly 3D scatter plot as a fallback/implementation of the concept
import plotly.graph_objects as go
class StackFrame(BaseModel):
function: str
file: str
line: int
is_external: bool = False
class ErrorFlowVisualizer:
def __init__(self):
pass
def _get_node_color(self, idx: int, total: int, is_external: bool) -> str:
if is_external:
return "purple"
if idx == 0:
return "green" # Entry
if idx == total - 1:
return "red" # Error
return "blue" # Normal
def generate_flow(self, stack_trace: List[Dict[str, Any]]) -> str:
"""
Generate 3D visualization of error flow.
Returns HTML string of the visualization.
"""
try:
frames = [StackFrame(**f) for f in stack_trace]
if not frames:
return "<div>No stack trace available for visualization.</div>"
# Limit nodes for performance
if len(frames) > 50:
frames = frames[-50:]
# 3D Coordinates layout (simple spiral or linear)
x_coords = []
y_coords = []
z_coords = []
colors = []
sizes = []
hover_texts = []
for idx, frame in enumerate(frames):
# Simple linear layout along X axis, with slight spiral
x_coords.append(idx * 2)
y_coords.append(0)
z_coords.append(0)
color = self._get_node_color(idx, len(frames), frame.is_external)
colors.append(color)
# Pulse effect for error node (simulated by larger size)
size = 20 if idx == len(frames) - 1 else 12
sizes.append(size)
hover_texts.append(
f"<b>{frame.function}</b><br>"
f"{frame.file}:{frame.line}<br>"
f"{'External Library' if frame.is_external else 'User Code'}"
)
# Create Nodes Trace
node_trace = go.Scatter3d(
x=x_coords, y=y_coords, z=z_coords,
mode='markers+text',
marker=dict(
size=sizes,
color=colors,
opacity=0.8,
line=dict(width=2, color='white')
),
text=[f.function for f in frames],
textposition="top center",
hoverinfo='text',
hovertext=hover_texts
)
# Create Edges Trace
edge_x = []
edge_y = []
edge_z = []
for i in range(len(frames) - 1):
edge_x.extend([x_coords[i], x_coords[i+1], None])
edge_y.extend([y_coords[i], y_coords[i+1], None])
edge_z.extend([z_coords[i], z_coords[i+1], None])
edge_trace = go.Scatter3d(
x=edge_x, y=edge_y, z=edge_z,
mode='lines',
line=dict(color='#888', width=2),
hoverinfo='none'
)
# Layout
layout = go.Layout(
title="3D Error Flow Visualization",
showlegend=False,
scene=dict(
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
zaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
bgcolor='rgba(0,0,0,0)'
),
margin=dict(l=0, r=0, b=0, t=30),
height=500
)
fig = go.Figure(data=[edge_trace, node_trace], layout=layout)
# Return HTML div
return fig.to_html(full_html=False, include_plotlyjs='cdn')
except Exception as e:
logger.error(f"Visualization generation failed: {e}")
return f"<div>Error generating visualization: {str(e)}</div>"
def generate_mock_trace(self) -> List[Dict[str, Any]]:
"""Generate a mock trace for testing."""
return [
{"function": "main", "file": "app.py", "line": 10, "is_external": False},
{"function": "process_request", "file": "core/handler.py", "line": 45, "is_external": False},
{"function": "validate_input", "file": "utils/validation.py", "line": 12, "is_external": False},
{"function": "json.loads", "file": "json/decoder.py", "line": 337, "is_external": True},
{"function": "decode", "file": "json/decoder.py", "line": 355, "is_external": True},
]
|