feat(ui): show host status, simplex and absent protocols
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uc9V1v7iXruubpoLiSE24M
This commit is contained in:
@@ -73,6 +73,7 @@
|
||||
.tipbox .up { color: var(--st-ok); font-weight: 700; }
|
||||
.tipbox .dn { color: var(--st-crit); font-weight: 700; }
|
||||
.tipbox .ov { color: var(--st-warn); font-weight: 700; }
|
||||
.tipbox .ab { color: var(--st-faint); font-weight: 700; }
|
||||
.tipbox .meta { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--st-line-soft); font-size: 11px; color: var(--st-faint); }
|
||||
|
||||
@media (max-width: 760px) {
|
||||
@@ -134,18 +135,18 @@
|
||||
function worstConnection(data) {
|
||||
var worst = null;
|
||||
(data.connections || []).forEach(function (c) {
|
||||
if (!c.state || c.state === 'unknown') return;
|
||||
if (!c.state || c.state === 'unknown' || c.state === 'absent') return;
|
||||
if (!worst || (STATE_RANK[c.state] || 0) > (STATE_RANK[worst.state] || 0)) worst = c;
|
||||
});
|
||||
return worst;
|
||||
}
|
||||
|
||||
function severity(data) {
|
||||
var w = worstConnection(data);
|
||||
var st = data.status;
|
||||
if ((data.alert_critical_unacked || 0) > 0 || (data.alert_critical_acked || 0) > 0) return 'crit';
|
||||
if (w && w.state === 'down') return 'crit';
|
||||
if (st === 'down') return 'crit';
|
||||
if ((data.alert_warning_unacked || 0) > 0 || (data.alert_warning_acked || 0) > 0) return 'warn';
|
||||
if (w && w.state === 'overdue') return 'warn';
|
||||
if (st === 'overdue') return 'warn';
|
||||
return 'ok';
|
||||
}
|
||||
var SEV_ORDER = { crit: 0, warn: 1, ok: 2 };
|
||||
@@ -171,17 +172,17 @@
|
||||
|
||||
// ---- host row rendering ---------------------------------------------
|
||||
function statusChip(data) {
|
||||
var w = worstConnection(data);
|
||||
if (!w) return '<span class="chip outline">—</span>';
|
||||
var cls = w.state === 'up' ? 'ok' : (w.state === 'down' ? 'crit' : 'warn');
|
||||
return '<span class="chip ' + cls + '">' + escHtml(w.state) + '</span>';
|
||||
var st = data.status;
|
||||
if (!st || st === 'unknown') return '<span class="chip outline">—</span>';
|
||||
var cls = (st === 'up' || st === 'simplex') ? 'ok' : (st === 'down' ? 'crit' : 'warn');
|
||||
return '<span class="chip ' + cls + '">' + escHtml(st) + '</span>';
|
||||
}
|
||||
|
||||
function tipCard(data) {
|
||||
var rows = '';
|
||||
(data.connections || []).forEach(function (c) {
|
||||
if (!c.state || c.state === 'unknown') return;
|
||||
var cls = c.state === 'up' ? 'up' : (c.state === 'down' ? 'dn' : 'ov');
|
||||
var cls = c.state === 'up' ? 'up' : (c.state === 'down' ? 'dn' : (c.state === 'absent' ? 'ab' : 'ov'));
|
||||
var fam = (c.afam || '').replace('IPv', 'v');
|
||||
var rtt = (c.state === 'up' && c.rtts && c.rtts[0]) ? Math.round(c.rtts[0]) + ' ms' : '—';
|
||||
rows += '<tr><td>' + escHtml(fam) + '</td><td>' + escHtml(c.addr || '—') + '</td>'
|
||||
@@ -247,7 +248,9 @@
|
||||
else if (data.hbc_version !== HBD_VERSION) {
|
||||
staleTag = '<span class="stale" title="agent v' + escHtml(String(data.hbc_version)) + ' ≠ server v' + HBD_VERSION + '">v' + escHtml(String(data.hbc_version)) + '</span>';
|
||||
}
|
||||
var dotCls = w ? (w.state === 'up' ? sev : (w.state === 'down' ? 'down' : 'overdue')) : 'off';
|
||||
var st = data.status;
|
||||
var dotCls = (!st || st === 'unknown') ? 'off'
|
||||
: ((st === 'up' || st === 'simplex') ? sev : (st === 'down' ? 'down' : 'overdue'));
|
||||
var flapTag = '';
|
||||
var flapping = data.flapping || [];
|
||||
if (flapping.length) {
|
||||
@@ -286,11 +289,11 @@
|
||||
var total = 0, up = 0, overdue = 0, down = 0;
|
||||
Object.values(hostData).forEach(function (d) {
|
||||
total++;
|
||||
var w = worstConnection(d);
|
||||
if (!w) return;
|
||||
if (w.state === 'up') up++;
|
||||
else if (w.state === 'overdue') overdue++;
|
||||
else if (w.state === 'down') down++;
|
||||
var st = d.status;
|
||||
if (!st || st === 'unknown') return;
|
||||
if (st === 'up' || st === 'simplex') up++;
|
||||
else if (st === 'overdue') overdue++;
|
||||
else if (st === 'down') down++;
|
||||
});
|
||||
var parts = [total + ' hosts', up + ' up'];
|
||||
if (overdue) parts.push(overdue + ' overdue');
|
||||
|
||||
@@ -456,7 +456,7 @@
|
||||
</tr></thead><tbody>`;
|
||||
for (const c of data.connections) {
|
||||
const st = escHtml(c.state || '—');
|
||||
const stCls = c.state === 'up' ? 'status-up' : (c.state ? 'status-down' : '');
|
||||
const stCls = c.state === 'up' ? 'status-up' : (c.state === 'absent' ? '' : (c.state ? 'status-down' : ''));
|
||||
const rtt = (c.state === 'up' && c.rtt) ? Math.round(c.rtt) + ' ms' : '—';
|
||||
const chg = c.statetime ? new Date(c.statetime * 1000).toLocaleString() : '—';
|
||||
const seen = c.lastbeat ? new Date(c.lastbeat * 1000).toLocaleString() : '—';
|
||||
@@ -1143,6 +1143,24 @@
|
||||
function renderNetworkTables(d) {
|
||||
let html = '';
|
||||
|
||||
if (d.connectivity) {
|
||||
let t = '<table class="data-table"><thead><tr><th>Protocol</th><th>Internet</th>'
|
||||
+ '<th>Address</th><th>Gateway</th><th class="num">RTT</th></tr></thead><tbody>';
|
||||
for (const fam of ['ipv4', 'ipv6']) {
|
||||
const c = d.connectivity[fam];
|
||||
if (!c) continue;
|
||||
const known = c.present === true || c.present === false;
|
||||
const cls = c.present === true ? 'status-up' : '';
|
||||
const txt = c.present === true ? '✓ present' : (c.present === false ? 'absent' : '?');
|
||||
t += `<tr><td>${fam === 'ipv4' ? 'IPv4' : 'IPv6'}</td>
|
||||
<td class="${cls}">${txt}</td>
|
||||
<td>${escHtml(c.addr || '—')}</td><td>${escHtml(c.gateway || '—')}</td>
|
||||
<td class="num">${known && c.rtt != null ? Math.round(c.rtt) + ' ms' : '—'}</td></tr>`;
|
||||
}
|
||||
t += '</tbody></table>';
|
||||
html += `<div class="table-section-label">Connectivity</div>${t}`;
|
||||
}
|
||||
|
||||
if (d.interfaces && Object.keys(d.interfaces).length) {
|
||||
const sample = Object.values(d.interfaces)[0];
|
||||
const hasDelta = 'bytes_sent_delta' in sample;
|
||||
|
||||
Reference in New Issue
Block a user