fix: evenly space chart runs at fixed width and trim initial data to match
This commit is contained in:
parent
766d1094ad
commit
f2fcf1a0b9
|
|
@ -179,12 +179,26 @@
|
||||||
'us-west': '🇺🇸 US West', 'ap-southeast': '🇸🇬 AP Southeast'
|
'us-west': '🇺🇸 US West', 'ap-southeast': '🇸🇬 AP Southeast'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MAX_RUNS = 50;
|
||||||
let chartPings = <%~ JSON.stringify(chartPings.map(p => ({
|
let chartPings = <%~ JSON.stringify(chartPings.map(p => ({
|
||||||
latency_ms: p.latency_ms, region: p.region || '__none__',
|
latency_ms: p.latency_ms, region: p.region || '__none__',
|
||||||
checked_at: p.checked_at, up: p.up, run_id: p.run_id || null,
|
checked_at: p.checked_at, up: p.up, run_id: p.run_id || null,
|
||||||
status_code: p.status_code
|
status_code: p.status_code
|
||||||
}))) %>;
|
}))) %>;
|
||||||
|
|
||||||
|
// Trim initial data to MAX_RUNS
|
||||||
|
(function() {
|
||||||
|
const seen = []; const s = new Set();
|
||||||
|
for (const p of chartPings) {
|
||||||
|
const rid = p.run_id || p.checked_at;
|
||||||
|
if (!s.has(rid)) { s.add(rid); seen.push(rid); }
|
||||||
|
}
|
||||||
|
if (seen.length > MAX_RUNS) {
|
||||||
|
const stale = new Set(seen.slice(0, seen.length - MAX_RUNS));
|
||||||
|
chartPings = chartPings.filter(p => !stale.has(p.run_id || p.checked_at));
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
function renderChart() {
|
function renderChart() {
|
||||||
const canvas = document.getElementById('chart-canvas');
|
const canvas = document.getElementById('chart-canvas');
|
||||||
const container = canvas.parentElement;
|
const container = canvas.parentElement;
|
||||||
|
|
@ -208,18 +222,23 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute a shared x-position per run_id (avg checked_at of all pings in the run)
|
// Build ordered list of unique runs, sorted by avg checked_at
|
||||||
// so all regions in the same run align vertically on the chart
|
|
||||||
const runTimes = {};
|
const runTimes = {};
|
||||||
for (const p of data) {
|
for (const p of data) {
|
||||||
const rid = p.run_id || p.checked_at; // fallback for pings without run_id
|
const rid = p.run_id || p.checked_at;
|
||||||
if (!runTimes[rid]) runTimes[rid] = [];
|
if (!runTimes[rid]) runTimes[rid] = [];
|
||||||
runTimes[rid].push(new Date(p.checked_at).getTime());
|
runTimes[rid].push(new Date(p.checked_at).getTime());
|
||||||
}
|
}
|
||||||
const runAvgTime = {};
|
const runs = Object.keys(runTimes).sort((a, b) => {
|
||||||
for (const [rid, times] of Object.entries(runTimes)) {
|
const avgA = runTimes[a].reduce((x, y) => x + y, 0) / runTimes[a].length;
|
||||||
runAvgTime[rid] = times.reduce((a, b) => a + b, 0) / times.length;
|
const avgB = runTimes[b].reduce((x, y) => x + y, 0) / runTimes[b].length;
|
||||||
}
|
return avgA - avgB;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Evenly space runs across the chart width (fixed spacing like SSR)
|
||||||
|
const runIndex = {};
|
||||||
|
runs.forEach((rid, i) => { runIndex[rid] = i; });
|
||||||
|
const maxIdx = Math.max(runs.length - 1, 1);
|
||||||
|
|
||||||
// Group by region
|
// Group by region
|
||||||
const byRegion = {};
|
const byRegion = {};
|
||||||
|
|
@ -232,13 +251,12 @@
|
||||||
const allLat = data.map(p => p.latency_ms);
|
const allLat = data.map(p => p.latency_ms);
|
||||||
const yMin = Math.min(...allLat), yMax = Math.max(...allLat);
|
const yMin = Math.min(...allLat), yMax = Math.max(...allLat);
|
||||||
const yRange = yMax - yMin || 1;
|
const yRange = yMax - yMin || 1;
|
||||||
const avgTimes = Object.values(runAvgTime);
|
|
||||||
const tMin = Math.min(...avgTimes), tMax = Math.max(...avgTimes);
|
|
||||||
const tRange = tMax - tMin || 1;
|
|
||||||
|
|
||||||
function toX(t) { return pad.left + ((t - tMin) / tRange) * cW; }
|
|
||||||
function toY(v) { return pad.top + cH - ((v - yMin) / yRange) * cH; }
|
function toY(v) { return pad.top + cH - ((v - yMin) / yRange) * cH; }
|
||||||
function pingX(p) { return toX(runAvgTime[p.run_id || p.checked_at]); }
|
function pingX(p) {
|
||||||
|
const idx = runIndex[p.run_id || p.checked_at] || 0;
|
||||||
|
return pad.left + (idx / maxIdx) * cW;
|
||||||
|
}
|
||||||
|
|
||||||
// Grid lines
|
// Grid lines
|
||||||
ctx.strokeStyle = 'rgba(75,85,99,0.3)'; ctx.lineWidth = 0.5;
|
ctx.strokeStyle = 'rgba(75,85,99,0.3)'; ctx.lineWidth = 0.5;
|
||||||
|
|
@ -310,9 +328,6 @@
|
||||||
|
|
||||||
// Store for hover
|
// Store for hover
|
||||||
canvas._regionPoints = regionPoints;
|
canvas._regionPoints = regionPoints;
|
||||||
canvas._toX = toX; canvas._toY = toY;
|
|
||||||
canvas._tMin = tMin; canvas._tRange = tRange;
|
|
||||||
canvas._W = W; canvas._H = H; canvas._pad = pad; canvas._cW = cW;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group pings by run_id for tooltip
|
// Group pings by run_id for tooltip
|
||||||
|
|
@ -472,7 +487,6 @@
|
||||||
status_code: ping.status_code
|
status_code: ping.status_code
|
||||||
});
|
});
|
||||||
// Count distinct runs and remove oldest runs as a group
|
// Count distinct runs and remove oldest runs as a group
|
||||||
const MAX_RUNS = 50;
|
|
||||||
const seen = []; const runSet = new Set();
|
const seen = []; const runSet = new Set();
|
||||||
for (const p of chartPings) {
|
for (const p of chartPings) {
|
||||||
const rid = p.run_id || p.checked_at;
|
const rid = p.run_id || p.checked_at;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue