- Implement comprehensive SQL query logging for queries over 10ms - Add logging wrapper methods for all database operations - Replace timing code in GetStats with simple info log messages - Add missing database indexes for better query performance: - idx_live_routes_lookup for common prefix/origin/peer lookups - idx_live_routes_withdraw for withdrawal updates - idx_prefixes_prefix for prefix lookups - idx_asn_peerings_lookup for peering relationship queries - Increase SQLite cache size to 512MB - Add performance-oriented SQLite pragmas - Extract HTML templates to separate files using go:embed - Add JSON response middleware with @meta field (like bgpview.io API) - Fix concurrent map write errors in HTTP handlers - Add request timeout handling with proper JSON error responses These changes significantly improve database query performance and provide visibility into slow queries for debugging purposes.
191 lines
7.3 KiB
HTML
191 lines
7.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>RouteWatch Status</title>
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
background: #f5f5f5;
|
|
}
|
|
h1 {
|
|
color: #333;
|
|
margin-bottom: 30px;
|
|
}
|
|
.status-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: 20px;
|
|
margin-bottom: 30px;
|
|
}
|
|
.status-card {
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
.status-card h2 {
|
|
margin: 0 0 15px 0;
|
|
font-size: 18px;
|
|
color: #666;
|
|
}
|
|
.metric {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 8px 0;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
.metric:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.metric-label {
|
|
color: #666;
|
|
}
|
|
.metric-value {
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
.connected {
|
|
color: #22c55e;
|
|
}
|
|
.disconnected {
|
|
color: #ef4444;
|
|
}
|
|
.error {
|
|
background: #fee;
|
|
color: #c00;
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
margin-top: 20px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>RouteWatch Status</h1>
|
|
<div id="error" class="error" style="display: none;"></div>
|
|
<div class="status-grid">
|
|
<div class="status-card">
|
|
<h2>Connection Status</h2>
|
|
<div class="metric">
|
|
<span class="metric-label">Status</span>
|
|
<span class="metric-value" id="connected">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">Uptime</span>
|
|
<span class="metric-value" id="uptime">-</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="status-card">
|
|
<h2>Stream Statistics</h2>
|
|
<div class="metric">
|
|
<span class="metric-label">Total Messages</span>
|
|
<span class="metric-value" id="total_messages">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">Messages/sec</span>
|
|
<span class="metric-value" id="messages_per_sec">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">Total Data</span>
|
|
<span class="metric-value" id="total_bytes">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">Throughput</span>
|
|
<span class="metric-value" id="mbits_per_sec">-</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="status-card">
|
|
<h2>Database Statistics</h2>
|
|
<div class="metric">
|
|
<span class="metric-label">ASNs</span>
|
|
<span class="metric-value" id="asns">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">Total Prefixes</span>
|
|
<span class="metric-value" id="prefixes">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">IPv4 Prefixes</span>
|
|
<span class="metric-value" id="ipv4_prefixes">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">IPv6 Prefixes</span>
|
|
<span class="metric-value" id="ipv6_prefixes">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">Peerings</span>
|
|
<span class="metric-value" id="peerings">-</span>
|
|
</div>
|
|
<div class="metric">
|
|
<span class="metric-label">Live Routes</span>
|
|
<span class="metric-value" id="live_routes">-</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function formatBytes(bytes) {
|
|
if (bytes === 0) return '0 B';
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
}
|
|
|
|
function formatNumber(num) {
|
|
return num.toLocaleString();
|
|
}
|
|
|
|
function updateStatus() {
|
|
fetch('/api/v1/stats')
|
|
.then(response => response.json())
|
|
.then(response => {
|
|
// Check if response is an error
|
|
if (response.status === 'error') {
|
|
document.getElementById('error').textContent = 'Error: ' + response.error.msg;
|
|
document.getElementById('error').style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
// Extract data from successful response
|
|
const data = response.data;
|
|
|
|
// Connection status
|
|
const connectedEl = document.getElementById('connected');
|
|
connectedEl.textContent = data.connected ? 'Connected' : 'Disconnected';
|
|
connectedEl.className = 'metric-value ' + (data.connected ? 'connected' : 'disconnected');
|
|
|
|
// Update all metrics
|
|
document.getElementById('uptime').textContent = data.uptime;
|
|
document.getElementById('total_messages').textContent = formatNumber(data.total_messages);
|
|
document.getElementById('messages_per_sec').textContent = data.messages_per_sec.toFixed(1);
|
|
document.getElementById('total_bytes').textContent = formatBytes(data.total_bytes);
|
|
document.getElementById('mbits_per_sec').textContent = data.mbits_per_sec.toFixed(2) + ' Mbps';
|
|
document.getElementById('asns').textContent = formatNumber(data.asns);
|
|
document.getElementById('prefixes').textContent = formatNumber(data.prefixes);
|
|
document.getElementById('ipv4_prefixes').textContent = formatNumber(data.ipv4_prefixes);
|
|
document.getElementById('ipv6_prefixes').textContent = formatNumber(data.ipv6_prefixes);
|
|
document.getElementById('peerings').textContent = formatNumber(data.peerings);
|
|
document.getElementById('live_routes').textContent = formatNumber(data.live_routes);
|
|
|
|
// Clear any errors
|
|
document.getElementById('error').style.display = 'none';
|
|
})
|
|
.catch(error => {
|
|
document.getElementById('error').textContent = 'Error fetching status: ' + error;
|
|
document.getElementById('error').style.display = 'block';
|
|
});
|
|
}
|
|
|
|
// Update immediately and then every 500ms
|
|
updateStatus();
|
|
setInterval(updateStatus, 500);
|
|
</script>
|
|
</body>
|
|
</html> |