|
70 | 70 | .spinner{width:8px;height:8px;border:1.5px solid #30363d;border-top-color:#58a6ff;border-radius:50%;display:inline-block} |
71 | 71 | .spinner.active{animation:spin 0.6s linear infinite} |
72 | 72 | @keyframes spin{to{transform:rotate(360deg)}} |
| 73 | +
|
| 74 | +canvas.sparkline{display:block;width:100%;height:24px;margin-top:6px} |
| 75 | +.bw-row{display:flex;align-items:center;gap:12px;padding:5px 0;border-bottom:1px solid #21262d} |
| 76 | +.bw-row:last-child{border-bottom:none} |
| 77 | +.bw-label{color:#8b949e;font-size:11px;width:56px;flex-shrink:0} |
| 78 | +canvas.bw-spark{display:block;flex:1;height:32px} |
| 79 | +.bw-val{color:#f0f6fc;font-size:12px;font-weight:500;width:100px;text-align:right;flex-shrink:0;font-variant-numeric:tabular-nums} |
73 | 80 | </style> |
74 | 81 | </head> |
75 | 82 | <body> |
|
93 | 100 | <div class="section-title">Health <span class="section-tag">this pod</span></div> |
94 | 101 | <div class="row"><span class="label">Memory</span><span class="value" id="memory">-</span></div> |
95 | 102 | <div class="row"><span class="label">In-Flight</span><span class="value" id="in-flight">-</span></div> |
96 | | -<div class="section-title" style="margin-top:10px;margin-bottom:6px">Errors <span class="section-tag">5 min rate</span></div> |
| 103 | +<div class="section-title" style="margin-top:10px;margin-bottom:6px">Errors <span class="section-tag">10 min rate</span></div> |
97 | 104 | <div class="errors-row"> |
98 | 105 | <span class="err-item">4xx <span class="err-val" id="err-4xx">0</span>/min</span> |
99 | 106 | <span class="err-item">5xx <span class="err-val" id="err-5xx">0</span>/min</span> |
|
102 | 109 | </div> |
103 | 110 |
|
104 | 111 | <div class="section"> |
105 | | -<div class="section-title">Throughput <span class="section-tag">this pod · 5 min rate</span></div> |
| 112 | +<div class="section-title">Throughput <span class="section-tag">this pod · 10 min</span></div> |
106 | 113 | <div class="throughput-grid"> |
107 | | -<div class="tp-item"><div class="tp-num" id="tp-req">0</div><div class="tp-unit">/min</div><div class="tp-label">requests</div></div> |
108 | | -<div class="tp-item"><div class="tp-num" id="tp-enc">0</div><div class="tp-unit">/min · <span id="tp-enc-bytes">0 B</span>/min</div><div class="tp-label">encrypt</div></div> |
109 | | -<div class="tp-item"><div class="tp-num" id="tp-dec">0</div><div class="tp-unit">/min · <span id="tp-dec-bytes">0 B</span>/min</div><div class="tp-label">decrypt</div></div> |
| 114 | +<div class="tp-item"><div class="tp-num" id="tp-req">0</div><div class="tp-unit">/min</div><div class="tp-label">requests</div><canvas class="sparkline" id="spark-req" height="24"></canvas></div> |
| 115 | +<div class="tp-item"><div class="tp-num" id="tp-enc">0</div><div class="tp-unit">/min · <span id="tp-enc-bytes">0 B</span>/min</div><div class="tp-label">encrypt</div><canvas class="sparkline" id="spark-enc" height="24"></canvas></div> |
| 116 | +<div class="tp-item"><div class="tp-num" id="tp-dec">0</div><div class="tp-unit">/min · <span id="tp-dec-bytes">0 B</span>/min</div><div class="tp-label">decrypt</div><canvas class="sparkline" id="spark-dec" height="24"></canvas></div> |
| 117 | +</div> |
110 | 118 | </div> |
| 119 | +
|
| 120 | +<div class="section"> |
| 121 | +<div class="section-title">Bandwidth <span class="section-tag">this pod · 10 min</span></div> |
| 122 | +<div class="bw-row"><span class="bw-label">encrypt</span><canvas class="bw-spark" id="spark-bw-enc" height="32"></canvas><span class="bw-val" id="bw-enc-val">0 B/min</span></div> |
| 123 | +<div class="bw-row"><span class="bw-label">decrypt</span><canvas class="bw-spark" id="spark-bw-dec" height="32"></canvas><span class="bw-val" id="bw-dec-val">0 B/min</span></div> |
111 | 124 | </div> |
112 | 125 |
|
113 | 126 | <div class="section"> |
|
130 | 143 | return Math.floor(s/86400)+'d '+Math.floor((s%86400)/3600)+'h'; |
131 | 144 | } |
132 | 145 |
|
| 146 | +function drawSpark(id,data,color){ |
| 147 | + var c=document.getElementById(id); |
| 148 | + if(!c)return; |
| 149 | + var dpr=window.devicePixelRatio||1; |
| 150 | + var w=c.offsetWidth,h=parseInt(c.getAttribute('height'))||24; |
| 151 | + c.width=w*dpr;c.height=h*dpr; |
| 152 | + var ctx=c.getContext('2d'); |
| 153 | + ctx.scale(dpr,dpr); |
| 154 | + if(!data||data.length<2)return; |
| 155 | + var mx=0; |
| 156 | + for(var i=0;i<data.length;i++)if(data[i]>mx)mx=data[i]; |
| 157 | + if(!mx)return; |
| 158 | + var bw=Math.max(1,Math.floor(w/data.length)-1); |
| 159 | + ctx.fillStyle=color||'#3fb950'; |
| 160 | + for(var i=0;i<data.length;i++){ |
| 161 | + var bh=Math.round((data[i]/mx)*(h-2)); |
| 162 | + if(data[i]>0&&bh<1)bh=1; |
| 163 | + ctx.fillRect(i*(bw+1),h-bh,bw,bh); |
| 164 | + } |
| 165 | +} |
| 166 | +
|
133 | 167 | function updatePods(pods, currentPod){ |
134 | 168 | var grid=document.getElementById('pods-grid'); |
135 | 169 | if(!pods||pods.length<=1){grid.innerHTML='';return;} |
|
176 | 210 | document.getElementById('tp-enc-bytes').textContent=f.bytes_encrypted_per_min||'0 B'; |
177 | 211 | document.getElementById('tp-dec-bytes').textContent=f.bytes_decrypted_per_min||'0 B'; |
178 | 212 |
|
| 213 | + var hist=(d.throughput||{}).history||{}; |
| 214 | + drawSpark('spark-req',hist.requests_per_min,'#3fb950'); |
| 215 | + drawSpark('spark-enc',hist.encrypt_per_min,'#3fb950'); |
| 216 | + drawSpark('spark-dec',hist.decrypt_per_min,'#58a6ff'); |
| 217 | + drawSpark('spark-bw-enc',hist.bytes_encrypted_per_min,'#3fb950'); |
| 218 | + drawSpark('spark-bw-dec',hist.bytes_decrypted_per_min,'#58a6ff'); |
| 219 | + document.getElementById('bw-enc-val').textContent=(f.bytes_encrypted_per_min||'0 B')+'/min'; |
| 220 | + document.getElementById('bw-dec-val').textContent=(f.bytes_decrypted_per_min||'0 B')+'/min'; |
| 221 | +
|
179 | 222 | document.getElementById('upload-num').textContent=u.active_count||0; |
180 | 223 | document.getElementById('uploads-source').textContent=pod.storage_backend==='In-memory'?'this pod':'cluster \\u00b7 Redis'; |
181 | 224 | var ut=document.getElementById('uploads-table'); |
|
0 commit comments