Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { roundDiv } from "./math_round_div.ts"; ← from math.round-div ^1.0.0 · built alongside by fune
import { percentile } from "./stats_percentile.ts"; ← from stats.percentile ^2.0.0 · built alongside by fune
import { type LatencySummary } from "./net_latency_summary_types.ts";
/**
* Summarise a run of probes the way ping does, in whole microseconds.
*
* Integer microseconds rather than float milliseconds, so every language
* gives the same answer and a vector can compare exactly. A lost probe counts
* towards loss and is skipped (not a break) when measuring jitter.
*/
export function summariseLatency(samplesUs: readonly (number | null)[]): LatencySummary {
if (!Array.isArray(samplesUs)) throw new TypeError("samplesUs must be a list");
if (samplesUs.length === 0) throw new RangeError("samplesUs must not be empty");
const got: number[] = [];
for (const s of samplesUs) {
if (s === null || s === undefined) continue;
if (typeof s !== "number" || !Number.isInteger(s)) {
throw new TypeError(`each sample must be a whole number of microseconds or null, received ${s}`);
}
if (s < 0) throw new RangeError(`samples must not be negative, received ${s}`);
got.push(s);
}
const sent = samplesUs.length;
const received = got.length;
const lost = sent - received;
const lossBasisPoints = roundDiv(lost * 10000, sent, "half-up");
if (received === 0) {
return { sent, received, lost, lossBasisPoints, minUs: null, avgUs: null, maxUs: null, p95Us: null, jitterUs: null };
}
let min = got[0];
let max = got[0];
let sum = 0;
for (const v of got) {
if (v < min) min = v;
if (v > max) max = v;
sum += v;
}
let jitterUs: number | null = null;
if (received >= 2) {
let diffs = 0;
for (let i = 1; i < received; i++) diffs += Math.abs(got[i] - got[i - 1]);
jitterUs = roundDiv(diffs, received - 1, "half-up");
}
// Nearest-rank returns a sample that was really seen, so it is a whole number.
const p95Us = percentile(got, 95, "nearest-rank", 0);
return {
sent,
received,
lost,
lossBasisPoints,
minUs: min,
avgUs: roundDiv(sum, received, "half-up"),
maxUs: max,
p95Us,
jitterUs,
};
}