feat: per-region chart lines and lowest-avg sparkline

This commit is contained in:
M1
2026-03-18 16:25:47 +04:00
parent e1bb39431d
commit 07648672ad
3 changed files with 107 additions and 29 deletions
+35 -2
View File
@@ -1,4 +1,4 @@
export function sparkline(values: number[], width = 120, height = 32): string {
export function sparkline(values: number[], width = 120, height = 32, color = '#60a5fa'): string {
if (!values.length) return '';
const max = Math.max(...values, 1);
const min = Math.min(...values, 0);
@@ -9,5 +9,38 @@ export function sparkline(values: number[], width = 120, height = 32): string {
const y = height - ((v - min) / range) * (height - 4) - 2;
return `${x},${y}`;
}).join(' ');
return `<svg width="${width}" height="${height}" class="inline-block" data-vals="${values.join(',')}"><polyline points="${points}" fill="none" stroke="#60a5fa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
return `<svg width="${width}" height="${height}" class="inline-block" data-vals="${values.join(',')}"><polyline points="${points}" fill="none" stroke="${color}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
}
// Given pings with region+latency, pick the region with the lowest avg latency
// and return its sparkline in that region's color.
export function sparklineFromPings(pings: Array<{latency_ms?: number|null, region?: string|null}>, width = 120, height = 32): string {
const COLORS: Record<string, string> = {
'eu-central': '#3b82f6',
'us-east': '#10b981',
'us-west': '#f59e0b',
'ap-southeast': '#a78bfa',
};
// Group by region
const byRegion: Record<string, number[]> = {};
for (const p of pings) {
if (p.latency_ms == null) continue;
const key = p.region || '__none__';
if (!byRegion[key]) byRegion[key] = [];
byRegion[key].push(p.latency_ms);
}
if (!Object.keys(byRegion).length) return '';
// Pick region with lowest average latency
let bestRegion = '__none__';
let bestAvg = Infinity;
for (const [region, vals] of Object.entries(byRegion)) {
const avg = vals.reduce((a, b) => a + b, 0) / vals.length;
if (avg < bestAvg) { bestAvg = avg; bestRegion = region; }
}
const color = COLORS[bestRegion] || '#60a5fa';
return sparkline(byRegion[bestRegion], width, height, color);
}