feat(admin): chart redraws every 1 s — live bucket at right edge
Deploy to Production / deploy (push) Successful in 3m12s
Deploy to Production / deploy (push) Successful in 3m12s
Separate chart refresh from bucket flush: - 5 s flush commits completed bucket into buf, resets accumulator - Every poll (1 s): redraw path as buf[1..] + current live bucket so the rightmost bar visually builds up in real time - Label and chart now both update at 1 s cadence Co-Authored-By: Mira Rehfeld <noreply@anthropic.com>
This commit is contained in:
@@ -206,20 +206,28 @@
|
|||||||
if (elLive) elLive.textContent = fmt(rpm) + ' req/min (' + pct + '%)';
|
if (elLive) elLive.textContent = fmt(rpm) + ' req/min (' + pct + '%)';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chart bucket: flush accumulated delta every 5 s regardless of poll rate
|
// Compute the current in-progress bucket value (capped at rateLimit)
|
||||||
// Cap at rateLimit so the area never visually exceeds 100% (live label shows true value)
|
function liveRpm() {
|
||||||
|
var windowMs = Math.max(Date.now() - lastFlushTime, 1);
|
||||||
|
return Math.min(Math.round(accDelta * (60000 / windowMs)), rateLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redraw: historical buf + current live bucket at the right edge ("now")
|
||||||
|
function redraw() {
|
||||||
|
var view = buf.slice(1).concat([liveRpm()]);
|
||||||
|
path.attr('d', areaFn(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every 5 s: commit the current bucket into buf, reset accumulator
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
var now = Date.now();
|
var rpm = liveRpm();
|
||||||
var elapsed = now - lastFlushTime;
|
|
||||||
var rpm = Math.min(Math.round(accDelta * (60000 / (elapsed || CHART_TICK))), rateLimit);
|
|
||||||
lastWindowRpm = rpm;
|
lastWindowRpm = rpm;
|
||||||
lastFlushTime = now;
|
lastFlushTime = Date.now();
|
||||||
buf.push(rpm); buf.shift();
|
buf.push(rpm); buf.shift();
|
||||||
path.attr('d', areaFn(buf));
|
|
||||||
accDelta = 0;
|
accDelta = 0;
|
||||||
}, CHART_TICK);
|
}, CHART_TICK);
|
||||||
|
|
||||||
async function poll(elapsed) {
|
async function poll() {
|
||||||
try {
|
try {
|
||||||
var r = await fetch('/sandbox/' + sid + '/poll');
|
var r = await fetch('/sandbox/' + sid + '/poll');
|
||||||
if (!r.ok) return;
|
if (!r.ok) return;
|
||||||
@@ -229,12 +237,10 @@
|
|||||||
var delta = Math.max(0, total - lastTotal);
|
var delta = Math.max(0, total - lastTotal);
|
||||||
accDelta += delta;
|
accDelta += delta;
|
||||||
if (delta > 0) lastActivity = Date.now();
|
if (delta > 0) lastActivity = Date.now();
|
||||||
// Use accumulated rate over current window — smooth, not instantaneous per-poll delta
|
|
||||||
var windowMs = Date.now() - lastFlushTime;
|
var windowMs = Date.now() - lastFlushTime;
|
||||||
var liveRpm = windowMs > 200
|
var rpm = windowMs > 200 ? liveRpm() : lastWindowRpm;
|
||||||
? Math.round(accDelta * (60000 / windowMs))
|
updateLabel(rpm);
|
||||||
: lastWindowRpm; // too early in window — carry previous
|
redraw(); // update chart on every poll, not just every 5 s
|
||||||
updateLabel(liveRpm);
|
|
||||||
}
|
}
|
||||||
lastTotal = total;
|
lastTotal = total;
|
||||||
currentInterval = (Date.now() - lastActivity > IDLE_AFTER_MS) ? IDLE_INTERVAL : FAST_INTERVAL;
|
currentInterval = (Date.now() - lastActivity > IDLE_AFTER_MS) ? IDLE_INTERVAL : FAST_INTERVAL;
|
||||||
@@ -243,9 +249,9 @@
|
|||||||
|
|
||||||
function scheduleNext() {
|
function scheduleNext() {
|
||||||
var interval = currentInterval;
|
var interval = currentInterval;
|
||||||
setTimeout(function () { poll(interval).then(scheduleNext); }, interval);
|
setTimeout(function () { poll().then(scheduleNext); }, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
poll(0); // set lastTotal immediately, no rpm yet
|
poll(); // set lastTotal immediately
|
||||||
scheduleNext();
|
scheduleNext();
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -106,6 +106,6 @@ nav {
|
|||||||
<script>var __D = {statsJson.raw};</script>
|
<script>var __D = {statsJson.raw};</script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js"></script>
|
||||||
<script src="/admin.js?v=8"></script>
|
<script src="/admin.js?v=9"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -151,6 +151,6 @@ button.promote:hover { background: #2ea043; }
|
|||||||
<script>var __D = {dataJson.raw};</script>
|
<script>var __D = {dataJson.raw};</script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js"></script>
|
||||||
<script src="/admin.js?v=8"></script>
|
<script src="/admin.js?v=9"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user