diff --git a/extensions/Servers/Proxmox/views/statistics.blade.php b/extensions/Servers/Proxmox/views/statistics.blade.php index d60ddcca0..2eadca325 100644 --- a/extensions/Servers/Proxmox/views/statistics.blade.php +++ b/extensions/Servers/Proxmox/views/statistics.blade.php @@ -340,6 +340,9 @@ This graph displays network traffic over time, showing both incoming (Network In) and outgoing (Network Out) data rates. It helps you monitor bandwidth utilization, identify network bottlenecks, and track data transfer patterns.
+ 95th Percentile Line: The dashed red line shows the 95th percentile of your combined network traffic. This is a common billing metric used by data centers - it means 95% of your traffic samples fall below this line. Understanding your 95th percentile helps predict bandwidth costs and capacity needs. +
Time Range: Select from Hour, Day, Week, Month, or Year to view network usage over different time periods.
@@ -4973,6 +4976,9 @@ }, { name: 'Network Out', data: [] + }, { + name: '95th Percentile', + data: [] }], yaxis: { labels: { @@ -4984,7 +4990,16 @@ }, } }, - colors: ['#a37443', '#dcce58'], + colors: ['#a37443', '#dcce58', '#ef4444'], + stroke: { + curve: 'smooth', + width: [2, 2, 2], + dashArray: [0, 0, 5] + }, + fill: { + type: ['gradient', 'gradient', 'solid'], + opacity: [0.4, 0.4, 0] + }, }); var diskOptions = Object.assign({}, baseOptions, { @@ -5311,6 +5326,18 @@ console.warn('No Network data received', eventData); return; } + + // Calculate 95th percentile of combined network traffic + var allTrafficValues = data.map(function(item) { + return (item.netin || 0) + (item.netout || 0); + }).filter(function(v) { return v > 0; }).sort(function(a, b) { return a - b; }); + + var p95Value = 0; + if (allTrafficValues.length > 0) { + var p95Index = Math.floor(allTrafficValues.length * 0.95); + p95Value = allTrafficValues[Math.min(p95Index, allTrafficValues.length - 1)]; + } + networkChart.updateSeries([{ name: 'Network In', data: data.map(function(item) { @@ -5327,6 +5354,14 @@ y: item.netout ? item.netout : 0, } }) + }, { + name: '95th Percentile (' + formatBytes(p95Value) + ')', + data: data.map(function(item) { + return { + x: item.time * 1000, + y: p95Value, + } + }) }]); // Mark that this chart has successfully received data @@ -5709,16 +5744,18 @@ alert('No data available to export'); return; } - var csv = 'Timestamp,Network In (bytes),Network Out (bytes)\n'; + var csv = 'Timestamp,Network In (bytes),Network Out (bytes),95th Percentile (bytes)\n'; var inData = series[0].data; var outData = series[1] ? series[1].data : []; - var maxLength = Math.max(inData.length, outData.length); + var p95Data = series[2] ? series[2].data : []; + var maxLength = Math.max(inData.length, outData.length, p95Data.length); for (var i = 0; i < maxLength; i++) { var timestamp = inData[i] ? new Date(inData[i].x).toISOString() : (outData[i] ? new Date(outData[i].x).toISOString() : ''); var netIn = inData[i] && inData[i].y !== undefined ? inData[i].y : '0'; var netOut = outData[i] && outData[i].y !== undefined ? outData[i].y : '0'; - csv += timestamp + ',' + netIn + ',' + netOut + '\n'; + var p95 = p95Data[i] && p95Data[i].y !== undefined ? p95Data[i].y : '0'; + csv += timestamp + ',' + netIn + ',' + netOut + ',' + p95 + '\n'; } window.downloadCSV(csv, 'network-usage-' + new Date().toISOString().split('T')[0] + '.csv'); } catch (error) {