feat: add number and time formatting to dashboard metrics
Some checks failed
Build and Test / build (push) Failing after 36s
Build and Test / coverage (push) Failing after 44s

This commit is contained in:
retoor 2025-12-29 01:50:08 +01:00
parent c414e2c2b1
commit 967cf09beb
2 changed files with 16 additions and 6 deletions

View File

@ -7,6 +7,14 @@
## Version 0.7.0 - 2025-12-29
The dashboard now formats numbers and times in metrics for improved readability.
**Changes:** 1 files, 14 lines
**Languages:** C (14 lines)
## Version 0.6.0 - 2025-12-29
Integrates monitoring metrics into connection handling to provide real-time insights into network performance. Redesigns the dashboard with advanced metrics and charts for enhanced visualization of system data.

View File

@ -86,6 +86,8 @@ static const char *DASHBOARD_HTML =
" const formatDisk = v => v>=1024?(v/1024).toFixed(1)+' GB/s':v.toFixed(1)+' MB/s';\n"
" const formatBytes = b => { if(b===0)return'0 B'; const k=1024,s=['B','KB','MB','GB','TB'],i=Math.floor(Math.log(b)/Math.log(k)); return(b/Math.pow(k,i)).toFixed(1)+' '+s[i]; };\n"
" const formatUptime = s => { const d=Math.floor(s/86400),h=Math.floor((s%86400)/3600),m=Math.floor((s%3600)/60); return d>0?d+'d '+h+'h':h>0?h+'h '+m+'m':m+'m'; };\n"
" const formatNum = n => { if(n===null||n===undefined)return'0'; n=parseFloat(n); if(isNaN(n))return'0'; if(n>=1e9)return(n/1e9).toFixed(1)+'B'; if(n>=1e6)return(n/1e6).toFixed(1)+'M'; if(n>=1e3)return(n/1e3).toFixed(1)+'K'; return n.toFixed(0); };\n"
" const formatMs = v => { if(v>=1000)return(v/1000).toFixed(1)+'s'; return v.toFixed(0)+'ms'; };\n"
" const baseOpts = (sec,yCb) => ({responsive:true,maintainAspectRatio:false,animation:false,layout:{padding:{top:30}},interaction:{mode:'nearest',axis:'x',intersect:false},scales:{x:{type:'linear',display:true,grid:{color:'#2a2e3e'},ticks:{color:'#666',maxTicksLimit:7,callback:formatTime},min:-sec*1000,max:0},y:{display:true,grid:{color:'#2a2e3e'},ticks:{color:'#666',beginAtZero:true,callback:yCb}}},plugins:{legend:{display:false}},elements:{point:{radius:0},line:{borderWidth:2,tension:0.4,fill:true}}});\n"
" const cpuChart = new Chart(document.getElementById('cpuChart'),{type:'line',data:{datasets:[{data:[],borderColor:'#f39c12',backgroundColor:'rgba(243,156,18,0.1)'}]},options:{...baseOpts(300,v=>v+'%'),scales:{...baseOpts(300).scales,y:{...baseOpts(300).scales.y,max:100}}}});\n"
" const memChart = new Chart(document.getElementById('memChart'),{type:'line',data:{datasets:[{data:[],borderColor:'#e74c3c',backgroundColor:'rgba(231,76,60,0.1)'}]},options:baseOpts(300,v=>v.toFixed(1)+' GB')});\n"
@ -102,13 +104,13 @@ static const char *DASHBOARD_HTML =
" const r=await fetch('/rproxy/api/stats'),d=await r.json();\n"
" const hs=d.current.health_score||100; document.getElementById('healthScore').textContent=hs.toFixed(0);\n"
" const hEl=document.getElementById('healthScore'); hEl.className='metric-value '+(hs>=80?'health':hs>=50?'warning':'danger');\n"
" document.getElementById('rps').textContent=(d.current.requests_per_second||0).toFixed(0);\n"
" document.getElementById('p50').textContent=(d.latency?.p50_ms||0).toFixed(0);\n"
" document.getElementById('p99').textContent=(d.latency?.p99_ms||0).toFixed(0);\n"
" document.getElementById('rps').textContent=formatNum(d.current.requests_per_second||0);\n"
" document.getElementById('p50').textContent=formatMs(d.latency?.p50_ms||0);\n"
" document.getElementById('p99').textContent=formatMs(d.latency?.p99_ms||0);\n"
" document.getElementById('errorRate').textContent=((d.current.error_rate_1m||0)*100).toFixed(1)+'%';\n"
" document.getElementById('connections').textContent=d.current.active_connections;\n"
" document.getElementById('connections').textContent=formatNum(d.current.active_connections);\n"
" document.getElementById('cpu').textContent=d.current.cpu_percent+'%';\n"
" document.getElementById('memory').textContent=d.current.memory_gb+'G';\n"
" document.getElementById('memory').textContent=d.current.memory_gb+'GB';\n"
" document.getElementById('uptime').textContent=formatUptime(d.current.uptime_seconds||0);\n"
" cpuChart.data.datasets[0].data=d.cpu_history; memChart.data.datasets[0].data=d.memory_history;\n"
" netChart.data.datasets[0].data=d.network_rx_history; netChart.data.datasets[1].data=d.network_tx_history;\n"
@ -124,7 +126,7 @@ static const char *DASHBOARD_HTML =
" d.processes.forEach((p,i)=>{\n"
" let row=tbody.children[i*2]; if(!row){row=document.createElement('tr'); tbody.appendChild(row);}\n"
" const errP=(p.error_rate*100).toFixed(1); const cls=parseFloat(errP)>5?'status-error':parseFloat(errP)>1?'status-warn':'status-ok';\n"
" row.innerHTML=`<td><span class='status-indicator ${cls}'></span>${p.name}</td><td>${p.rps||0}</td><td>${p.total_requests}</td><td>${(p.latency_p50||0).toFixed(0)}</td><td>${(p.latency_p99||0).toFixed(0)}</td><td>${p.status_2xx||0}</td><td>${p.status_4xx||0}</td><td>${p.status_5xx||0}</td><td>${errP}%</td><td>${formatBytes(p.bytes_sent)}</td><td>${formatBytes(p.bytes_recv)}</td>`;\n"
" row.innerHTML=`<td><span class='status-indicator ${cls}'></span>${p.name}</td><td>${formatNum(p.rps||0)}</td><td>${formatNum(p.total_requests)}</td><td>${formatMs(p.latency_p50||0)}</td><td>${formatMs(p.latency_p99||0)}</td><td>${formatNum(p.status_2xx||0)}</td><td>${formatNum(p.status_4xx||0)}</td><td>${formatNum(p.status_5xx||0)}</td><td>${errP}%</td><td>${formatBytes(p.bytes_sent)}</td><td>${formatBytes(p.bytes_recv)}</td>`;\n"
" let chartRow=tbody.children[i*2+1]; if(!chartRow){chartRow=document.createElement('tr'); chartRow.innerHTML=`<td colspan='11' style='padding:10px 0;border:none;'><div class='vhost-chart-container'><div class='chart-title'>Throughput - ${p.name}</div><canvas id='vc${i}'></canvas></div></td>`; tbody.appendChild(chartRow);}\n"
" const cid='vc'+i,cv=document.getElementById(cid); if(!cv)return;\n"
" if(!window.vhostCharts[cid]){const cols=[{b:'#3498db',bg:'rgba(52,152,219,0.1)'},{b:'#2ecc71',bg:'rgba(46,204,113,0.1)'},{b:'#f39c12',bg:'rgba(243,156,18,0.1)'},{b:'#e74c3c',bg:'rgba(231,76,60,0.1)'}],c=cols[i%4]; window.vhostCharts[cid]=new Chart(cv,{type:'line',data:{datasets:[{data:p.throughput_history||[],borderColor:c.b,backgroundColor:c.bg}]},options:baseOpts(60,formatSize)});}\n"