42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
|
|
import type { Client } from 'ssh2'
|
||
|
|
import { execCommand } from './common.js'
|
||
|
|
|
||
|
|
export async function collectNetworkMetrics(
|
||
|
|
client: Client,
|
||
|
|
): Promise<{ interfaces: Array<{ name: string; ip: string; state: string }> }> {
|
||
|
|
const interfaces: Array<{ name: string; ip: string; state: string }> = []
|
||
|
|
|
||
|
|
try {
|
||
|
|
const [addrOut, linkOut] = await Promise.all([
|
||
|
|
execCommand(client, "ip -o addr show | awk '{print $2,$4}' | grep -v '^lo'"),
|
||
|
|
execCommand(client, "ip -o link show | awk '{gsub(/:/,\"\",$2); print $2,$9}'"),
|
||
|
|
])
|
||
|
|
|
||
|
|
const ipByIface = new Map<string, string>()
|
||
|
|
for (const line of addrOut.stdout.split('\n')) {
|
||
|
|
const [iface, addr] = line.trim().split(/\s+/)
|
||
|
|
if (iface && addr) ipByIface.set(iface, addr)
|
||
|
|
}
|
||
|
|
|
||
|
|
const stateByIface = new Map<string, string>()
|
||
|
|
for (const line of linkOut.stdout.split('\n')) {
|
||
|
|
const [iface, state] = line.trim().split(/\s+/)
|
||
|
|
if (iface) stateByIface.set(iface, state ?? 'UNKNOWN')
|
||
|
|
}
|
||
|
|
|
||
|
|
const names = new Set([...ipByIface.keys(), ...stateByIface.keys()])
|
||
|
|
for (const name of names) {
|
||
|
|
if (name === 'lo' || !name) continue
|
||
|
|
interfaces.push({
|
||
|
|
name,
|
||
|
|
ip: ipByIface.get(name) ?? '',
|
||
|
|
state: stateByIface.get(name) ?? 'UNKNOWN',
|
||
|
|
})
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
// best-effort
|
||
|
|
}
|
||
|
|
|
||
|
|
return { interfaces }
|
||
|
|
}
|