diff --git a/dDashboardServer/routes/ServerRoutes.cpp b/dDashboardServer/routes/ServerRoutes.cpp index f466cd4f3..3fb974130 100644 --- a/dDashboardServer/routes/ServerRoutes.cpp +++ b/dDashboardServer/routes/ServerRoutes.cpp @@ -81,6 +81,12 @@ namespace { pid = ServerState::g_UgcPid; } out["pid"] = pid; + // Up since its process started when this machine runs it (the dashboard may have started after it) + if (pid && out.value("online", false)) { + for (const auto& process : ServerRoutes::Processes()) { + if (process.pid == pid && process.startedAt) out["since"] = process.startedAt; + } + } // Its traffic report (every few seconds, via master) carries its workers, totals and storage const auto traffic = Traffic::Server("ugc"); out["gauges"] = traffic.value("gauges", nlohmann::json::object()); diff --git a/dDashboardServer/static/js/common.js b/dDashboardServer/static/js/common.js index fc1010be2..506088330 100644 --- a/dDashboardServer/static/js/common.js +++ b/dDashboardServer/static/js/common.js @@ -123,6 +123,21 @@ // Formatting helpers used by table renderers window.fmt = { unix: function (ts) { return ts ? new Date(ts * 1000).toLocaleString() : '-'; }, + // 1536 -> "1.5 KB" + bytes: function (n) { + n = Number(n) || 0; + var units = ['B', 'KB', 'MB', 'GB', 'TB'], i = 0; + while (n >= 1024 && i < units.length - 1) { n /= 1024; i++; } + return (i === 0 ? n : n.toFixed(n < 10 ? 1 : 0)) + ' ' + units[i]; + }, + // Seconds -> "3d 4h", "2h 5m", "7m", "12s" + duration: function (s) { + s = Math.max(0, Math.floor(Number(s) || 0)); + var d = Math.floor(s / 86400), h = Math.floor(s % 86400 / 3600), m = Math.floor(s % 3600 / 60); + if (d) return d + 'd ' + h + 'h'; + if (h) return h + 'h ' + m + 'm'; + return m ? m + 'm' : s + 's'; + }, date: function (s) { if (!s) return '-'; var d = new Date(String(s).replace(' ', 'T') + (String(s).indexOf('Z') === -1 && String(s).indexOf('T') === -1 ? 'Z' : '')); diff --git a/dDashboardServer/templates/health.jinja2 b/dDashboardServer/templates/health.jinja2 index 56bee6bfb..5e723b6ac 100644 --- a/dDashboardServer/templates/health.jinja2 +++ b/dDashboardServer/templates/health.jinja2 @@ -31,7 +31,12 @@
Loading…
Red means the server was not connected when the sample was taken.
'; @@ -109,7 +119,8 @@ var c = d.current; document.getElementById('healthNow').innerHTML = [ ['Players online', nf.format(c.players)], ['Worlds running', nf.format(c.worlds)], - ['Auth / chat', (c.auth ? 'up' : 'DOWN') + ' / ' + (c.chat ? 'up' : 'DOWN')], ['Memory', c.memory_kb ? size(c.memory_kb) : 'n/a'] + [c.ugc_enabled ? 'Auth / chat / UGC' : 'Auth / chat', [c.auth, c.chat].concat(c.ugc_enabled ? [c.ugc] : []).map(function (up) { return up ? 'up' : 'DOWN'; }).join(' / ')], + ['Memory', c.memory_kb ? size(c.memory_kb) : 'n/a'] ].map(function (s) { return '' + esc(d.error) + '
'; return; } + var now = Date.now() / 1000; + var details = function (s) { + var g = (s.traffic && s.traffic.gauges) || {}, parts = []; + if (s.players !== undefined) parts.push(nf.format(s.players) + ' player' + (s.players === 1 ? '' : 's')); + if (s.traffic && s.traffic.connections) parts.push(nf.format(s.traffic.connections) + ' connection' + (s.traffic.connections === 1 ? '' : 's') + (s.traffic.ping_ms ? ', ' + s.traffic.ping_ms + ' ms' : '')); + if (g.workers_threads !== undefined) parts.push('workers ' + g.workers_busy + '/' + g.workers_threads + (g.workers_queued ? ', ' + g.workers_queued + ' queued' : '')); + if (s.key === 'ugc') { + var c = d.ugc.counts || { model: {}, modular: {} }; + var sum = function (state) { return (c.model[state] || 0) + (c.modular[state] || 0); }; + parts.push(nf.format(sum('pending')) + ' waiting, ' + nf.format(sum('done')) + ' made, ' + nf.format(sum('failed')) + ' failed'); + if (g.ugc_stored_bytes !== undefined) parts.push(fmt.bytes(g.ugc_stored_bytes) + (g.ugc_max_storage_bytes ? ' of ' + fmt.bytes(g.ugc_max_storage_bytes) : '') + ' stored'); + } + return esc(parts.join(' ยท ')); + }; + box.innerHTML = '| Server | Status | Up for | PID | Memory | CPU | Details |
|---|---|---|---|---|---|---|
| ' + label + ' | ' + (s.kind === 'OTHER' ? fmt.badge('Not listed', 'secondary') : fmt.badge(s.online ? 'Online' : 'Offline', s.online ? 'success' : 'danger')) + ' | ' + + '' + ((s.online || s.kind === 'OTHER') && started ? esc(fmt.duration(now - started)) : '-') + ' | ' + + '' + (p ? esc(p.pid) : '-') + ' | ' + (p ? esc(size(p.memory_kb)) : '-') + ' | ' + + '' + (p ? esc(p.cpu_percent.toFixed(1) + '%') : '-') + ' | ' + details(s) + ' |
Loading…