diff --git a/static/index.html b/static/index.html index 49f3ae3..655d263 100644 --- a/static/index.html +++ b/static/index.html @@ -137,6 +137,23 @@ color: #f99; } + .node .switch-port .error-info, + .node .uplink .error-info { + display: none; + font-size: 8px; + opacity: 0.8; + } + + .node .switch-port:hover .error-info, + .node .uplink:hover .error-info { + display: block; + } + + .node .switch-port:hover, + .node .uplink:hover { + z-index: 100; + } + .node .uplink { position: absolute; top: -8px; @@ -678,6 +695,16 @@ return iface.stats?.speed || 0; } + function getInterfaceErrors(node) { + if (!node.interfaces || node.interfaces.length === 0) return null; + const iface = node.interfaces[0]; + if (!iface.stats) return null; + const inErr = iface.stats.in_errors || 0; + const outErr = iface.stats.out_errors || 0; + if (inErr === 0 && outErr === 0) return null; + return { in: inErr, out: outErr }; + } + let anonCounter = 0; function buildLocationTree(locations, parent) { @@ -773,6 +800,12 @@ } const speedClass = getSpeedClass(switchConnection.speed); if (speedClass) portEl.classList.add(speedClass); + const errIn = switchConnection.errors?.in || 0; + const errOut = switchConnection.errors?.out || 0; + const errInfo = document.createElement('div'); + errInfo.className = 'error-info'; + errInfo.textContent = 'err: ' + errIn + '/' + errOut; + portEl.appendChild(errInfo); div.appendChild(portEl); } @@ -791,6 +824,12 @@ uplinkEl.textContent = uplinkInfo.localPort + ' → ' + uplinkInfo.parentName + ':' + uplinkInfo.remotePort; const speedClass = getSpeedClass(uplinkInfo.speed); if (speedClass) uplinkEl.classList.add(speedClass); + const errIn = uplinkInfo.errors?.in || 0; + const errOut = uplinkInfo.errors?.out || 0; + const errInfo = document.createElement('div'); + errInfo.className = 'error-info'; + errInfo.textContent = 'err: ' + errIn + '/' + errOut; + uplinkEl.appendChild(errInfo); div.appendChild(uplinkEl); } @@ -1050,7 +1089,9 @@ portA: link.interface_a || '?', portB: link.interface_b || '?', speedA: getInterfaceSpeed(link.node_a), - speedB: getInterfaceSpeed(link.node_b) + speedB: getInterfaceSpeed(link.node_b), + errorsA: getInterfaceErrors(link.node_a), + errorsB: getInterfaceErrors(link.node_b) }); } else if (aIsSwitch && !bIsSwitch) { const nodeLoc = nodeLocations.get(nodeB.typeid); @@ -1059,7 +1100,8 @@ port: link.interface_a || '?', switchName: getLabel(nodeA), external: !effectiveSwitch || effectiveSwitch.typeid !== nodeA.typeid, - speed: getInterfaceSpeed(link.node_a) + speed: getInterfaceSpeed(link.node_a), + errors: getInterfaceErrors(link.node_a) }); } else if (bIsSwitch && !aIsSwitch) { const nodeLoc = nodeLocations.get(nodeA.typeid); @@ -1068,7 +1110,8 @@ port: link.interface_b || '?', switchName: getLabel(nodeB), external: !effectiveSwitch || effectiveSwitch.typeid !== nodeB.typeid, - speed: getInterfaceSpeed(link.node_b) + speed: getInterfaceSpeed(link.node_b), + errors: getInterfaceErrors(link.node_b) }); } }); @@ -1123,13 +1166,15 @@ neighbor: link.switchB, localPort: link.portA, remotePort: link.portB, - localSpeed: link.speedA + localSpeed: link.speedA, + localErrors: link.errorsA }); adjacency.get(link.switchB.typeid).push({ neighbor: link.switchA, localPort: link.portB, remotePort: link.portA, - localSpeed: link.speedB + localSpeed: link.speedB, + localErrors: link.errorsB }); }); @@ -1183,7 +1228,8 @@ localPort: edge.localPort, remotePort: edge.remotePort, parentName: getLabel(current), - speed: edge.localSpeed + speed: edge.localSpeed, + errors: edge.localErrors }); queue.push(edge.neighbor); }