// src/services/voiceDiag/checks/wan/wanLatency.js // // Per-path WAN latency (LQM one-way average, milliseconds) vs // ITU-T G.114 references: // - <= 150ms : good (no perceptible degradation) // - 150-400ms : warn (audible echo/lag, still usable) // - > 400ms : error (voice becomes duplex-half, users stop // talking over each other and start waiting) // // Both thresholds are env-configurable via WAN_STANDARD_LATENCY_* // (see .env.example). Worst path drives severity — a single bad // path takes precedence over three good ones because that's the // one your voice ticket is routed over. import { maybeSkippedByKillSwitch, getLinks, getLatencyWarnMs, getLatencyErrorMs, evaluatePerLinkMetric, } from './_helpers.js'; // Standards frozen as a plain constant so the README standards // table + regression guards can read it without invoking the // accessors. Same values as `getLatencyWarnMs()` / `getLatencyErrorMs()` // unless the operator overrode via env. export const WAN_LATENCY_STANDARDS = Object.freeze({ maxWarnMs: 150, maxErrorMs: 400, unit: 'ms', reference: 'ITU-T G.114', }); export const wanLatencyCheck = { id: 'wanLatency', label: 'SD-WAN Latency (per path)', requires: ['sdwanSite'], scope: null, standards: WAN_LATENCY_STANDARDS, async run(ctx) { const skip = maybeSkippedByKillSwitch(wanLatencyCheck); if (skip) return skip; const warnThresh = getLatencyWarnMs(); const errorThresh = getLatencyErrorMs(); return evaluatePerLinkMetric({ links: getLinks(ctx), metricKey: 'latencyMs', label: 'latency', unit: 'ms', warnThresh, errorThresh, lowIsBad: false, standardLabel: `warn > ${warnThresh}ms, error > ${errorThresh}ms`, }); }, };