chore: clean up backup files from tracking, fix remote to main repo
This commit is contained in:
@@ -1,135 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Syslog GPU Monitor</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0d1117; color: #c9d1d9; padding: 20px; }
|
||||
h1 { font-size: 22px; margin-bottom: 8px; color: #58a6ff; }
|
||||
.subtitle { color: #8b949e; font-size: 13px; margin-bottom: 24px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 24px; }
|
||||
.card { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 20px; }
|
||||
.card h2 { font-size: 16px; margin-bottom: 12px; color: #f0f6fc; }
|
||||
.card.down { border-color: #da3633; }
|
||||
.card.warn { border-color: #d29922; }
|
||||
.metric { display: flex; justify-content: space-between; padding: 4px 0; font-size: 14px; }
|
||||
.metric .label { color: #8b949e; }
|
||||
.metric .value { font-weight: 600; font-variant-numeric: tabular-nums; }
|
||||
.value.good { color: #3fb950; }
|
||||
.value.warn { color: #d29922; }
|
||||
.value.bad { color: #da3633; }
|
||||
.bar-bg { background: #21262d; border-radius: 4px; height: 8px; margin: 4px 0 8px; overflow: hidden; }
|
||||
.bar { height: 100%; border-radius: 4px; transition: width 0.5s; }
|
||||
.bar.good { background: #3fb950; }
|
||||
.bar.warn { background: #d29922; }
|
||||
.bar.bad { background: #da3633; }
|
||||
.summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 24px; }
|
||||
.stat { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 14px; text-align: center; }
|
||||
.stat .num { font-size: 28px; font-weight: 700; }
|
||||
.stat .lbl { font-size: 11px; color: #8b949e; margin-top: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
|
||||
.status-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; }
|
||||
.status-dot.healthy { background: #3fb950; }
|
||||
.status-dot.warning { background: #d29922; }
|
||||
.status-dot.down { background: #da3633; }
|
||||
.circuit { font-size: 12px; padding: 2px 8px; border-radius: 4px; display: inline-block; }
|
||||
.circuit.open { background: #da363322; color: #da3633; border: 1px solid #da363344; }
|
||||
.circuit.closed { background: #3fb95022; color: #3fb950; border: 1px solid #3fb95044; }
|
||||
footer { text-align: center; color: #484f58; font-size: 11px; margin-top: 20px; }
|
||||
.refresh { animation: pulse 0.3s; }
|
||||
@keyframes pulse { 0%{opacity:0.4} 100%{opacity:1} }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>⚡ Syslog GPU Monitor</h1>
|
||||
<p class="subtitle">Real-time GPU health — <span id="updated">loading...</span></p>
|
||||
|
||||
<div class="summary">
|
||||
<div class="stat"><div class="num good" id="gpus-online">-</div><div class="lbl">GPUs Online</div></div>
|
||||
<div class="stat"><div class="num" id="total-requests">-</div><div class="lbl">Active Requests</div></div>
|
||||
<div class="stat"><div class="num warn" id="trip-count">-</div><div class="lbl">Circuit Trips</div></div>
|
||||
<div class="stat"><div class="num" id="slots-used">-</div><div class="lbl">Slots Used</div></div>
|
||||
</div>
|
||||
|
||||
<div class="grid" id="gpu-grid"></div>
|
||||
|
||||
<footer>Syslog Solution LLC — Auto-refreshes every 5s · <span id="last-refresh">—</span></footer>
|
||||
|
||||
<script>
|
||||
const API = '';
|
||||
|
||||
async function fetchJSON(url) {
|
||||
const r = await fetch(url);
|
||||
return r.json();
|
||||
}
|
||||
|
||||
function barClass(pct) {
|
||||
if (pct > 90) return 'bad';
|
||||
if (pct > 75) return 'warn';
|
||||
return 'good';
|
||||
}
|
||||
|
||||
function tempClass(temp) {
|
||||
if (temp > 80) return 'bad';
|
||||
if (temp > 65) return 'warn';
|
||||
return 'good';
|
||||
}
|
||||
|
||||
function scoreClass(score) {
|
||||
if (score > 60) return 'bad';
|
||||
if (score > 35) return 'warn';
|
||||
return 'good';
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
const [health, perf] = await Promise.all([
|
||||
fetchJSON(API + '/metrics/gpu-health'),
|
||||
fetchJSON(API + '/metrics/performance?window=1')
|
||||
]);
|
||||
|
||||
// Summary stats
|
||||
document.getElementById('gpus-online').textContent = health.kpi.gpus_online + '/' + health.kpi.total_gpus;
|
||||
document.getElementById('trip-count').textContent = health.kpi.total_trips;
|
||||
document.getElementById('total-requests').textContent = perf.summary?.total_requests || 0;
|
||||
const used = health.gpus.reduce((s,g) => s + g.active_requests, 0);
|
||||
const total = health.gpus.reduce((s,g) => s + g.max_concurrent, 0);
|
||||
document.getElementById('slots-used').textContent = used + '/' + total;
|
||||
|
||||
// GPU cards
|
||||
const grid = document.getElementById('gpu-grid');
|
||||
grid.innerHTML = health.gpus.map(g => {
|
||||
const statusClass = g.status === 'healthy' ? 'healthy' : g.status === 'down' ? 'down' : 'warning';
|
||||
const circuitLabel = g.circuit_tripped ? 'OPEN' : 'closed';
|
||||
const circuitClass = g.circuit_tripped ? 'open' : 'closed';
|
||||
const cardClass = g.circuit_tripped ? 'warn' : g.status === 'down' ? 'down' : '';
|
||||
const activeLabel = `${g.active_requests}/${g.max_concurrent}`;
|
||||
const name = g.label || g.id;
|
||||
|
||||
return `
|
||||
<div class="card ${cardClass}">
|
||||
<h2><span class="status-dot ${statusClass}"></span>${name}</h2>
|
||||
<div class="metric"><span class="label">Health Score</span><span class="value ${scoreClass(g.health_score)}">${g.health_score}</span></div>
|
||||
<div class="metric"><span class="label">VRAM</span><span class="value ${barClass(g.vram_pct)}">${g.vram_pct}%</span></div>
|
||||
<div class="bar-bg"><div class="bar ${barClass(g.vram_pct)}" style="width:${g.vram_pct}%"></div></div>
|
||||
<div class="metric"><span class="label">Temperature</span><span class="value ${tempClass(g.temp_c)}">${g.temp_c}°C</span></div>
|
||||
<div class="bar-bg"><div class="bar ${tempClass(g.temp_c)}" style="width:${Math.min(g.temp_c,100)}%"></div></div>
|
||||
<div class="metric"><span class="label">Active</span><span class="value">${activeLabel}</span></div>
|
||||
<div class="metric"><span class="label">Circuit</span><span class="circuit ${circuitClass}">${circuitLabel}</span></div>
|
||||
<div class="metric"><span class="label">Trips</span><span class="value">${g.circuit_trip_count}</span></div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
document.getElementById('updated').textContent = new Date().toLocaleTimeString();
|
||||
document.getElementById('last-refresh').textContent = 'Last refresh: ' + new Date().toLocaleTimeString();
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
refresh();
|
||||
setInterval(refresh, 5000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user