collabSupport/services/voiceDiag/checks/wan/wanLatency.js
jmcqueen b802383441 Add Prisma SD-WAN voice-quality enrichment for /phonestatus + /voicediag
Introduces a full Palo Alto Prisma SD-WAN integration (dual-mode SASE
OAuth 2.0 / legacy CloudGenix auth, pagination, 429 backoff, session
priming) that surfaces per-path latency/jitter/loss/MOS, site
healthscore, link state, and alarm data for a store. Wired into the
/phonestatus WAN follow-up and eight new /voicediag WAN checks graded
against ITU-T G.114 / RFC 3550 defaults (env-overridable via
WAN_STANDARD_*).

Also adds a shape-aware detail renderer for /voicediag (per-link
tables with verdict icons instead of a stringified JSON dump) and a
--window flag (15m / 1h / 6h / 24h / 1d, env default via
WAN_STANDARD_WINDOW_MINUTES) so operators can widen the look-back
without redeploying. scripts/prismaProbe.js is bundled as a CLI for
schema iteration against a live tenant.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-09 09:45:29 -04:00

58 lines
1.8 KiB
JavaScript

// 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`,
});
},
};