fix(web-probe): expose slow API samples in observe analysis (#644)
Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
@@ -1488,7 +1488,23 @@ function compactPerformanceItems(items) {
|
||||
name: item?.name ?? null,
|
||||
initiatorType: item?.initiatorType ?? null,
|
||||
startTime: item?.startTime ?? null,
|
||||
duration: item?.duration ?? null
|
||||
duration: item?.duration ?? null,
|
||||
workerStart: item?.workerStart ?? null,
|
||||
redirectStart: item?.redirectStart ?? null,
|
||||
redirectEnd: item?.redirectEnd ?? null,
|
||||
fetchStart: item?.fetchStart ?? null,
|
||||
domainLookupStart: item?.domainLookupStart ?? null,
|
||||
domainLookupEnd: item?.domainLookupEnd ?? null,
|
||||
connectStart: item?.connectStart ?? null,
|
||||
connectEnd: item?.connectEnd ?? null,
|
||||
secureConnectionStart: item?.secureConnectionStart ?? null,
|
||||
requestStart: item?.requestStart ?? null,
|
||||
responseStart: item?.responseStart ?? null,
|
||||
responseEnd: item?.responseEnd ?? null,
|
||||
transferSize: item?.transferSize ?? null,
|
||||
encodedBodySize: item?.encodedBodySize ?? null,
|
||||
decodedBodySize: item?.decodedBodySize ?? null,
|
||||
nextHopProtocol: item?.nextHopProtocol ?? null
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1707,10 +1723,12 @@ function buildPagePerformanceReport(samples, manifest) {
|
||||
lastSeq: sample.seq ?? null,
|
||||
initiatorTypes: [],
|
||||
pageAssetFingerprints: [],
|
||||
slowSamples: [],
|
||||
valuesRedacted: true
|
||||
};
|
||||
group.sampleCount += 1;
|
||||
group.durationsMs.push(durationMs);
|
||||
let overBudget = false;
|
||||
if (isLongLivedStream) {
|
||||
if (durationMs > 5000) group.streamLifetimeOverFiveSecondCount += 1;
|
||||
if (streamOpenMs !== null) {
|
||||
@@ -1718,11 +1736,14 @@ function buildPagePerformanceReport(samples, manifest) {
|
||||
if (streamOpenMs > 5000) {
|
||||
group.streamOpenOverFiveSecondCount += 1;
|
||||
group.overFiveSecondCount += 1;
|
||||
overBudget = true;
|
||||
}
|
||||
}
|
||||
} else if (durationMs > 5000) {
|
||||
group.overFiveSecondCount += 1;
|
||||
overBudget = true;
|
||||
}
|
||||
if (overBudget && group.slowSamples.length < 80) group.slowSamples.push(compactPagePerformanceSlowSample({ sample, entry, normalizedPath, rawPath: parsed.path, durationMs, streamOpenMs }));
|
||||
group.lastAt = sample.ts ?? null;
|
||||
group.lastSeq = sample.seq ?? null;
|
||||
if (parsed.path && !group.rawPathSamples.includes(parsed.path)) group.rawPathSamples.push(parsed.path);
|
||||
@@ -1761,6 +1782,10 @@ function buildPagePerformanceReport(samples, manifest) {
|
||||
initiatorTypes: group.initiatorTypes,
|
||||
rawPathSamples: group.rawPathSamples.slice(0, 8),
|
||||
pageAssetFingerprints: group.pageAssetFingerprints.slice(0, 8),
|
||||
slowSamples: group.slowSamples
|
||||
.slice()
|
||||
.sort((a, b) => Number(b.durationMs ?? 0) - Number(a.durationMs ?? 0))
|
||||
.slice(0, 12),
|
||||
valuesRedacted: true
|
||||
};
|
||||
}).sort((a, b) => (b.overFiveSecondCount - a.overFiveSecondCount) || (Number(b.p95Ms ?? 0) - Number(a.p95Ms ?? 0)) || a.path.localeCompare(b.path));
|
||||
@@ -1786,6 +1811,45 @@ function buildPagePerformanceReport(samples, manifest) {
|
||||
};
|
||||
}
|
||||
|
||||
function compactPagePerformanceSlowSample({ sample, entry, normalizedPath, rawPath, durationMs, streamOpenMs }) {
|
||||
return {
|
||||
ts: sample?.ts ?? null,
|
||||
seq: sample?.seq ?? null,
|
||||
path: normalizedPath ?? null,
|
||||
rawPath: rawPath ?? null,
|
||||
initiatorType: entry?.initiatorType ?? null,
|
||||
durationMs: roundFinite(durationMs),
|
||||
startTimeMs: roundFinite(entry?.startTime),
|
||||
fetchStartMs: roundFinite(entry?.fetchStart),
|
||||
requestStartMs: roundFinite(entry?.requestStart),
|
||||
responseStartMs: roundFinite(entry?.responseStart),
|
||||
responseEndMs: roundFinite(entry?.responseEnd),
|
||||
streamOpenMs: roundFinite(streamOpenMs),
|
||||
dnsMs: phaseDeltaMs(entry, "domainLookupEnd", "domainLookupStart"),
|
||||
tcpMs: phaseDeltaMs(entry, "connectEnd", "connectStart"),
|
||||
tlsStartMs: roundFinite(entry?.secureConnectionStart),
|
||||
requestToResponseStartMs: phaseDeltaMs(entry, "responseStart", "requestStart"),
|
||||
responseTransferMs: phaseDeltaMs(entry, "responseEnd", "responseStart"),
|
||||
transferSize: Number.isFinite(Number(entry?.transferSize)) ? Number(entry.transferSize) : null,
|
||||
encodedBodySize: Number.isFinite(Number(entry?.encodedBodySize)) ? Number(entry.encodedBodySize) : null,
|
||||
decodedBodySize: Number.isFinite(Number(entry?.decodedBodySize)) ? Number(entry.decodedBodySize) : null,
|
||||
nextHopProtocol: entry?.nextHopProtocol ?? null,
|
||||
valuesRedacted: true
|
||||
};
|
||||
}
|
||||
|
||||
function phaseDeltaMs(entry, endKey, startKey) {
|
||||
const end = Number(entry?.[endKey]);
|
||||
const start = Number(entry?.[startKey]);
|
||||
if (!Number.isFinite(end) || !Number.isFinite(start) || end <= 0 || start < 0 || end < start) return null;
|
||||
return Math.round(end - start);
|
||||
}
|
||||
|
||||
function roundFinite(value) {
|
||||
const numeric = Number(value);
|
||||
return Number.isFinite(numeric) ? Math.round(numeric) : null;
|
||||
}
|
||||
|
||||
function classifyApiPerformanceRoute(normalizedPath, entry = {}) {
|
||||
if (normalizedPath === "/v1/workbench/events") return "same-origin-api-stream";
|
||||
if (String(entry?.initiatorType ?? "").toLowerCase() === "eventsource") return "same-origin-api-stream";
|
||||
|
||||
Reference in New Issue
Block a user