diff --git a/apps/web/src/views/detail.ejs b/apps/web/src/views/detail.ejs
index d1c1b3e..f3e3341 100644
--- a/apps/web/src/views/detail.ejs
+++ b/apps/web/src/views/detail.ejs
@@ -265,68 +265,9 @@
}
});
- // Track running stats for SSE incremental updates
- let _totalPings = <%= pings.length %>, _upPings = <%= upPings.length %>;
- let _latencySum = <%= latencies.reduce((a, b) => a + b, 0) %>, _latencyCount = <%= latencies.length %>;
-
- // SSE: live ping updates (minimal DOM patches only — no chart re-render)
- watchMonitor(monitorId, (ping) => {
- // Stats
- _totalPings++;
- if (ping.up) _upPings++;
- if (ping.latency_ms != null) {
- _latencySum += ping.latency_ms;
- _latencyCount++;
- const avg = Math.round(_latencySum / _latencyCount);
- document.getElementById('stat-latency').textContent = avg + 'ms';
- }
-
- document.getElementById('stat-last').innerHTML = timeAgo(ping.checked_at);
- document.getElementById('stat-status').innerHTML = ping.up
- ? 'Up'
- : 'Down';
- document.getElementById('status-dot').innerHTML = ping.up
- ? ''
- : '';
-
- if (_totalPings > 0) {
- const pct = Math.round((_upPings / _totalPings) * 100);
- document.getElementById('stat-uptime').textContent = pct + '%';
- }
-
- // Status history bar — append new segment
- const bar = document.getElementById('status-bar');
- if (bar) {
- const seg = document.createElement('div');
- seg.className = `flex-1 ${ping.up ? 'bg-green-500/70' : 'bg-red-500/70'}`;
- seg.title = `${new Date(ping.checked_at).toLocaleString()} — ${ping.up ? 'Up' : 'Down'}${ping.latency_ms ? ' ' + ping.latency_ms + 'ms' : ''}`;
- bar.prepend(seg);
- while (bar.children.length > 60) bar.removeChild(bar.lastChild);
- }
-
- // Refresh latency chart (debounced)
- scheduleChartRefresh();
-
- // Ping table — prepend plain HTML row
- const tbody = document.getElementById('pings-table');
- if (tbody) {
- const tr = document.createElement('tr');
- tr.className = 'hover:bg-gray-800/50';
- tr.innerHTML = `
-
${ping.up ? 'Up' : 'Down'} |
- ${ping.status_code ?? '—'} |
- ${ping.latency_ms ? ping.latency_ms + 'ms' : '—'} |
- ${timeAgo(ping.checked_at)} |
- ${ping.error ? escapeHtml(ping.error) : ''} |
- `;
- tbody.prepend(tr);
- while (tbody.children.length > 100) tbody.removeChild(tbody.lastChild);
- }
- });
-
- // Refresh latency chart from server (debounced — at most once per 5s)
+ // SSE: on each ping, refresh the chart (debounced — at most once per 5s)
let _chartRefreshTimer = null;
- function scheduleChartRefresh() {
+ watchMonitor(monitorId, () => {
if (_chartRefreshTimer) return;
_chartRefreshTimer = setTimeout(async () => {
_chartRefreshTimer = null;
@@ -335,7 +276,7 @@
if (res.ok) document.getElementById('latency-chart').innerHTML = await res.text();
} catch {}
}, 5000);
- }
+ });
<%~ include('./partials/foot') %>
diff --git a/apps/web/src/views/home.ejs b/apps/web/src/views/home.ejs
index f4296ae..4297f58 100644
--- a/apps/web/src/views/home.ejs
+++ b/apps/web/src/views/home.ejs
@@ -88,41 +88,14 @@
}, 5000);
}
- // SSE: subscribe to all monitors for live updates
- const sseConnections = [];
- function subscribeAll() {
- const monitorCards = document.querySelectorAll('[data-monitor-id]');
- monitorCards.forEach(card => {
- const mid = card.dataset.monitorId;
- const es = watchMonitor(mid, (ping) => {
- // Status dot
- const statusDot = card.querySelector('.status-dot');
- if (statusDot) {
- const wasUp = statusDot.classList.contains('bg-green-500');
- statusDot.className = `status-dot w-2.5 h-2.5 rounded-full ${ping.up ? 'bg-green-500' : 'bg-red-500'}`;
- if (wasUp !== ping.up) {
- const dots = document.querySelectorAll('.status-dot');
- const upNow = [...dots].filter(d => d.classList.contains('bg-green-500')).length;
- const downNow = [...dots].filter(d => d.classList.contains('bg-red-500')).length;
- const summary = document.getElementById('summary');
- if (summary) summary.innerHTML = `${upNow} up · ${downNow} down · ${dots.length} total`;
- }
- }
-
- // Latency text
- if (ping.latency_ms) card.querySelector('.stat-latency').textContent = `${ping.latency_ms}ms`;
-
- // Timestamp
- card.querySelector('.stat-last').innerHTML = timeAgo(ping.checked_at);
-
- // Sparkline — debounced fetch from server
- const sparkEl = card.querySelector('.stat-sparkline');
- if (sparkEl) scheduleSparklineRefresh(mid, sparkEl);
- });
- if (es) sseConnections.push(es);
+ // SSE: subscribe to all monitors, refresh sparkline on each ping
+ document.querySelectorAll('[data-monitor-id]').forEach(card => {
+ const mid = card.dataset.monitorId;
+ watchMonitor(mid, () => {
+ const sparkEl = card.querySelector('.stat-sparkline');
+ if (sparkEl) scheduleSparklineRefresh(mid, sparkEl);
});
- }
- subscribeAll();
+ });
<%~ include('./partials/foot') %>