added server tracking plus server metrics
This commit is contained in:
parent
80a0a16bab
commit
ca12f4807b
5 changed files with 567 additions and 6 deletions
|
|
@ -14,10 +14,23 @@
|
|||
|
||||
<!-- Sidebar for active players list and filters -->
|
||||
<aside id="sidebar">
|
||||
<!-- Container for sort and filter controls -->
|
||||
<div id="sortButtons" class="sort-buttons"></div>
|
||||
|
||||
<h2 id="activePlayersHeader">Active Mosswart Enjoyers</h2>
|
||||
|
||||
<!-- Server Status -->
|
||||
<div id="serverStatus" class="server-status-container">
|
||||
<h3>Coldeve Server Status</h3>
|
||||
<div class="status-indicator">
|
||||
<span class="status-dot" id="statusDot"></span>
|
||||
<span id="statusText">Checking...</span>
|
||||
</div>
|
||||
<div class="status-details">
|
||||
<div>Players: <span id="playerCount">-</span></div>
|
||||
<div>Latency: <span id="latencyMs">-</span> ms</div>
|
||||
<div>Uptime: <span id="uptime">-</span></div>
|
||||
<div>Last Restart: <span id="lastRestart">-</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Total rares counter -->
|
||||
<div id="totalRaresCounter" class="total-rares-counter">
|
||||
🔥 Total Rares: <span id="totalRaresCount">Loading...</span>
|
||||
|
|
@ -60,6 +73,9 @@
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Container for sort and filter controls -->
|
||||
<div id="sortButtons" class="sort-buttons"></div>
|
||||
|
||||
<!-- Text input to filter active players by name -->
|
||||
<input type="text" id="playerFilter" class="player-filter" placeholder="Filter players..." />
|
||||
|
||||
|
|
|
|||
|
|
@ -1067,13 +1067,87 @@ function updateTotalRaresDisplay(data) {
|
|||
}
|
||||
}
|
||||
|
||||
async function pollServerHealth() {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/server-health`);
|
||||
const data = await response.json();
|
||||
updateServerStatusDisplay(data);
|
||||
} catch (e) {
|
||||
console.error('Server health fetch failed:', e);
|
||||
updateServerStatusDisplay({ status: 'error' });
|
||||
}
|
||||
}
|
||||
|
||||
function updateServerStatusDisplay(data) {
|
||||
const statusDot = document.getElementById('statusDot');
|
||||
const statusText = document.getElementById('statusText');
|
||||
const playerCount = document.getElementById('playerCount');
|
||||
const latencyMs = document.getElementById('latencyMs');
|
||||
const uptime = document.getElementById('uptime');
|
||||
const lastRestart = document.getElementById('lastRestart');
|
||||
|
||||
if (!statusDot || !statusText) return;
|
||||
|
||||
// Update status indicator
|
||||
const status = data.status || 'unknown';
|
||||
statusDot.className = `status-dot status-${status}`;
|
||||
statusText.textContent = status.charAt(0).toUpperCase() + status.slice(1);
|
||||
|
||||
// Update player count
|
||||
if (playerCount) {
|
||||
playerCount.textContent = data.player_count !== null && data.player_count !== undefined ? data.player_count : '-';
|
||||
}
|
||||
|
||||
// Update latency
|
||||
if (latencyMs) {
|
||||
latencyMs.textContent = data.latency_ms ? Math.round(data.latency_ms) : '-';
|
||||
}
|
||||
|
||||
// Update uptime
|
||||
if (uptime) {
|
||||
uptime.textContent = data.uptime || '-';
|
||||
}
|
||||
|
||||
// Update last restart with Stockholm timezone (24h format, no year)
|
||||
if (lastRestart) {
|
||||
if (data.last_restart) {
|
||||
const restartDate = new Date(data.last_restart);
|
||||
const formattedDate = restartDate.toLocaleString('sv-SE', {
|
||||
timeZone: 'Europe/Stockholm',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false
|
||||
});
|
||||
lastRestart.textContent = formattedDate;
|
||||
} else {
|
||||
lastRestart.textContent = 'Unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleServerStatusUpdate(msg) {
|
||||
// Handle real-time server status updates via WebSocket
|
||||
if (msg.status === 'up' && msg.message) {
|
||||
// Show notification for server coming back online
|
||||
console.log(`Server Status: ${msg.message}`);
|
||||
}
|
||||
|
||||
// Trigger an immediate server health poll to refresh the display
|
||||
pollServerHealth();
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
if (pollID !== null) return;
|
||||
pollLive();
|
||||
pollTotalRares(); // Initial fetch
|
||||
pollServerHealth(); // Initial server health check
|
||||
pollID = setInterval(pollLive, POLL_MS);
|
||||
// Poll total rares every 5 minutes (300,000 ms)
|
||||
setInterval(pollTotalRares, 300000);
|
||||
// Poll server health every 30 seconds (30,000 ms)
|
||||
setInterval(pollServerHealth, 30000);
|
||||
}
|
||||
|
||||
img.onload = () => {
|
||||
|
|
@ -1091,6 +1165,12 @@ img.onload = () => {
|
|||
initHeatMap();
|
||||
};
|
||||
|
||||
// Ensure server health polling starts regardless of image loading
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Start server health polling immediately on DOM ready
|
||||
pollServerHealth();
|
||||
});
|
||||
|
||||
/* ---------- rendering sorted list & dots ------------------------ */
|
||||
/**
|
||||
* Filter and sort the currentPlayers, then render them.
|
||||
|
|
@ -1293,6 +1373,8 @@ function initWebSocket() {
|
|||
updateVitalsDisplay(msg);
|
||||
} else if (msg.type === 'rare') {
|
||||
triggerEpicRareNotification(msg.character_name, msg.name);
|
||||
} else if (msg.type === 'server_status') {
|
||||
handleServerStatusUpdate(msg);
|
||||
}
|
||||
});
|
||||
socket.addEventListener('close', () => setTimeout(initWebSocket, 2000));
|
||||
|
|
|
|||
|
|
@ -203,6 +203,98 @@ body {
|
|||
to { text-shadow: 0 0 18px rgba(255, 255, 255, 0.9), 0 0 25px rgba(136, 102, 255, 0.5); }
|
||||
}
|
||||
|
||||
/* Server Status Styling */
|
||||
.server-status-container {
|
||||
margin: 0 0 16px 0;
|
||||
padding: 12px;
|
||||
background: linear-gradient(135deg, #2a4a2a, #1a3a1a);
|
||||
border: 2px solid #44aa44;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.server-status-container h3 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 1.1rem;
|
||||
color: #aaffaa;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.status-dot.status-up {
|
||||
background-color: #44ff44;
|
||||
box-shadow: 0 0 8px rgba(68, 255, 68, 0.6);
|
||||
animation: status-pulse-up 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.status-dot.status-down {
|
||||
background-color: #ff4444;
|
||||
box-shadow: 0 0 8px rgba(255, 68, 68, 0.6);
|
||||
animation: status-pulse-down 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.status-dot.status-unknown,
|
||||
.status-dot.status-error {
|
||||
background-color: #ffaa44;
|
||||
box-shadow: 0 0 8px rgba(255, 170, 68, 0.6);
|
||||
}
|
||||
|
||||
@keyframes status-pulse-up {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 8px rgba(68, 255, 68, 0.6);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 16px rgba(68, 255, 68, 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes status-pulse-down {
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 8px rgba(255, 68, 68, 0.6);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 16px rgba(255, 68, 68, 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.status-details {
|
||||
font-size: 0.85rem;
|
||||
color: #ccc;
|
||||
line-height: 1.6;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px 16px;
|
||||
}
|
||||
|
||||
.status-details div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.status-details span {
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.total-kills-counter {
|
||||
margin: 0 0 12px 0;
|
||||
padding: 8px 12px;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue