Fixed wrong full refresh
This commit is contained in:
@@ -37,7 +37,7 @@ def _mk_span_rows(span, depth: int, total_ms: float) -> list:
|
|||||||
"""
|
"""
|
||||||
rows = []
|
rows = []
|
||||||
indent = [Div(cls="mf-profiler-span-indent") for _ in range(depth)]
|
indent = [Div(cls="mf-profiler-span-indent") for _ in range(depth)]
|
||||||
|
|
||||||
if isinstance(span, CumulativeSpan):
|
if isinstance(span, CumulativeSpan):
|
||||||
pct = (span.total_ms / total_ms * 100) if total_ms > 0 else 0
|
pct = (span.total_ms / total_ms * 100) if total_ms > 0 else 0
|
||||||
duration_cls = _span_duration_cls(span.total_ms)
|
duration_cls = _span_duration_cls(span.total_ms)
|
||||||
@@ -57,7 +57,7 @@ def _mk_span_rows(span, depth: int, total_ms: float) -> list:
|
|||||||
cls="mf-profiler-span-row",
|
cls="mf-profiler-span-row",
|
||||||
)
|
)
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pct = (span.duration_ms / total_ms * 100) if total_ms > 0 else 0
|
pct = (span.duration_ms / total_ms * 100) if total_ms > 0 else 0
|
||||||
duration_cls = _span_duration_cls(span.duration_ms)
|
duration_cls = _span_duration_cls(span.duration_ms)
|
||||||
@@ -75,7 +75,7 @@ def _mk_span_rows(span, depth: int, total_ms: float) -> list:
|
|||||||
rows.append(row)
|
rows.append(row)
|
||||||
for child in span.children:
|
for child in span.children:
|
||||||
rows.extend(_mk_span_rows(child, depth + 1, total_ms))
|
rows.extend(_mk_span_rows(child, depth + 1, total_ms))
|
||||||
|
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ class Commands(BaseCommands):
|
|||||||
self._owner,
|
self._owner,
|
||||||
self._owner.handle_toggle_detail_view,
|
self._owner.handle_toggle_detail_view,
|
||||||
).htmx(target=f"#{self._id}")
|
).htmx(target=f"#{self._id}")
|
||||||
|
|
||||||
def toggle_enable(self):
|
def toggle_enable(self):
|
||||||
return Command(
|
return Command(
|
||||||
"ProfilerToggleEnable",
|
"ProfilerToggleEnable",
|
||||||
@@ -145,7 +145,7 @@ class Commands(BaseCommands):
|
|||||||
self._owner,
|
self._owner,
|
||||||
self._owner.handle_select_trace,
|
self._owner.handle_select_trace,
|
||||||
kwargs={"trace_id": trace_id},
|
kwargs={"trace_id": trace_id},
|
||||||
).htmx(target=f"#{self._id}")
|
).htmx(target=f"#tr_{trace_id}")
|
||||||
|
|
||||||
|
|
||||||
class Profiler(SingleInstance):
|
class Profiler(SingleInstance):
|
||||||
@@ -186,15 +186,24 @@ class Profiler(SingleInstance):
|
|||||||
|
|
||||||
def handle_select_trace(self, trace_id: str):
|
def handle_select_trace(self, trace_id: str):
|
||||||
"""Select a trace row and re-render to show it highlighted."""
|
"""Select a trace row and re-render to show it highlighted."""
|
||||||
|
if self._selected_id is not None:
|
||||||
|
old_trace = next(trace for trace in profiler.traces if trace.trace_id == self._selected_id)
|
||||||
|
else:
|
||||||
|
old_trace = None
|
||||||
|
|
||||||
self._selected_id = trace_id
|
self._selected_id = trace_id
|
||||||
return self
|
trace = next(trace for trace in profiler.traces if trace.trace_id == trace_id)
|
||||||
|
|
||||||
|
return (self._mk_trace_item(trace),
|
||||||
|
self._mk_trace_item(old_trace),
|
||||||
|
self._panel.set_right(self._mk_right_panel(trace)))
|
||||||
|
|
||||||
def handle_toggle_detail_view(self):
|
def handle_toggle_detail_view(self):
|
||||||
"""Toggle detail panel between tree and pie view."""
|
"""Toggle detail panel between tree and pie view."""
|
||||||
self._detail_view = "pie" if self._detail_view == "tree" else "tree"
|
self._detail_view = "pie" if self._detail_view == "tree" else "tree"
|
||||||
logger.debug(f"Profiler detail view set to {self._detail_view}")
|
logger.debug(f"Profiler detail view set to {self._detail_view}")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def handle_refresh(self):
|
def handle_refresh(self):
|
||||||
"""Refresh the trace list without changing selection."""
|
"""Refresh the trace list without changing selection."""
|
||||||
return self
|
return self
|
||||||
@@ -245,32 +254,36 @@ class Profiler(SingleInstance):
|
|||||||
id=f"tb_{self._id}",
|
id=f"tb_{self._id}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _mk_trace_item(self, trace: ProfilingTrace):
|
||||||
|
if trace is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
ts = trace.timestamp.strftime("%H:%M:%S.") + f"{trace.timestamp.microsecond // 1000:03d}"
|
||||||
|
duration_cls = self._duration_cls(trace.total_duration_ms)
|
||||||
|
row_cls = "mf-profiler-row mf-profiler-row-selected" if trace.trace_id == self._selected_id else "mf-profiler-row"
|
||||||
|
|
||||||
|
return mk.mk(
|
||||||
|
Div(
|
||||||
|
Div(
|
||||||
|
Span(trace.command_name, cls="mf-profiler-cmd"),
|
||||||
|
Span(trace.command_description, cls="mf-profiler-cmd-description"),
|
||||||
|
cls="mf-profiler-cmd-cell",
|
||||||
|
),
|
||||||
|
Span(f"{trace.total_duration_ms:.1f} ms", cls=f"mf-profiler-duration {duration_cls}"),
|
||||||
|
Span(ts, cls="mf-profiler-ts"),
|
||||||
|
cls=row_cls,
|
||||||
|
id=f"tr_{trace.trace_id}",
|
||||||
|
),
|
||||||
|
command=self.commands.select_trace(trace.trace_id),
|
||||||
|
)
|
||||||
|
|
||||||
def _mk_trace_list(self):
|
def _mk_trace_list(self):
|
||||||
"""Build the trace list with one clickable row per recorded trace."""
|
"""Build the trace list with one clickable row per recorded trace."""
|
||||||
traces = profiler.traces
|
traces = profiler.traces
|
||||||
if not traces:
|
if not traces:
|
||||||
return Div("No traces recorded.", cls="mf-profiler-empty")
|
return Div("No traces recorded.", cls="mf-profiler-empty")
|
||||||
|
|
||||||
rows = []
|
rows = [self._mk_trace_item(trace) for trace in reversed(traces)]
|
||||||
for trace in reversed(traces):
|
|
||||||
ts = trace.timestamp.strftime("%H:%M:%S.") + f"{trace.timestamp.microsecond // 1000:03d}"
|
|
||||||
duration_cls = self._duration_cls(trace.total_duration_ms)
|
|
||||||
row_cls = "mf-profiler-row mf-profiler-row-selected" if trace.trace_id == self._selected_id else "mf-profiler-row"
|
|
||||||
|
|
||||||
row = mk.mk(
|
|
||||||
Div(
|
|
||||||
Div(
|
|
||||||
Span(trace.command_name, cls="mf-profiler-cmd"),
|
|
||||||
Span(trace.command_description, cls="mf-profiler-cmd-description"),
|
|
||||||
cls="mf-profiler-cmd-cell",
|
|
||||||
),
|
|
||||||
Span(f"{trace.total_duration_ms:.1f} ms", cls=f"mf-profiler-duration {duration_cls}"),
|
|
||||||
Span(ts, cls="mf-profiler-ts"),
|
|
||||||
cls=row_cls,
|
|
||||||
),
|
|
||||||
command=self.commands.select_trace(trace.trace_id),
|
|
||||||
)
|
|
||||||
rows.append(row)
|
|
||||||
|
|
||||||
return Div(
|
return Div(
|
||||||
Div(
|
Div(
|
||||||
@@ -286,7 +299,7 @@ class Profiler(SingleInstance):
|
|||||||
def _mk_detail_placeholder(self):
|
def _mk_detail_placeholder(self):
|
||||||
"""Placeholder shown in the right panel before a trace is selected."""
|
"""Placeholder shown in the right panel before a trace is selected."""
|
||||||
return Div("Select a trace to view details.", cls="mf-profiler-empty")
|
return Div("Select a trace to view details.", cls="mf-profiler-empty")
|
||||||
|
|
||||||
def _mk_detail_header(self, trace: "ProfilingTrace"):
|
def _mk_detail_header(self, trace: "ProfilingTrace"):
|
||||||
"""Build the detail panel header with title and tree/pie toggle.
|
"""Build the detail panel header with title and tree/pie toggle.
|
||||||
|
|
||||||
@@ -305,12 +318,14 @@ class Profiler(SingleInstance):
|
|||||||
tree_cls = "mf-profiler-view-btn mf-profiler-view-btn-active" if self._detail_view == "tree" else "mf-profiler-view-btn"
|
tree_cls = "mf-profiler-view-btn mf-profiler-view-btn-active" if self._detail_view == "tree" else "mf-profiler-view-btn"
|
||||||
pie_cls = "mf-profiler-view-btn mf-profiler-view-btn-active" if self._detail_view == "pie" else "mf-profiler-view-btn"
|
pie_cls = "mf-profiler-view-btn mf-profiler-view-btn-active" if self._detail_view == "pie" else "mf-profiler-view-btn"
|
||||||
toggle = Div(
|
toggle = Div(
|
||||||
mk.icon(text_bullet_list_tree20_filled, command=self.commands.toggle_detail_view(), tooltip="Span tree", cls=tree_cls),
|
mk.icon(text_bullet_list_tree20_filled, command=self.commands.toggle_detail_view(), tooltip="Span tree",
|
||||||
mk.icon(data_pie24_regular, command=self.commands.toggle_detail_view(), tooltip="Pie chart (coming soon)", cls=pie_cls),
|
cls=tree_cls),
|
||||||
|
mk.icon(data_pie24_regular, command=self.commands.toggle_detail_view(), tooltip="Pie chart (coming soon)",
|
||||||
|
cls=pie_cls),
|
||||||
cls="mf-profiler-view-toggle",
|
cls="mf-profiler-view-toggle",
|
||||||
)
|
)
|
||||||
return Div(title, toggle, cls="mf-profiler-detail-header")
|
return Div(title, toggle, cls="mf-profiler-detail-header")
|
||||||
|
|
||||||
def _mk_detail_body(self, trace: "ProfilingTrace"):
|
def _mk_detail_body(self, trace: "ProfilingTrace"):
|
||||||
"""Build the scrollable detail body: metadata, kwargs and span breakdown.
|
"""Build the scrollable detail body: metadata, kwargs and span breakdown.
|
||||||
|
|
||||||
@@ -321,28 +336,28 @@ class Profiler(SingleInstance):
|
|||||||
A FT element for the detail body.
|
A FT element for the detail body.
|
||||||
"""
|
"""
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
meta_props = Properties(
|
meta_props = Properties(
|
||||||
self,
|
self,
|
||||||
conf=PropertiesConf(
|
conf=PropertiesConf(
|
||||||
obj=trace,
|
obj=trace,
|
||||||
groups={"Metadata": {
|
groups={"Metadata": {
|
||||||
"command": "command_name",
|
"command": "command_name",
|
||||||
"description": "command_description",
|
"description": "command_description",
|
||||||
"duration_ms": "total_duration_ms",
|
"duration_ms": "total_duration_ms",
|
||||||
"timestamp": "timestamp",
|
"timestamp": "timestamp",
|
||||||
}},
|
}},
|
||||||
),
|
),
|
||||||
_id="-detail-meta",
|
_id="-detail-meta",
|
||||||
)
|
)
|
||||||
|
|
||||||
kwargs_obj = SimpleNamespace(**trace.kwargs) if trace.kwargs else SimpleNamespace()
|
kwargs_obj = SimpleNamespace(**trace.kwargs) if trace.kwargs else SimpleNamespace()
|
||||||
kwargs_props = Properties(
|
kwargs_props = Properties(
|
||||||
self,
|
self,
|
||||||
conf=PropertiesConf(obj=kwargs_obj, groups={"kwargs": {"*": ""}}),
|
conf=PropertiesConf(obj=kwargs_obj, groups={"kwargs": {"*": ""}}),
|
||||||
_id="-detail-kwargs",
|
_id="-detail-kwargs",
|
||||||
)
|
)
|
||||||
|
|
||||||
span_props = None
|
span_props = None
|
||||||
if trace.root_span is not None:
|
if trace.root_span is not None:
|
||||||
span_props = Properties(
|
span_props = Properties(
|
||||||
@@ -354,13 +369,13 @@ class Profiler(SingleInstance):
|
|||||||
),
|
),
|
||||||
_id="-detail-spans",
|
_id="-detail-spans",
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._detail_view == "pie":
|
if self._detail_view == "pie":
|
||||||
pie_placeholder = Div("Pie chart — coming soon.", cls="mf-profiler-empty")
|
pie_placeholder = Div("Pie chart — coming soon.", cls="mf-profiler-empty")
|
||||||
return Div(meta_props, kwargs_props, pie_placeholder, cls="mf-profiler-detail-body")
|
return Div(meta_props, kwargs_props, pie_placeholder, cls="mf-profiler-detail-body")
|
||||||
|
|
||||||
return Div(meta_props, kwargs_props, span_props, cls="mf-profiler-detail-body")
|
return Div(meta_props, kwargs_props, span_props, cls="mf-profiler-detail-body")
|
||||||
|
|
||||||
def _mk_detail_panel(self, trace: "ProfilingTrace"):
|
def _mk_detail_panel(self, trace: "ProfilingTrace"):
|
||||||
"""Build the full detail panel for a selected trace.
|
"""Build the full detail panel for a selected trace.
|
||||||
|
|
||||||
@@ -376,6 +391,14 @@ class Profiler(SingleInstance):
|
|||||||
cls="mf-profiler-detail",
|
cls="mf-profiler-detail",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _mk_right_panel(self, trace: "ProfilingTrace"):
|
||||||
|
"""Build the right panel with a trace detail view."""
|
||||||
|
return (
|
||||||
|
self._mk_detail_panel(trace)
|
||||||
|
if trace is not None
|
||||||
|
else self._mk_detail_placeholder()
|
||||||
|
)
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Render
|
# Render
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
@@ -386,15 +409,9 @@ class Profiler(SingleInstance):
|
|||||||
selected_trace = next(
|
selected_trace = next(
|
||||||
(t for t in profiler.traces if t.trace_id == self._selected_id), None
|
(t for t in profiler.traces if t.trace_id == self._selected_id), None
|
||||||
)
|
)
|
||||||
|
|
||||||
right_panel = (
|
|
||||||
self._mk_detail_panel(selected_trace)
|
|
||||||
if selected_trace is not None
|
|
||||||
else self._mk_detail_placeholder()
|
|
||||||
)
|
|
||||||
|
|
||||||
self._panel.set_main(self._mk_trace_list())
|
self._panel.set_main(self._mk_trace_list())
|
||||||
self._panel.set_right(right_panel)
|
self._panel.set_right(self._mk_right_panel(selected_trace))
|
||||||
return Div(
|
return Div(
|
||||||
self._mk_toolbar(),
|
self._mk_toolbar(),
|
||||||
self._panel,
|
self._panel,
|
||||||
|
|||||||
Reference in New Issue
Block a user