115 أسطر
5.1 KiB
HTML
115 أسطر
5.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>mithal.space Monitoring Dashboard</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<style>
|
|
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #0f172a; color: #f8fafc; margin: 0; padding: 20px; }
|
|
.container { max-width: 1100px; margin: auto; }
|
|
h1 { text-align: center; color: #38bdf8; margin-bottom: 30px; }
|
|
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; margin-bottom: 30px; }
|
|
.card { background: #1e293b; padding: 20px; border-radius: 12px; border: 1px solid #334155; text-align: center; }
|
|
.card h3 { margin: 0; font-size: 14px; color: #94a3b8; }
|
|
.card p { margin: 10px 0 0; font-size: 28px; font-weight: bold; color: #38bdf8; }
|
|
.chart-container { background: #1e293b; padding: 20px; border-radius: 12px; border: 1px solid #334155; margin-bottom: 30px; }
|
|
table { width: 100%; border-collapse: collapse; background: #1e293b; border-radius: 12px; overflow: hidden; }
|
|
th, td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #334155; }
|
|
th { background-color: #0f172a; color: #38bdf8; }
|
|
.badge-up { background: #166534; color: #4ade80; padding: 4px 8px; border-radius: 4px; font-weight: bold; }
|
|
.badge-down { background: #991b1b; color: #f87171; padding: 4px 8px; border-radius: 4px; font-weight: bold; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>mithal.space Live Engine Monitoring</h1>
|
|
|
|
<div class="cards">
|
|
<div class="card"><h3>24h Uptime</h3><p id="uptime-val">100%</p></div>
|
|
<div class="card"><h3>Avg Latency</h3><p id="latency-val">-- ms</p></div>
|
|
<div class="card"><h3>SSL Cert Expiry</h3><p id="ssl-val">-- days</p></div>
|
|
<div class="card"><h3>DNS Lookup</h3><p id="dns-val">-- ms</p></div>
|
|
</div>
|
|
|
|
<div class="chart-container">
|
|
<canvas id="latencyChart" height="100"></canvas>
|
|
</div>
|
|
|
|
<h2>Recent 10 Checks Log</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Timestamp</th>
|
|
<th>Status</th>
|
|
<th>HTTP Code</th>
|
|
<th>Latency</th>
|
|
<th>DNS Time</th>
|
|
<th>Search Response</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="logs-body"></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<script>
|
|
async function fetchMetrics() {
|
|
try {
|
|
const res = await fetch('/api/mithal-metrics');
|
|
const data = await res.json();
|
|
|
|
if(!data || data.length === 0) return;
|
|
|
|
// Uptime calc
|
|
const upCount = data.filter(d => d.uptime).length;
|
|
const uptimePct = ((upCount / data.length) * 100).toFixed(1);
|
|
document.getElementById('uptime-val').innerText = `${uptimePct}%`;
|
|
|
|
const latest = data[data.length - 1];
|
|
document.getElementById('latency-val').innerText = `${latest.latency_ms} ms`;
|
|
document.getElementById('ssl-val').innerText = `${latest.ssl_days_left} Days`;
|
|
document.getElementById('dns-val').innerText = `${latest.dns_time_ms} ms`;
|
|
|
|
// Render Logs Table (Last 10)
|
|
const logs = data.slice(-10).reverse();
|
|
const tbody = document.getElementById('logs-body');
|
|
tbody.innerHTML = logs.map(l => `
|
|
<tr>
|
|
<td>${l.timestamp}</td>
|
|
<td><span class="${l.uptime ? 'badge-up' : 'badge-down'}">${l.uptime ? 'UP' : 'DOWN'}</span></td>
|
|
<td>${l.status_code}</td>
|
|
<td>${l.latency_ms} ms</td>
|
|
<td>${l.dns_time_ms} ms</td>
|
|
<td>${l.search_response_ms} ms</td>
|
|
</tr>
|
|
`).join('');
|
|
|
|
// Render Chart
|
|
const labels = data.map(d => d.timestamp.split(' ')[1]);
|
|
const latencies = data.map(d => d.latency_ms);
|
|
|
|
if (window.myChart) window.myChart.destroy();
|
|
const ctx = document.getElementById('latencyChart').getContext('2d');
|
|
window.myChart = new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: labels,
|
|
datasets: [{
|
|
label: 'HTTP Latency (ms)',
|
|
data: latencies,
|
|
borderColor: '#38bdf8',
|
|
backgroundColor: 'rgba(56, 189, 248, 0.1)',
|
|
fill: true,
|
|
tension: 0.3
|
|
}]
|
|
},
|
|
options: { responsive: true, scales: { y: { beginAtZero: true } } }
|
|
});
|
|
} catch(e) { console.error("Error loading metrics:", e); }
|
|
}
|
|
|
|
fetchMetrics();
|
|
setInterval(fetchMetrics, 30000);
|
|
</script>
|
|
</body>
|
|
</html>
|