feat: animated live gauge circles (PageSpeed-style)
Backend:
- Re-add --out json=- but properly route: JSON lines → metric
aggregation, non-JSON lines → text log (summary text lands in log)
- Aggregate http_req_duration / http_reqs / http_req_failed / checks
per test into live state (capped 50k samples)
- Broadcast { metrics: {...} } SSE events every second with
score, checksRate, httpOkRate, p90/p95/p99, req/s etc.
- computeScore() composite 0-100 based on p95 + error rate
Frontend:
- 3 animated SVG ring gauges: Score (/100), Checks OK (%), HTTP OK (%)
- Smooth CSS transition on stroke-dashoffset (0.7s cubic-bezier)
- Pulse animation while test is live, stops on completion
- Color: green ≥90/98/99, yellow mid-range, red below thresholds
- Stats strip: Requests, Req/s, Avg, p(90), p(95), p(99)
- p(95) cell color-coded green/yellow/red vs latency
- Threshold pass/fail banner at bottom of gauges panel
- Raw output collapsed in <details> by default
- History items show mini score ring gauge (44px) inline
- History detail expands 3 medium gauges + stat grid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -108,14 +108,83 @@
|
||||
|
||||
<div id="result-panel" style="display:none">
|
||||
<div class="result-header">
|
||||
<h2>Test Running</h2>
|
||||
<h2>Test Results</h2>
|
||||
<span id="result-status" class="badge running">running</span>
|
||||
</div>
|
||||
<pre id="output-log"></pre>
|
||||
<div id="summary-panel" style="display:none">
|
||||
<h3>Summary</h3>
|
||||
<div id="summary-cards" class="summary-grid"></div>
|
||||
|
||||
<!-- Gauge circles -->
|
||||
<div id="gauges-panel">
|
||||
<div class="gauges-main">
|
||||
|
||||
<div class="gauge-wrap" id="gauge-score">
|
||||
<svg viewBox="0 0 120 120" class="gauge-svg" aria-label="Performance score">
|
||||
<circle class="gauge-track" cx="60" cy="60" r="50"/>
|
||||
<circle class="gauge-ring" cx="60" cy="60" r="50"/>
|
||||
</svg>
|
||||
<div class="gauge-inner">
|
||||
<span class="gauge-value" aria-live="polite">--</span>
|
||||
<span class="gauge-sub">/100</span>
|
||||
<span class="gauge-title">Score</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gauge-wrap" id="gauge-checks">
|
||||
<svg viewBox="0 0 120 120" class="gauge-svg" aria-label="Checks passed">
|
||||
<circle class="gauge-track" cx="60" cy="60" r="50"/>
|
||||
<circle class="gauge-ring" cx="60" cy="60" r="50"/>
|
||||
</svg>
|
||||
<div class="gauge-inner">
|
||||
<span class="gauge-value" aria-live="polite">--</span>
|
||||
<span class="gauge-sub">%</span>
|
||||
<span class="gauge-title">Checks OK</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gauge-wrap" id="gauge-http">
|
||||
<svg viewBox="0 0 120 120" class="gauge-svg" aria-label="HTTP success rate">
|
||||
<circle class="gauge-track" cx="60" cy="60" r="50"/>
|
||||
<circle class="gauge-ring" cx="60" cy="60" r="50"/>
|
||||
</svg>
|
||||
<div class="gauge-inner">
|
||||
<span class="gauge-value" aria-live="polite">--</span>
|
||||
<span class="gauge-sub">%</span>
|
||||
<span class="gauge-title">HTTP OK</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Live stat strip -->
|
||||
<div class="stats-strip" id="stats-strip">
|
||||
<div class="stat-cell" id="sc-reqs">
|
||||
<span class="sc-val">--</span><span class="sc-lbl">Requests</span>
|
||||
</div>
|
||||
<div class="stat-cell" id="sc-rps">
|
||||
<span class="sc-val">--</span><span class="sc-lbl">Req / s</span>
|
||||
</div>
|
||||
<div class="stat-cell" id="sc-avg">
|
||||
<span class="sc-val">--</span><span class="sc-lbl">Avg</span>
|
||||
</div>
|
||||
<div class="stat-cell" id="sc-p90">
|
||||
<span class="sc-val">--</span><span class="sc-lbl">p(90)</span>
|
||||
</div>
|
||||
<div class="stat-cell" id="sc-p95">
|
||||
<span class="sc-val">--</span><span class="sc-lbl">p(95)</span>
|
||||
</div>
|
||||
<div class="stat-cell" id="sc-p99">
|
||||
<span class="sc-val">--</span><span class="sc-lbl">p(99)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Threshold results -->
|
||||
<div id="threshold-banner" style="display:none"></div>
|
||||
</div>
|
||||
|
||||
<!-- Raw log (collapsible) -->
|
||||
<details id="log-details">
|
||||
<summary>Raw Output</summary>
|
||||
<pre id="output-log"></pre>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user