Compare commits
2 Commits
4dd632012f
...
2ab3f1fe9e
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ab3f1fe9e | |||
| a3c50fd845 |
@@ -19,7 +19,8 @@ import time
|
|||||||
from .widgets.sparkline import SparklineWidget
|
from .widgets.sparkline import SparklineWidget
|
||||||
from .widgets.metric_card import MetricCard
|
from .widgets.metric_card import MetricCard
|
||||||
from .widgets.flow_table_v2 import EnhancedFlowTable
|
from .widgets.flow_table_v2 import EnhancedFlowTable
|
||||||
from .widgets.flow_details import FlowDetailsPanel
|
from .widgets.split_flow_details import FlowMainDetailsPanel, SubFlowDetailsPanel
|
||||||
|
from .widgets.debug_panel import DebugPanel
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ...analysis.core import EthernetAnalyzer
|
from ...analysis.core import EthernetAnalyzer
|
||||||
@@ -59,6 +60,7 @@ class StreamLensAppV2(App):
|
|||||||
bytes_per_sec = reactive(0.0)
|
bytes_per_sec = reactive(0.0)
|
||||||
enhanced_flows = reactive(0)
|
enhanced_flows = reactive(0)
|
||||||
outlier_count = reactive(0)
|
outlier_count = reactive(0)
|
||||||
|
debug_visible = reactive(False) # Hide debug panel for now
|
||||||
|
|
||||||
# Update timers
|
# Update timers
|
||||||
metric_timer: Timer = None
|
metric_timer: Timer = None
|
||||||
@@ -90,25 +92,41 @@ class StreamLensAppV2(App):
|
|||||||
yield MetricCard("Enhanced", f"{self.enhanced_flows}", color="success", id="enhanced-metric")
|
yield MetricCard("Enhanced", f"{self.enhanced_flows}", color="success", id="enhanced-metric")
|
||||||
yield MetricCard("Outliers", f"{self.outlier_count}", color="warning" if self.outlier_count > 0 else "normal", id="outliers-metric")
|
yield MetricCard("Outliers", f"{self.outlier_count}", color="warning" if self.outlier_count > 0 else "normal", id="outliers-metric")
|
||||||
|
|
||||||
# Main content area with horizontal split
|
# Main content area with conditional debug panel
|
||||||
with Horizontal(id="content-area"):
|
with Horizontal(id="content-area"):
|
||||||
# Left - Enhanced flow table (wider)
|
# Left - Enhanced flow table
|
||||||
with Vertical(id="left-panel", classes="panel-wide"):
|
|
||||||
yield EnhancedFlowTable(
|
yield EnhancedFlowTable(
|
||||||
self.analyzer,
|
self.analyzer,
|
||||||
id="flow-table"
|
id="flow-table",
|
||||||
|
classes="panel-wide"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Right - Selected flow details
|
# Middle - Flow details
|
||||||
with Vertical(id="right-panel", classes="panel"):
|
with Vertical(id="flow-panels"):
|
||||||
yield FlowDetailsPanel(
|
yield FlowMainDetailsPanel(id="main-flow-details")
|
||||||
id="flow-details"
|
yield SubFlowDetailsPanel(id="sub-flow-details")
|
||||||
)
|
|
||||||
|
# Right - Debug panel (conditionally visible)
|
||||||
|
if self.debug_visible:
|
||||||
|
yield DebugPanel(id="debug-panel")
|
||||||
|
|
||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
def on_mount(self) -> None:
|
||||||
"""Initialize the application with TipTop-style updates"""
|
"""Initialize the application with TipTop-style updates"""
|
||||||
|
try:
|
||||||
|
debug_panel = self.query_one("#debug-panel", DebugPanel)
|
||||||
|
debug_panel.add_debug_message("APP: Application mounted, checking panels...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
main_panel = self.query_one("#main-flow-details", FlowMainDetailsPanel)
|
||||||
|
sub_panel = self.query_one("#sub-flow-details", SubFlowDetailsPanel)
|
||||||
|
debug_panel.add_debug_message("APP: Both panels found successfully")
|
||||||
|
except Exception as e:
|
||||||
|
debug_panel.add_debug_message(f"APP: Panel query failed: {e}")
|
||||||
|
except:
|
||||||
|
pass # Debug panel not visible
|
||||||
|
|
||||||
self.update_metrics()
|
self.update_metrics()
|
||||||
|
|
||||||
# Set up update intervals like TipTop
|
# Set up update intervals like TipTop
|
||||||
@@ -240,9 +258,21 @@ class StreamLensAppV2(App):
|
|||||||
|
|
||||||
def on_enhanced_flow_table_flow_selected(self, event: EnhancedFlowTable.FlowSelected) -> None:
|
def on_enhanced_flow_table_flow_selected(self, event: EnhancedFlowTable.FlowSelected) -> None:
|
||||||
"""Handle flow selection events"""
|
"""Handle flow selection events"""
|
||||||
|
try:
|
||||||
|
debug_panel = self.query_one("#debug-panel", DebugPanel)
|
||||||
|
flow_info = f"{event.flow.src_ip}:{event.flow.src_port}" if event.flow else "None"
|
||||||
|
debug_panel.add_debug_message(f"APP: Flow selected - {flow_info}, subflow={event.subflow_type}")
|
||||||
|
except:
|
||||||
|
pass # Debug panel not visible
|
||||||
|
|
||||||
if event.flow:
|
if event.flow:
|
||||||
details_panel = self.query_one("#flow-details", FlowDetailsPanel)
|
# Update main flow details panel
|
||||||
details_panel.update_flow(event.flow)
|
main_panel = self.query_one("#main-flow-details", FlowMainDetailsPanel)
|
||||||
|
main_panel.update_flow(event.flow)
|
||||||
|
|
||||||
|
# Update sub-flow details panel
|
||||||
|
sub_panel = self.query_one("#sub-flow-details", SubFlowDetailsPanel)
|
||||||
|
sub_panel.update_flow(event.flow, event.subflow_type)
|
||||||
|
|
||||||
|
|
||||||
def _format_bytes_per_sec(self, bps: float) -> str:
|
def _format_bytes_per_sec(self, bps: float) -> str:
|
||||||
|
|||||||
@@ -35,15 +35,13 @@ MetricCard {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Panel Styling - Minimal borders */
|
/* Panel Styling - No borders for clean look */
|
||||||
.panel {
|
.panel {
|
||||||
border: solid #99ccff;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-wide {
|
.panel-wide {
|
||||||
border: solid #99ccff;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@@ -62,13 +60,31 @@ MetricCard {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Right Panel - Details (compact) */
|
/* Flow Panels - Details (30% width) */
|
||||||
#right-panel {
|
#flow-panels {
|
||||||
width: 25%;
|
width: 30%;
|
||||||
background: #1a1a1a;
|
background: #1a1a1a;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlowMainDetailsPanel {
|
||||||
|
height: 3fr;
|
||||||
|
background: #1a1a1a;
|
||||||
|
border: solid #ff8800;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubFlowDetailsPanel {
|
||||||
|
height: 2fr;
|
||||||
|
background: #1a1a1a;
|
||||||
|
border: solid #ff8800;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Debug Panel - Fixed width when visible */
|
||||||
|
#debug-panel {
|
||||||
|
width: 25%;
|
||||||
|
background: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sparkline Charts */
|
/* Sparkline Charts */
|
||||||
SparklineWidget {
|
SparklineWidget {
|
||||||
height: 5;
|
height: 5;
|
||||||
@@ -188,9 +204,6 @@ DataTable:focus {
|
|||||||
border: solid #00ffcc;
|
border: solid #00ffcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Panel Borders */
|
/* Panel Borders - Removed for clean look */
|
||||||
Static {
|
|
||||||
border: round #0080ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* End of styles */
|
/* End of styles */
|
||||||
69
analyzer/tui/textual/widgets/debug_panel.py
Normal file
69
analyzer/tui/textual/widgets/debug_panel.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
"""
|
||||||
|
Debug Panel - Real-time debugging information in TUI
|
||||||
|
"""
|
||||||
|
|
||||||
|
from textual.widget import Widget
|
||||||
|
from textual.containers import Vertical
|
||||||
|
from textual.widgets import Static
|
||||||
|
from rich.text import Text
|
||||||
|
from rich.console import RenderableType
|
||||||
|
from typing import Optional, List
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class DebugPanel(Vertical):
|
||||||
|
"""Debug panel showing real-time flow selection and logic information"""
|
||||||
|
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
DebugPanel {
|
||||||
|
height: 1fr;
|
||||||
|
padding: 1;
|
||||||
|
background: #1a1a1a;
|
||||||
|
border: solid #ff0080;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugPanel Static {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.debug_messages = []
|
||||||
|
self.max_messages = 20
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
"""Create the debug panel layout"""
|
||||||
|
yield Static("DEBUG PANEL", classes="panel-header")
|
||||||
|
yield Static(
|
||||||
|
"Waiting for flow selection...",
|
||||||
|
id="debug-content"
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_debug_message(self, message: str) -> None:
|
||||||
|
"""Add a debug message with timestamp"""
|
||||||
|
timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
||||||
|
full_message = f"[{timestamp}] {message}"
|
||||||
|
|
||||||
|
self.debug_messages.append(full_message)
|
||||||
|
if len(self.debug_messages) > self.max_messages:
|
||||||
|
self.debug_messages.pop(0)
|
||||||
|
|
||||||
|
self._update_display()
|
||||||
|
|
||||||
|
def _update_display(self) -> None:
|
||||||
|
"""Update the debug display with recent messages"""
|
||||||
|
content_widget = self.query_one("#debug-content", Static)
|
||||||
|
|
||||||
|
if not self.debug_messages:
|
||||||
|
content_widget.update("No debug messages yet...")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Show recent messages, newest at bottom
|
||||||
|
display_text = "\n".join(self.debug_messages[-15:]) # Show last 15 messages
|
||||||
|
content_widget.update(Text(display_text, style="white"))
|
||||||
|
|
||||||
|
def clear_messages(self) -> None:
|
||||||
|
"""Clear all debug messages"""
|
||||||
|
self.debug_messages.clear()
|
||||||
|
self._update_display()
|
||||||
@@ -75,6 +75,9 @@ class EnhancedFlowTable(Vertical):
|
|||||||
table.add_column("Frame Type", width=10, key="frame_type")
|
table.add_column("Frame Type", width=10, key="frame_type")
|
||||||
table.add_column("Pkts", width=6, key="rate")
|
table.add_column("Pkts", width=6, key="rate")
|
||||||
table.add_column("Size", width=8, key="volume")
|
table.add_column("Size", width=8, key="volume")
|
||||||
|
table.add_column("ΔT(ms)", width=8, key="delta_t")
|
||||||
|
table.add_column("σ(ms)", width=8, key="sigma")
|
||||||
|
table.add_column("Out", width=5, key="outliers")
|
||||||
|
|
||||||
self.refresh_data()
|
self.refresh_data()
|
||||||
|
|
||||||
@@ -95,6 +98,7 @@ class EnhancedFlowTable(Vertical):
|
|||||||
|
|
||||||
# Clear row mapping
|
# Clear row mapping
|
||||||
self.row_to_flow_map.clear()
|
self.row_to_flow_map.clear()
|
||||||
|
self.row_to_subflow_map = {} # Map row keys to (flow_index, subflow_type)
|
||||||
|
|
||||||
# Get and sort flows
|
# Get and sort flows
|
||||||
self.flows_list = self._get_sorted_flows()
|
self.flows_list = self._get_sorted_flows()
|
||||||
@@ -139,10 +143,14 @@ class EnhancedFlowTable(Vertical):
|
|||||||
# Add sub-rows for protocol breakdown
|
# Add sub-rows for protocol breakdown
|
||||||
if self._should_show_subrows(flow):
|
if self._should_show_subrows(flow):
|
||||||
sub_rows = self._create_protocol_subrows(flow)
|
sub_rows = self._create_protocol_subrows(flow)
|
||||||
|
combinations = self._get_protocol_frame_combinations(flow)
|
||||||
for j, sub_row in enumerate(sub_rows):
|
for j, sub_row in enumerate(sub_rows):
|
||||||
sub_key = table.add_row(*sub_row, key=f"flow_{i}_sub_{j}")
|
sub_key = table.add_row(*sub_row, key=f"flow_{i}_sub_{j}")
|
||||||
# Map sub-row to parent flow
|
# Map sub-row to parent flow and subflow type
|
||||||
self.row_to_flow_map[sub_key] = i
|
self.row_to_flow_map[sub_key] = i
|
||||||
|
if j < len(combinations):
|
||||||
|
_, frame_type, _, _ = combinations[j]
|
||||||
|
self.row_to_subflow_map[sub_key] = (i, frame_type)
|
||||||
|
|
||||||
# Restore cursor position
|
# Restore cursor position
|
||||||
if selected_row_key and selected_row_key in table.rows:
|
if selected_row_key and selected_row_key in table.rows:
|
||||||
@@ -188,24 +196,37 @@ class EnhancedFlowTable(Vertical):
|
|||||||
size_value = self._format_bytes(flow.total_bytes)
|
size_value = self._format_bytes(flow.total_bytes)
|
||||||
size_text = Text(f"{size_value:>8}")
|
size_text = Text(f"{size_value:>8}")
|
||||||
|
|
||||||
# Quality with bar chart and color
|
# Delta T (average time between packets in ms)
|
||||||
quality_bar, quality_color = self._create_quality_bar(flow)
|
if flow.avg_inter_arrival > 0:
|
||||||
quality_value = self._get_quality_score(flow)
|
delta_t_ms = flow.avg_inter_arrival * 1000
|
||||||
quality_text = Text(f"{quality_value:>3}% {quality_bar}", style=quality_color)
|
if delta_t_ms >= 1000:
|
||||||
|
delta_t_str = f"{delta_t_ms/1000:.1f}s"
|
||||||
|
else:
|
||||||
|
delta_t_str = f"{delta_t_ms:.1f}"
|
||||||
|
else:
|
||||||
|
delta_t_str = "N/A"
|
||||||
|
delta_t_text = Text(delta_t_str, justify="right")
|
||||||
|
|
||||||
# Status indicator
|
# Sigma (standard deviation in ms)
|
||||||
status = self._get_flow_status(flow)
|
if flow.std_inter_arrival > 0:
|
||||||
status_color = {
|
sigma_ms = flow.std_inter_arrival * 1000
|
||||||
"Normal": "green",
|
if sigma_ms >= 1000:
|
||||||
"Enhanced": "bold green",
|
sigma_str = f"{sigma_ms/1000:.1f}s"
|
||||||
"Warning": "yellow",
|
else:
|
||||||
"Alert": "red"
|
sigma_str = f"{sigma_ms:.1f}"
|
||||||
}.get(status, "white")
|
else:
|
||||||
status_text = Text(status, style=status_color)
|
sigma_str = "N/A"
|
||||||
|
sigma_text = Text(sigma_str, justify="right")
|
||||||
|
|
||||||
|
# Outlier count (packets outside tolerance)
|
||||||
|
outlier_count = len(flow.outlier_frames)
|
||||||
|
outlier_text = Text(str(outlier_count), justify="right",
|
||||||
|
style="red" if outlier_count > 0 else "green")
|
||||||
|
|
||||||
return [
|
return [
|
||||||
num_text, source_text, proto_text, dest_text,
|
num_text, source_text, proto_text, dest_text,
|
||||||
extended_text, frame_text, rate_text, size_text
|
extended_text, frame_text, rate_text, size_text,
|
||||||
|
delta_t_text, sigma_text, outlier_text
|
||||||
]
|
]
|
||||||
|
|
||||||
def _create_rate_sparkline(self, history: List[float]) -> str:
|
def _create_rate_sparkline(self, history: List[float]) -> str:
|
||||||
@@ -307,7 +328,22 @@ class EnhancedFlowTable(Vertical):
|
|||||||
subrows = []
|
subrows = []
|
||||||
combinations = self._get_protocol_frame_combinations(flow)
|
combinations = self._get_protocol_frame_combinations(flow)
|
||||||
|
|
||||||
for extended_proto, frame_type, count, percentage in combinations[:3]: # Max 3 subrows
|
for extended_proto, frame_type, count, percentage in combinations: # Show all subrows
|
||||||
|
# Calculate timing for this frame type if available
|
||||||
|
frame_delta_t = ""
|
||||||
|
frame_sigma = ""
|
||||||
|
frame_outliers = ""
|
||||||
|
|
||||||
|
if frame_type in flow.frame_types:
|
||||||
|
ft_stats = flow.frame_types[frame_type]
|
||||||
|
if ft_stats.avg_inter_arrival > 0:
|
||||||
|
dt_ms = ft_stats.avg_inter_arrival * 1000
|
||||||
|
frame_delta_t = f"{dt_ms:.1f}" if dt_ms < 1000 else f"{dt_ms/1000:.1f}s"
|
||||||
|
if ft_stats.std_inter_arrival > 0:
|
||||||
|
sig_ms = ft_stats.std_inter_arrival * 1000
|
||||||
|
frame_sigma = f"{sig_ms:.1f}" if sig_ms < 1000 else f"{sig_ms/1000:.1f}s"
|
||||||
|
frame_outliers = str(len(ft_stats.outlier_frames))
|
||||||
|
|
||||||
subrow = [
|
subrow = [
|
||||||
Text(""), # Empty flow number
|
Text(""), # Empty flow number
|
||||||
Text(""), # Empty source
|
Text(""), # Empty source
|
||||||
@@ -316,7 +352,10 @@ class EnhancedFlowTable(Vertical):
|
|||||||
Text(f" {extended_proto}", style="dim yellow"),
|
Text(f" {extended_proto}", style="dim yellow"),
|
||||||
Text(frame_type, style="dim blue"),
|
Text(frame_type, style="dim blue"),
|
||||||
Text(f"{count}", style="dim", justify="right"),
|
Text(f"{count}", style="dim", justify="right"),
|
||||||
Text(f"{self._format_bytes(count * (flow.total_bytes // flow.frame_count) if flow.frame_count > 0 else 0):>8}", style="dim")
|
Text(f"{self._format_bytes(count * (flow.total_bytes // flow.frame_count) if flow.frame_count > 0 else 0):>8}", style="dim"),
|
||||||
|
Text(frame_delta_t, style="dim", justify="right"),
|
||||||
|
Text(frame_sigma, style="dim", justify="right"),
|
||||||
|
Text(frame_outliers, style="dim red" if frame_outliers and int(frame_outliers) > 0 else "dim", justify="right")
|
||||||
]
|
]
|
||||||
subrows.append(subrow)
|
subrows.append(subrow)
|
||||||
|
|
||||||
@@ -348,8 +387,9 @@ class EnhancedFlowTable(Vertical):
|
|||||||
|
|
||||||
class FlowSelected(Message):
|
class FlowSelected(Message):
|
||||||
"""Message sent when a flow is selected"""
|
"""Message sent when a flow is selected"""
|
||||||
def __init__(self, flow: Optional['FlowStats']) -> None:
|
def __init__(self, flow: Optional['FlowStats'], subflow_type: Optional[str] = None) -> None:
|
||||||
self.flow = flow
|
self.flow = flow
|
||||||
|
self.subflow_type = subflow_type
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def get_selected_flow(self) -> Optional['FlowStats']:
|
def get_selected_flow(self) -> Optional['FlowStats']:
|
||||||
@@ -372,10 +412,43 @@ class EnhancedFlowTable(Vertical):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_selected_subflow_type(self) -> Optional[str]:
|
||||||
|
"""Get currently selected sub-flow type if applicable"""
|
||||||
|
table = self.query_one("#flows-data-table", DataTable)
|
||||||
|
if table.cursor_row is None or not table.rows:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Get the row key at cursor position
|
||||||
|
row_keys = list(table.rows.keys())
|
||||||
|
if table.cursor_row >= len(row_keys):
|
||||||
|
return None
|
||||||
|
|
||||||
|
row_key = row_keys[table.cursor_row]
|
||||||
|
|
||||||
|
# Check if this is a sub-row
|
||||||
|
if row_key in self.row_to_subflow_map:
|
||||||
|
_, subflow_type = self.row_to_subflow_map[row_key]
|
||||||
|
return subflow_type
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def on_data_table_row_highlighted(self, event: DataTable.RowHighlighted) -> None:
|
def on_data_table_row_highlighted(self, event: DataTable.RowHighlighted) -> None:
|
||||||
"""Handle row highlight to update selection"""
|
"""Handle row highlight to update selection"""
|
||||||
selected_flow = self.get_selected_flow()
|
selected_flow = self.get_selected_flow()
|
||||||
self.post_message(self.FlowSelected(selected_flow))
|
subflow_type = self.get_selected_subflow_type()
|
||||||
|
|
||||||
|
# Debug through app's debug panel
|
||||||
|
flow_info = f"{selected_flow.src_ip}:{selected_flow.src_port}" if selected_flow else "None"
|
||||||
|
table = self.query_one("#flows-data-table", DataTable)
|
||||||
|
current_row = table.cursor_row if table.cursor_row is not None else -1
|
||||||
|
|
||||||
|
try:
|
||||||
|
debug_panel = self.app.query_one("#debug-panel")
|
||||||
|
debug_panel.add_debug_message(f"TABLE: Row {current_row} - {flow_info}, subflow:{subflow_type}")
|
||||||
|
except:
|
||||||
|
pass # Debug panel might not be available yet
|
||||||
|
|
||||||
|
self.post_message(self.FlowSelected(selected_flow, subflow_type))
|
||||||
|
|
||||||
# Helper methods from original implementation
|
# Helper methods from original implementation
|
||||||
def _get_extended_protocol(self, flow: 'FlowStats') -> str:
|
def _get_extended_protocol(self, flow: 'FlowStats') -> str:
|
||||||
|
|||||||
367
analyzer/tui/textual/widgets/split_flow_details.py
Normal file
367
analyzer/tui/textual/widgets/split_flow_details.py
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
"""
|
||||||
|
Split Flow Details Panel - Top/Bottom layout for flow and sub-flow details
|
||||||
|
"""
|
||||||
|
|
||||||
|
from textual.widget import Widget
|
||||||
|
from textual.containers import Vertical
|
||||||
|
from textual.widgets import Static
|
||||||
|
from textual.reactive import reactive
|
||||||
|
from rich.text import Text
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.console import RenderableType, Group
|
||||||
|
from rich.table import Table
|
||||||
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ....models import FlowStats, FrameTypeStats
|
||||||
|
|
||||||
|
|
||||||
|
class FlowMainDetailsPanel(Vertical):
|
||||||
|
"""Top panel showing main flow details"""
|
||||||
|
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
FlowMainDetailsPanel {
|
||||||
|
height: 1fr;
|
||||||
|
padding: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowMainDetailsPanel Static {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.current_flow = None
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
"""Create the main flow details layout"""
|
||||||
|
yield Static("Main Flow Details", classes="panel-header")
|
||||||
|
yield Static(
|
||||||
|
"Select a flow to view details",
|
||||||
|
id="main-details-content"
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_flow(self, flow: Optional['FlowStats']) -> None:
|
||||||
|
"""Update panel with main flow details"""
|
||||||
|
flow_info = f"{flow.src_ip}:{flow.src_port}" if flow else "None"
|
||||||
|
try:
|
||||||
|
debug_panel = self.app.query_one("#debug-panel")
|
||||||
|
debug_panel.add_debug_message(f"MAIN_PANEL: Update called - {flow_info}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.current_flow = flow
|
||||||
|
content_widget = self.query_one("#main-details-content", Static)
|
||||||
|
|
||||||
|
if not flow:
|
||||||
|
content_widget.update("Select a flow to view details")
|
||||||
|
return
|
||||||
|
|
||||||
|
details = self._create_main_flow_details(flow)
|
||||||
|
|
||||||
|
# Debug what content we're actually setting
|
||||||
|
try:
|
||||||
|
debug_panel = self.app.query_one("#debug-panel")
|
||||||
|
debug_panel.add_debug_message(f"CONTENT: Setting panel content for {flow.src_ip}:{flow.src_port}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
content_widget.update(details)
|
||||||
|
|
||||||
|
def _create_main_flow_details(self, flow: 'FlowStats') -> RenderableType:
|
||||||
|
"""Create main flow details display"""
|
||||||
|
sections = []
|
||||||
|
|
||||||
|
# Flow identification
|
||||||
|
id_table = Table(show_header=False, box=None, padding=0)
|
||||||
|
id_table.add_column(style="dim", width=12)
|
||||||
|
id_table.add_column()
|
||||||
|
|
||||||
|
id_table.add_row("Source:", f"{flow.src_ip}:{flow.src_port}")
|
||||||
|
id_table.add_row("Destination:", f"{flow.dst_ip}:{flow.dst_port}")
|
||||||
|
id_table.add_row("Protocol:", flow.transport_protocol)
|
||||||
|
id_table.add_row("Packets:", f"{flow.frame_count:,}")
|
||||||
|
id_table.add_row("Volume:", self._format_bytes(flow.total_bytes))
|
||||||
|
|
||||||
|
sections.append(Text("Flow Information", style="bold blue"))
|
||||||
|
sections.append(id_table)
|
||||||
|
|
||||||
|
# Enhanced analysis
|
||||||
|
if flow.enhanced_analysis.decoder_type != "Standard":
|
||||||
|
enhanced_table = Table(show_header=False, box=None, padding=0)
|
||||||
|
enhanced_table.add_column(style="dim", width=12)
|
||||||
|
enhanced_table.add_column()
|
||||||
|
|
||||||
|
enhanced_table.add_row("Decoder:", flow.enhanced_analysis.decoder_type)
|
||||||
|
enhanced_table.add_row("Quality:", f"{flow.enhanced_analysis.avg_frame_quality:.1f}%")
|
||||||
|
enhanced_table.add_row("Fields:", str(flow.enhanced_analysis.field_count))
|
||||||
|
|
||||||
|
if flow.enhanced_analysis.frame_types:
|
||||||
|
types_str = ", ".join(list(flow.enhanced_analysis.frame_types)[:3])
|
||||||
|
if len(flow.enhanced_analysis.frame_types) > 3:
|
||||||
|
types_str += f" +{len(flow.enhanced_analysis.frame_types) - 3}"
|
||||||
|
enhanced_table.add_row("Types:", types_str)
|
||||||
|
|
||||||
|
sections.append(Text("Enhanced Analysis", style="bold green"))
|
||||||
|
sections.append(enhanced_table)
|
||||||
|
|
||||||
|
# Timing analysis - only show if no sub-flows exist
|
||||||
|
# Match the same logic as _should_show_subrows in flow_table_v2.py
|
||||||
|
has_subflows = (len(flow.frame_types) > 1 or
|
||||||
|
flow.enhanced_analysis.decoder_type != "Standard")
|
||||||
|
|
||||||
|
# Debug output
|
||||||
|
try:
|
||||||
|
debug_panel = self.app.query_one("#debug-panel")
|
||||||
|
debug_panel.add_debug_message(f"TIMING_LOGIC: {flow.src_ip}:{flow.src_port} - types={len(flow.frame_types)}, decoder={flow.enhanced_analysis.decoder_type}, has_subflows={has_subflows}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not has_subflows:
|
||||||
|
try:
|
||||||
|
debug_panel = self.app.query_one("#debug-panel")
|
||||||
|
debug_panel.add_debug_message(f"BRANCH: Taking FULL timing branch for {flow.src_ip}:{flow.src_port}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
timing_table = Table(show_header=False, box=None, padding=0)
|
||||||
|
timing_table.add_column(style="dim", width=12)
|
||||||
|
timing_table.add_column()
|
||||||
|
|
||||||
|
timing_table.add_row("Duration:", f"{flow.duration:.2f}s")
|
||||||
|
timing_table.add_row("Avg ΔT:", f"{flow.avg_inter_arrival * 1000:.1f}ms")
|
||||||
|
timing_table.add_row("Std σ:", f"{flow.std_inter_arrival * 1000:.1f}ms")
|
||||||
|
timing_table.add_row("Outliers:", f"{len(flow.outlier_frames)}")
|
||||||
|
timing_table.add_row("Jitter:", f"{flow.jitter * 1000:.2f}ms")
|
||||||
|
timing_table.add_row("First Seen:", self._format_timestamp(flow.first_seen))
|
||||||
|
timing_table.add_row("Last Seen:", self._format_timestamp(flow.last_seen))
|
||||||
|
|
||||||
|
sections.append(Text("Timing Analysis", style="bold cyan"))
|
||||||
|
sections.append(timing_table)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
debug_panel = self.app.query_one("#debug-panel")
|
||||||
|
debug_panel.add_debug_message(f"BRANCH: Taking BASIC timeline branch for {flow.src_ip}:{flow.src_port}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Just show duration and timestamps for flows with sub-flows
|
||||||
|
basic_timing_table = Table(show_header=False, box=None, padding=0)
|
||||||
|
basic_timing_table.add_column(style="dim", width=12)
|
||||||
|
basic_timing_table.add_column()
|
||||||
|
|
||||||
|
basic_timing_table.add_row("Duration:", f"{flow.duration:.2f}s")
|
||||||
|
basic_timing_table.add_row("First Seen:", self._format_timestamp(flow.first_seen))
|
||||||
|
basic_timing_table.add_row("Last Seen:", self._format_timestamp(flow.last_seen))
|
||||||
|
|
||||||
|
sections.append(Text("Flow Timeline", style="bold cyan"))
|
||||||
|
sections.append(basic_timing_table)
|
||||||
|
|
||||||
|
return Group(*sections)
|
||||||
|
|
||||||
|
def _format_bytes(self, bytes_count: int) -> str:
|
||||||
|
"""Format byte count with units"""
|
||||||
|
if bytes_count >= 1_000_000_000:
|
||||||
|
return f"{bytes_count / 1_000_000_000:.2f} GB"
|
||||||
|
elif bytes_count >= 1_000_000:
|
||||||
|
return f"{bytes_count / 1_000_000:.2f} MB"
|
||||||
|
elif bytes_count >= 1_000:
|
||||||
|
return f"{bytes_count / 1_000:.2f} KB"
|
||||||
|
else:
|
||||||
|
return f"{bytes_count} B"
|
||||||
|
|
||||||
|
def _format_timestamp(self, timestamp: float) -> str:
|
||||||
|
"""Format timestamp for display"""
|
||||||
|
import datetime
|
||||||
|
dt = datetime.datetime.fromtimestamp(timestamp)
|
||||||
|
return dt.strftime("%H:%M:%S.%f")[:-3]
|
||||||
|
|
||||||
|
|
||||||
|
class SubFlowDetailsPanel(Vertical):
|
||||||
|
"""Bottom panel showing sub-flow details or summary"""
|
||||||
|
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
SubFlowDetailsPanel {
|
||||||
|
height: 1fr;
|
||||||
|
padding: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubFlowDetailsPanel Static {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.current_flow = None
|
||||||
|
self.selected_subflow = None
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
"""Create the sub-flow details layout"""
|
||||||
|
yield Static("Sub-Flow Details", classes="panel-header")
|
||||||
|
yield Static(
|
||||||
|
"No sub-flow selected",
|
||||||
|
id="sub-details-content"
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_flow(self, flow: Optional['FlowStats'], subflow_type: Optional[str] = None) -> None:
|
||||||
|
"""Update panel with sub-flow details or summary"""
|
||||||
|
self.current_flow = flow
|
||||||
|
self.selected_subflow = subflow_type
|
||||||
|
content_widget = self.query_one("#sub-details-content", Static)
|
||||||
|
|
||||||
|
if not flow:
|
||||||
|
content_widget.update("No sub-flow selected")
|
||||||
|
return
|
||||||
|
|
||||||
|
if subflow_type and subflow_type in flow.frame_types:
|
||||||
|
# Show specific sub-flow details
|
||||||
|
details = self._create_subflow_details(flow, flow.frame_types[subflow_type])
|
||||||
|
else:
|
||||||
|
# Show summary of all sub-flows
|
||||||
|
details = self._create_subflow_summary(flow)
|
||||||
|
|
||||||
|
content_widget.update(details)
|
||||||
|
|
||||||
|
def _create_subflow_details(self, flow: 'FlowStats', subflow: 'FrameTypeStats') -> RenderableType:
|
||||||
|
"""Create specific sub-flow details"""
|
||||||
|
sections = []
|
||||||
|
|
||||||
|
# Sub-flow identification
|
||||||
|
id_table = Table(show_header=False, box=None, padding=0)
|
||||||
|
id_table.add_column(style="dim", width=12)
|
||||||
|
id_table.add_column()
|
||||||
|
|
||||||
|
id_table.add_row("Frame Type:", subflow.frame_type)
|
||||||
|
id_table.add_row("Packets:", f"{subflow.count:,}")
|
||||||
|
id_table.add_row("Volume:", self._format_bytes(subflow.total_bytes))
|
||||||
|
|
||||||
|
percentage = (subflow.count / flow.frame_count * 100) if flow.frame_count > 0 else 0
|
||||||
|
id_table.add_row("% of Flow:", f"{percentage:.1f}%")
|
||||||
|
|
||||||
|
sections.append(Text("Sub-Flow Information", style="bold yellow"))
|
||||||
|
sections.append(id_table)
|
||||||
|
|
||||||
|
# Sub-flow timing
|
||||||
|
timing_table = Table(show_header=False, box=None, padding=0)
|
||||||
|
timing_table.add_column(style="dim", width=12)
|
||||||
|
timing_table.add_column()
|
||||||
|
|
||||||
|
timing_table.add_row("Avg ΔT:", f"{subflow.avg_inter_arrival * 1000:.1f}ms" if subflow.avg_inter_arrival > 0 else "N/A")
|
||||||
|
timing_table.add_row("Std σ:", f"{subflow.std_inter_arrival * 1000:.1f}ms" if subflow.std_inter_arrival > 0 else "N/A")
|
||||||
|
timing_table.add_row("Outliers:", f"{len(subflow.outlier_frames)}")
|
||||||
|
|
||||||
|
sections.append(Text("Sub-Flow Timing", style="bold cyan"))
|
||||||
|
sections.append(timing_table)
|
||||||
|
|
||||||
|
# Outlier details if any
|
||||||
|
if subflow.outlier_frames and subflow.outlier_details:
|
||||||
|
outlier_table = Table(show_header=True, box=None)
|
||||||
|
outlier_table.add_column("Frame#", justify="right")
|
||||||
|
outlier_table.add_column("ΔT(ms)", justify="right")
|
||||||
|
|
||||||
|
for frame_num, delta_t in subflow.outlier_details[:5]: # Show first 5 outliers
|
||||||
|
outlier_table.add_row(
|
||||||
|
str(frame_num),
|
||||||
|
f"{delta_t * 1000:.1f}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(subflow.outlier_details) > 5:
|
||||||
|
outlier_table.add_row("...", f"+{len(subflow.outlier_details) - 5} more")
|
||||||
|
|
||||||
|
sections.append(Text("Outlier Details", style="bold red"))
|
||||||
|
sections.append(outlier_table)
|
||||||
|
|
||||||
|
return Group(*sections)
|
||||||
|
|
||||||
|
def _create_subflow_summary(self, flow: 'FlowStats') -> RenderableType:
|
||||||
|
"""Create summary of all sub-flows"""
|
||||||
|
if not flow.frame_types or len(flow.frame_types) <= 1:
|
||||||
|
return Text("No sub-flows available", style="dim")
|
||||||
|
|
||||||
|
sections = []
|
||||||
|
sections.append(Text("Sub-Flow Summary", style="bold yellow"))
|
||||||
|
|
||||||
|
# Frame type breakdown table
|
||||||
|
frame_table = Table(show_header=True, box=None)
|
||||||
|
frame_table.add_column("Frame Type", style="blue")
|
||||||
|
frame_table.add_column("Count", justify="right")
|
||||||
|
frame_table.add_column("%", justify="right", style="dim")
|
||||||
|
frame_table.add_column("ΔT(ms)", justify="right", style="cyan")
|
||||||
|
frame_table.add_column("σ(ms)", justify="right", style="cyan")
|
||||||
|
frame_table.add_column("Out", justify="right", style="red")
|
||||||
|
|
||||||
|
total = flow.frame_count
|
||||||
|
for frame_type, stats in sorted(
|
||||||
|
flow.frame_types.items(),
|
||||||
|
key=lambda x: x[1].count,
|
||||||
|
reverse=True
|
||||||
|
):
|
||||||
|
percentage = (stats.count / total * 100) if total > 0 else 0
|
||||||
|
delta_t = f"{stats.avg_inter_arrival * 1000:.1f}" if stats.avg_inter_arrival > 0 else "N/A"
|
||||||
|
sigma = f"{stats.std_inter_arrival * 1000:.1f}" if stats.std_inter_arrival > 0 else "N/A"
|
||||||
|
outliers = str(len(stats.outlier_frames))
|
||||||
|
|
||||||
|
frame_table.add_row(
|
||||||
|
frame_type[:15],
|
||||||
|
f"{stats.count:,}",
|
||||||
|
f"{percentage:.1f}%",
|
||||||
|
delta_t,
|
||||||
|
sigma,
|
||||||
|
outliers
|
||||||
|
)
|
||||||
|
|
||||||
|
sections.append(frame_table)
|
||||||
|
return Group(*sections)
|
||||||
|
|
||||||
|
def _format_bytes(self, bytes_count: int) -> str:
|
||||||
|
"""Format byte count with units"""
|
||||||
|
if bytes_count >= 1_000_000_000:
|
||||||
|
return f"{bytes_count / 1_000_000_000:.2f} GB"
|
||||||
|
elif bytes_count >= 1_000_000:
|
||||||
|
return f"{bytes_count / 1_000_000:.2f} MB"
|
||||||
|
elif bytes_count >= 1_000:
|
||||||
|
return f"{bytes_count / 1_000:.2f} KB"
|
||||||
|
else:
|
||||||
|
return f"{bytes_count} B"
|
||||||
|
|
||||||
|
|
||||||
|
class SplitFlowDetailsPanel(Vertical):
|
||||||
|
"""Combined panel with top/bottom split for flow and sub-flow details"""
|
||||||
|
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
SplitFlowDetailsPanel {
|
||||||
|
height: 1fr;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SplitFlowDetailsPanel > FlowMainDetailsPanel {
|
||||||
|
height: 3fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SplitFlowDetailsPanel > SubFlowDetailsPanel {
|
||||||
|
height: 2fr;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.current_flow = None
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
"""Create the split layout"""
|
||||||
|
yield FlowMainDetailsPanel(id="main-flow-details")
|
||||||
|
yield SubFlowDetailsPanel(id="sub-flow-details")
|
||||||
|
|
||||||
|
def update_flow(self, flow: Optional['FlowStats'], subflow_type: Optional[str] = None) -> None:
|
||||||
|
"""Update both panels with flow data"""
|
||||||
|
self.current_flow = flow
|
||||||
|
|
||||||
|
# Update main flow details
|
||||||
|
main_panel = self.query_one("#main-flow-details", FlowMainDetailsPanel)
|
||||||
|
main_panel.update_flow(flow)
|
||||||
|
|
||||||
|
# Update sub-flow details
|
||||||
|
sub_panel = self.query_one("#sub-flow-details", SubFlowDetailsPanel)
|
||||||
|
sub_panel.update_flow(flow, subflow_type)
|
||||||
237
debug.log
Normal file
237
debug.log
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
APP DEBUG: Application mounted, checking panels...
|
||||||
|
APP DEBUG: Both panels found successfully
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=CH10-Data
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=UDP
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=UDP
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=UDP
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=TMATS
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Signaling
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Sync
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Unknown (0x6)
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.202:5010 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.202:5010 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.202:5010 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.202:5010 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.202:5010 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.202:5010 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.202:5010 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.202:5010 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.202:5010 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.202:5010 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.202:5010 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.202:5010 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61112 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61112 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61112 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61112 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61113 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61113 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61113 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61113 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:319 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:319 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:319 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:319 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:0 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:0 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:0 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:0 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:5353 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:5353 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:5353 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:5353 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 169.254.0.1:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=169.254.0.1:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 169.254.0.1:5353 if flow else None
|
||||||
|
PANEL DEBUG: 169.254.0.1:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:5353 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:5353 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:5353 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:5353 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:0 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:0 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:0 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:0 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:319 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:319 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:319 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:319 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61113 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61113 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61113 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61113 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61112 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61112 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61112 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61112 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.202:5010 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.202:5010 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.202:5010 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.202:5010 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Unknown (0x6)
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Sync
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Signaling
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=TMATS
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=UDP
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=CH10-Data
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=CH10-Data
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=CH10-Data
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=CH10-Data
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=CH10-Data
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=CH10-Data
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=UDP
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:49154 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:49154 if event.flow else None, subflow_type=TMATS
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:49154 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:49154 - frame_types=10, decoder=Chapter10_Enhanced, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Signaling
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Sync
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:320 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:320 if event.flow else None, subflow_type=PTP-Unknown (0x6)
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:320 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:320 - frame_types=3, decoder=Standard, has_subflows=True
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.202:5010 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.202:5010 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.202:5010 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.202:5010 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61112 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61112 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61112 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61112 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61112 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61112 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61112 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61112 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61112 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61112 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61112 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61112 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:61113 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:61113 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:61113 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:61113 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.4.89:319 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.4.89:319 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.4.89:319 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.4.89:319 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 11.59.19.204:0 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=11.59.19.204:0 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 11.59.19.204:0 if flow else None
|
||||||
|
PANEL DEBUG: 11.59.19.204:0 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 192.168.43.111:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=192.168.43.111:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 192.168.43.111:5353 if flow else None
|
||||||
|
PANEL DEBUG: 192.168.43.111:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 169.254.0.1:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=169.254.0.1:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 169.254.0.1:5353 if flow else None
|
||||||
|
PANEL DEBUG: 169.254.0.1:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 169.254.0.1:5353 if selected_flow else None
|
||||||
|
TABLE DEBUG: Row highlighted, posting FlowSelected event for 169.254.0.1:5353 if selected_flow else None
|
||||||
|
APP DEBUG: Flow selected event - flow=169.254.0.1:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 169.254.0.1:5353 if flow else None
|
||||||
|
PANEL DEBUG: 169.254.0.1:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
|
APP DEBUG: Flow selected event - flow=169.254.0.1:5353 if event.flow else None, subflow_type=None
|
||||||
|
UPDATE_FLOW DEBUG: Called with flow 169.254.0.1:5353 if flow else None
|
||||||
|
PANEL DEBUG: 169.254.0.1:5353 - frame_types=1, decoder=Standard, has_subflows=False
|
||||||
61
debug_flow.py
Normal file
61
debug_flow.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Debug script to check flow data for the 192.168.7.168 source
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append('.')
|
||||||
|
|
||||||
|
from analyzer.analysis.core import EthernetAnalyzer
|
||||||
|
|
||||||
|
def debug_flow():
|
||||||
|
analyzer = EthernetAnalyzer()
|
||||||
|
|
||||||
|
# Load the sample file
|
||||||
|
pcap_file = "1 PTPGM.pcapng"
|
||||||
|
print(f"Loading {pcap_file}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
analyzer.analyze_pcap(pcap_file) # Load the file
|
||||||
|
|
||||||
|
# Find the flow with source 192.168.7.168
|
||||||
|
target_flow = None
|
||||||
|
for flow in analyzer.flows.values():
|
||||||
|
if flow.src_ip == "192.168.7.168":
|
||||||
|
target_flow = flow
|
||||||
|
break
|
||||||
|
|
||||||
|
if not target_flow:
|
||||||
|
print("No flow found with source 192.168.7.168")
|
||||||
|
print("Available flows:")
|
||||||
|
for flow in analyzer.flows.values():
|
||||||
|
print(f" {flow.src_ip}:{flow.src_port} -> {flow.dst_ip}:{flow.dst_port}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"\n=== Flow: {target_flow.src_ip}:{target_flow.src_port} -> {target_flow.dst_ip}:{target_flow.dst_port} ===")
|
||||||
|
print(f"Frame types: {len(target_flow.frame_types)} types")
|
||||||
|
|
||||||
|
if target_flow.frame_types:
|
||||||
|
for frame_type, stats in target_flow.frame_types.items():
|
||||||
|
print(f" - {frame_type}: {stats.count} packets")
|
||||||
|
|
||||||
|
print(f"Enhanced decoder: {target_flow.enhanced_analysis.decoder_type}")
|
||||||
|
|
||||||
|
# Check the subflow logic
|
||||||
|
has_subflows_condition1 = len(target_flow.frame_types) > 1
|
||||||
|
has_subflows_condition2 = target_flow.enhanced_analysis.decoder_type != "Standard"
|
||||||
|
has_subflows = has_subflows_condition1 or has_subflows_condition2
|
||||||
|
|
||||||
|
print(f"\nSubflow logic:")
|
||||||
|
print(f" Multiple frame types (>1): {has_subflows_condition1}")
|
||||||
|
print(f" Enhanced decoder (!='Standard'): {has_subflows_condition2}")
|
||||||
|
print(f" Should show subflows: {has_subflows}")
|
||||||
|
print(f" Should show timing in main panel: {not has_subflows}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
debug_flow()
|
||||||
Reference in New Issue
Block a user