fix(infrastructure): show the container-namespace notice when it applies
The network tab warns when Capture can only see a container's own network namespace, but the condition required EVERY reported interface to be named lo, lo0 or docker0. A containerised Capture usually also reports the container's veth under a host-looking name (eth0, ens3, ...), so the common case failed that test and the notice never appeared - leaving those users with plausible-but-meaningless traffic and nothing explaining why. Widening it to "any container-only name present" would have been wrong in the other direction: a host-level Capture on a machine running Docker legitimately reports docker0 alongside its real NIC, and would then have been warned incorrectly. Interface names alone cannot separate the two cases. What does is that in the container case nothing carries real traffic, while a genuine host has a busy NIC. The notice now fires when a container-only interface is present AND every interface is idle, using a 1 KB/s threshold - real NICs sit orders of magnitude above it, a container's veth sits at or near zero. Checked against six scenarios: the reported case (lo + ens3 + docker0, all near zero) now warns; a host with a busy NIC plus an idle docker0 does not; a fully namespaced container still warns as before; and a quiet host with no container-only names stays silent. The notice text is updated to match, since it previously described only the all-container-names case and did not explain that a host-looking interface can be the container's own. Claude-Session: https://claude.ai/code/session_01AbYLvwpEaZFXktHVcqrFRd
This commit is contained in:
1 parent
80073af80a
commit
9ffcbd1242
2 files changed
+40
-8
No files matched your search
@@ -63,19 +63,51 @@ const getChartConfigs = (
|
||||
return configs;
|
||||
};
|
||||
|
||||
// Loopback / bridge names Capture sees when it can only observe the container's
|
||||
// own network namespace. When ALL reported interfaces match this set we assume
|
||||
// the "no real interfaces visible" case and surface the notice.
|
||||
// Loopback / bridge names Capture reports when it can only observe the
|
||||
// container's own network namespace.
|
||||
const CONTAINER_ONLY_IFACE_NAMES = new Set(["lo", "lo0", "docker0"]);
|
||||
|
||||
// Below this, an interface is carrying no traffic worth charting. Real host
|
||||
// NICs sit orders of magnitude above it; a container's veth sits at or near
|
||||
// zero.
|
||||
const IDLE_INTERFACE_BYTES_PER_SECOND = 1024;
|
||||
|
||||
const interfaceIsIdle = (checks: HardwareCheckStats[], name: string): boolean =>
|
||||
checks.every((check) => {
|
||||
const iface = check.net?.find((candidate) => candidate.name === name);
|
||||
if (!iface) {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
(iface.bytesSentPerSecond || 0) < IDLE_INTERFACE_BYTES_PER_SECOND &&
|
||||
(iface.deltaBytesRecv || 0) < IDLE_INTERFACE_BYTES_PER_SECOND
|
||||
);
|
||||
});
|
||||
|
||||
// Capture running inside a container sees only that container's network
|
||||
// namespace. It reports the loopback and bridge names above, and usually also
|
||||
// the container's own veth under a host-looking name (eth0, ens3, ...) - so
|
||||
// requiring EVERY interface to be container-only missed the common case, and
|
||||
// those users saw plausible-but-meaningless traffic with no explanation.
|
||||
//
|
||||
// Interface names alone cannot separate the two cases: a host-level agent on a
|
||||
// machine running Docker legitimately reports docker0 too. What distinguishes
|
||||
// them is that in the container case nothing carries real traffic. So the
|
||||
// notice fires when a container-only interface is present AND every interface
|
||||
// is idle, which leaves a genuine host reporting docker0 alongside a busy NIC
|
||||
// untouched.
|
||||
const onlyContainerVisibleInterfaces = (checks: HardwareCheckStats[]): boolean => {
|
||||
const named = new Set<string>();
|
||||
checks.forEach((c) => c.net?.forEach((iface) => named.add(iface.name)));
|
||||
if (named.size === 0) return false;
|
||||
for (const name of named) {
|
||||
if (!CONTAINER_ONLY_IFACE_NAMES.has(name)) return false;
|
||||
if (named.size === 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
const names = [...named];
|
||||
if (!names.some((name) => CONTAINER_ONLY_IFACE_NAMES.has(name))) {
|
||||
return false;
|
||||
}
|
||||
return names.every((name) => interfaceIsIdle(checks, name));
|
||||
};
|
||||
|
||||
export const InfraNetworkCharts = ({
|
||||
|
||||
@@ -926,7 +926,7 @@
|
||||
"memory": "Memory usage",
|
||||
"netBytesRecv": "{{name}} - Bytes Received",
|
||||
"netBytesSent": "{{name}} - Bytes Sent",
|
||||
"loopbackOnlyNotice": "Capture is only reporting loopback or container-bridge interfaces (lo, lo0, docker0). This is normal when Capture runs inside a container that can only see its own network namespace — run Capture directly on the host to see real network activity.",
|
||||
"loopbackOnlyNotice": "Capture is only seeing container network interfaces, and none of them are carrying real traffic. This is normal when Capture runs inside a container that can only observe its own network namespace — interfaces with host-like names (eth0, ens3) are the container's virtual interfaces, not the host's. Run Capture directly on the host to see real network activity.",
|
||||
"temp": "CPU temperature"
|
||||
}
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user