fix(traffic): проверять live-срез и прекращать опрос выключенных устройств
This commit is contained in:
1 parent
1275dd7b9b
commit
2358ecef60
29 files changed
+1620
-114
No files matched your search
@@ -42,6 +42,7 @@ export interface MonitorLiveSample {
|
||||
rxMbps: number
|
||||
txMbps: number
|
||||
at: string
|
||||
timestampKind: "backend-receipt"
|
||||
}
|
||||
|
||||
export function isLoopbackName(name: string): boolean {
|
||||
@@ -61,7 +62,7 @@ export function shouldIncludeIface(
|
||||
|
||||
export function bpsToMbps(bps: number): number {
|
||||
if (!Number.isFinite(bps) || bps <= 0) return 0
|
||||
return Math.round((bps / 1_000_000) * 1000) / 1000
|
||||
return bps / 1_000_000
|
||||
}
|
||||
|
||||
/** bits/s из соседних счётчиков. null = нельзя (Δt≤0 или сброс). */
|
||||
@@ -75,7 +76,7 @@ export function rateBpsFromDelta(
|
||||
const dtSec = (nextAtMs - prevAtMs) / 1000
|
||||
if (!(dtSec > 0) || !Number.isFinite(dtSec)) return null
|
||||
if (nextBytes < prevBytes) return null
|
||||
const rate=Math.round(((nextBytes - prevBytes) * 8) / dtSec)
|
||||
const rate=((nextBytes - prevBytes) * 8) / dtSec
|
||||
return Number.isFinite(rate)?rate:null
|
||||
}
|
||||
|
||||
@@ -274,26 +275,41 @@ export function mergeBuiltTraffic(parts: BuiltTrafficSeries[]): BuiltTrafficSeri
|
||||
|
||||
export function parseMonitorTraffic(
|
||||
raw: unknown,
|
||||
opts?: { onlyInterface?: string },
|
||||
opts?: { onlyInterface?: string; expectedInterfaces?: readonly string[] },
|
||||
): MonitorLiveSample {
|
||||
const items = Array.isArray(raw) ? raw : raw != null ? [raw] : []
|
||||
let rxBps = 0
|
||||
let txBps = 0
|
||||
const seen = new Set<string>()
|
||||
const expected = opts?.expectedInterfaces ? new Set(opts.expectedInterfaces) : null
|
||||
const rate = (raw: unknown) => {
|
||||
if (typeof raw !== "number" && (typeof raw !== "string" || !/^(?:\d+(?:\.\d+)?|\.\d+)$/.test(raw.trim()))) throw new Error("Некорректная скорость monitor-traffic")
|
||||
const n = Number(raw)
|
||||
if (!Number.isFinite(n) || n < 0 || n > Number.MAX_SAFE_INTEGER) throw new Error("Некорректная скорость monitor-traffic")
|
||||
return n
|
||||
}
|
||||
for (const item of items) {
|
||||
if (!item || typeof item !== "object") continue
|
||||
if (!item || typeof item !== "object" || Array.isArray(item)) throw new Error("Некорректный ответ monitor-traffic")
|
||||
const rec = item as Record<string, unknown>
|
||||
const name = String(rec.name ?? rec.interface ?? "")
|
||||
const name = rec.name ?? rec.interface
|
||||
if (typeof name !== "string" || !name.trim()) throw new Error("Не указан интерфейс monitor-traffic")
|
||||
if (opts?.onlyInterface) {
|
||||
if (name && name !== opts.onlyInterface) continue
|
||||
if (name !== opts.onlyInterface) throw new Error("Ответ monitor-traffic относится к другому интерфейсу")
|
||||
} else if (isLoopbackName(name)) {
|
||||
continue
|
||||
}
|
||||
rxBps += Number.parseFloat(String(rec["rx-bits-per-second"] ?? 0)) || 0
|
||||
txBps += Number.parseFloat(String(rec["tx-bits-per-second"] ?? 0)) || 0
|
||||
if (seen.has(name) || expected && !expected.has(name)) throw new Error("Некорректный набор интерфейсов monitor-traffic")
|
||||
seen.add(name)
|
||||
rxBps += rate(rec["rx-bits-per-second"])
|
||||
txBps += rate(rec["tx-bits-per-second"])
|
||||
}
|
||||
if (!seen.size || expected && (expected.size !== opts!.expectedInterfaces!.length ||
|
||||
[...expected].some(name => !seen.has(name)))) throw new Error("Не получены все live-измерения интерфейсов")
|
||||
if (![rxBps, txBps].every(n => Number.isFinite(n) && n <= Number.MAX_SAFE_INTEGER)) throw new Error("Суммарная live-скорость вне допустимого диапазона")
|
||||
return {
|
||||
rxMbps: bpsToMbps(rxBps),
|
||||
txMbps: bpsToMbps(txBps),
|
||||
rxMbps: rxBps / 1_000_000,
|
||||
txMbps: txBps / 1_000_000,
|
||||
at: new Date().toISOString(),
|
||||
timestampKind: "backend-receipt",
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user