Source code for duck.etc.blueprints.dashboard.ui.components.latency_panel
"""
LatencyPanel component — displays latency percentile tiles and an
inline SVG sparkline chart of recent latency history.
"""
from duck.html.components import InnerComponent
from duck.html.components.container import Container
from ..components.theme import Theme
[docs]
class LatencyPanel(InnerComponent):
"""
Renders a panel with p50/p90/p95/p99 latency tiles and a sparkline.
Props:
data (dict): Output of services.get_latency_stats().
"""
[docs]
def get_element(self) -> str:
"""
Returns:
The HTML element tag for this component.
"""
return "div"
[docs]
def on_create(self) -> None:
"""
Builds the panel header, percentile grid, and sparkline.
"""
super().on_create()
data = self.kwargs.get("data", {})
self.props["class"] = "db-panel"
# Build the full panel layout
self.add_children([
self.build_header(),
self.build_body(data),
])
[docs]
def build_body(self, data: dict) -> Container:
"""
Returns the panel body containing the percentile grid and sparkline.
Args:
data: Latency stats dict from the service layer.
Returns:
A Container wrapping both the grid and sparkline.
"""
percentile_grid = self.build_percentile_grid(data)
sparkline = self.build_sparkline(data.get("history", []))
return Container(
klass="db-panel-body db-sparkline-wrap",
children=[percentile_grid, sparkline],
)
[docs]
def build_percentile_grid(self, data: dict) -> Container:
"""
Returns a grid of four latency percentile tiles.
Args:
data: Latency stats dict containing p50, p90, p95, p99 keys.
Returns:
A Container styled as the latency grid.
"""
tiles_html = "".join([
self.render_tile(label, data.get(key, 0))
for label, key in [("P50", "p50"), ("P90", "p90"), ("P95", "p95"), ("P99", "p99")]
])
return Container(klass="db-latency-grid", inner_html=tiles_html)
[docs]
def render_tile(self, label: str, value: int) -> str:
"""
Returns the raw HTML string for one latency tile.
Args:
label: Percentile label, e.g. "P50".
value: Latency value in milliseconds.
Returns:
HTML string for the tile div.
"""
return (
f'<div class="db-latency-tile">'
f'<span class="db-latency-label">{label}</span>'
f'<span class="db-latency-value">{value}'
f'<span class="db-latency-unit"> ms</span></span>'
f'</div>'
)
[docs]
def build_sparkline(self, history: list) -> Container:
"""
Returns an SVG sparkline chart from the latency history list.
Args:
history: List of latency integers representing recent measurements.
Returns:
A Container holding the inline SVG sparkline.
"""
if not history:
return Container(klass="db-sparkline")
width = 400
height = 56
min_val = min(history)
max_val = max(history) or 1
span = max_val - min_val or 1
# Compute (x, y) for each point
points = []
for i, val in enumerate(history):
x = (i / (len(history) - 1)) * width if i > 0 else 0
y = height - ((val - min_val) / span) * (height - 8) - 4
points.append((x, y))
polyline = " ".join(f"{x:.1f},{y:.1f}" for x, y in points)
# Build gradient fill polygon by closing the path
fill_pts = polyline + f" {width:.1f},{height} 0,{height}"
svg = (
f'<svg class="db-sparkline" viewBox="0 0 {width} {height}" '
f'preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">'
f'<defs>'
f'<linearGradient id="spark-grad" x1="0" y1="0" x2="0" y2="1">'
f'<stop offset="0%" stop-color="{Theme.orange}" stop-opacity="0.25"/>'
f'<stop offset="100%" stop-color="{Theme.orange}" stop-opacity="0"/>'
f'</linearGradient>'
f'</defs>'
f'<polygon points="{fill_pts}" fill="url(#spark-grad)"/>'
f'<polyline points="{polyline}" fill="none" '
f'stroke="{Theme.orange}" stroke-width="1.5" stroke-linejoin="round" '
f'stroke-linecap="round"/>'
f'</svg>'
)
return Container(inner_html=svg)