+
API Latency:{" "}
- {geoMetrics.globalAverages.avgApiLatencyMs > 0
- ? `${Math.round(geoMetrics.globalAverages.avgApiLatencyMs)} ms`
+ {geoMetrics.globalAverages.medianApiLatencyMs > 0
+ ? `${Math.round(geoMetrics.globalAverages.medianApiLatencyMs)} ms`
: "No data"}
@@ -464,10 +466,10 @@ export default function GeographicPerformancePage() {
handleSort("avgApiLatencyMs")}
- title="Agent→backend HTTP round-trip measured on the devices — high values indicate network distance to the backend region"
+ onClick={() => handleSort("medianApiLatencyMs")}
+ title="Agent→backend HTTP round-trip measured on the devices (median per location) — high values indicate network distance to the backend region"
>
- API Latency
+ API Latency
|
|
- {loc.avgApiLatencyMs > 0 ? (
- 0 ? "+" : ""}${loc.apiLatencyVsGlobalPct.toFixed(0)}% vs global` : ""}`}>
-
- {Math.round(loc.avgApiLatencyMs)} ms
+ {loc.medianApiLatencyMs > 0 ? (
+ 0 ? "+" : ""}${loc.apiLatencyVsGlobalPct.toFixed(0)}% vs global` : ""}`}>
+
+ {Math.round(loc.medianApiLatencyMs)} ms
({loc.apiLatencySessionCount})
diff --git a/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx b/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx
index 1f177756..67dbbea4 100644
--- a/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx
+++ b/src/Web/autopilot-monitor-web/app/geographic-performance/sessions/page.tsx
@@ -177,13 +177,15 @@ function LocationSessionsContent() {
.map((s) => s.durationSeconds!);
return durations.length > 0 ? Math.round(durations.reduce((a, b) => a + b, 0) / durations.length / 60) : 0;
})(),
- // Request-weighted API latency across sessions with latency data (matches region aggregate formula)
+ // Median API latency across sessions with latency data (matches region aggregate: robust
+ // against a single corrupt session average, unlike the request-weighted mean)
latencySessions: data.sessions.filter((s) => (s.avgApiLatencyMs ?? 0) > 0 && (s.apiRequestCount ?? 0) > 0).length,
- avgApiLatency: (() => {
- const withLatency = data.sessions.filter((s) => (s.avgApiLatencyMs ?? 0) > 0 && (s.apiRequestCount ?? 0) > 0);
- const totalRequests = withLatency.reduce((a, s) => a + s.apiRequestCount!, 0);
- const weightedSum = withLatency.reduce((a, s) => a + s.avgApiLatencyMs! * s.apiRequestCount!, 0);
- return totalRequests > 0 ? Math.round(weightedSum / totalRequests) : 0;
+ medianApiLatency: (() => {
+ const sorted = data.sessions
+ .filter((s) => (s.avgApiLatencyMs ?? 0) > 0 && (s.apiRequestCount ?? 0) > 0)
+ .map((s) => s.avgApiLatencyMs!)
+ .sort((a, b) => a - b);
+ return sorted.length > 0 ? Math.round(sorted[Math.floor(sorted.length / 2)]) : 0;
})(),
// Weighted peer-caching % across sessions with DO telemetry (matches region aggregate formula)
doSessions: data.sessions.filter((s) => s.hasDoTelemetry).length,
@@ -254,10 +256,10 @@ function LocationSessionsContent() {
Sessions
{stats.total}
-
+
API Latency
- 0 ? "text-gray-900" : "text-gray-400"}`}>
- {stats.avgApiLatency > 0 ? `${stats.avgApiLatency} ms` : "—"}
+ 0 ? "text-gray-900" : "text-gray-400"}`}>
+ {stats.medianApiLatency > 0 ? `${stats.medianApiLatency} ms` : "—"}
{stats.latencySessions > 0 ? `${stats.latencySessions} session(s) with data` : "requires latency-reporting agent"}
|