diff --git a/public/js/app.js b/public/js/app.js
index 7c572fe..53ac5da 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -970,6 +970,25 @@
+ ${m.key === 'networkTrend' ? `
+ ` : ''}
`).join('');
@@ -1073,12 +1092,62 @@
data.series = null; // This tells MetricChart to draw a single line instead of stacked area
}
+ if (metricKey === 'networkTrend') {
+ const stats = calculateHistoryStats(data);
+ const summaryDiv = document.getElementById(`summary-${metricKey}`);
+ if (summaryDiv) {
+ summaryDiv.style.display = 'flex';
+ const rxEl = document.getElementById(`stat-${metricKey}-rx`);
+ const txEl = document.getElementById(`stat-${metricKey}-tx`);
+ const p95El = document.getElementById(`stat-${metricKey}-p95`);
+ const totalEl = document.getElementById(`stat-${metricKey}-total`);
+
+ if (rxEl) rxEl.textContent = formatBytes(stats.rxTotal);
+ if (txEl) txEl.textContent = formatBytes(stats.txTotal);
+ if (p95El) p95El.textContent = formatBandwidth(stats.p95);
+ if (totalEl) totalEl.textContent = formatBytes(stats.total);
+ }
+ }
+
chart.setData(data);
} catch (err) {
console.error(`Error loading history for ${metricKey}:`, err);
}
};
+ function calculateHistoryStats(data) {
+ if (!data.timestamps || data.timestamps.length < 2) {
+ return { rxTotal: 0, txTotal: 0, p95: 0, total: 0 };
+ }
+
+ const tx = data.tx || [];
+ const rx = data.rx || [];
+ const ts = data.timestamps;
+
+ let rxTotal = 0;
+ let txTotal = 0;
+
+ for (let i = 0; i < ts.length - 1; i++) {
+ // Find interval in seconds
+ const duration = (ts[i+1] - ts[i]) / 1000;
+ // Bandwidth (B/s) * time (s) = Bytes
+ rxTotal += (rx[i] || 0) * duration;
+ txTotal += (tx[i] || 0) * duration;
+ }
+
+ // P95 calculation for TX (consistent with AreaChart)
+ const sortedTx = [...tx].sort((a, b) => a - b);
+ const p95Idx = Math.floor(sortedTx.length * 0.95);
+ const p95 = sortedTx.length > 0 ? sortedTx[p95Idx] : 0;
+
+ return {
+ rxTotal,
+ txTotal,
+ p95,
+ total: rxTotal + txTotal
+ };
+ }
+
window.loadCustomMetricHistory = async function (metricKey, event) {
if (event) event.stopPropagation();