fix(workbench): improve rum resource timing coverage (#1936)

This commit is contained in:
Lyon
2026-06-23 02:11:25 +08:00
committed by GitHub
parent 2b915ddcd7
commit cf8d691c73
@@ -141,6 +141,7 @@ const loadingStates = new Map<WorkbenchLoadingScope, LoadingStateRecord>();
let openJourney: OpenJourneyState | null = null;
let queue: WorkbenchPerformanceEvent[] = [];
let installed = false;
let resourceTimingBufferConfigured = false;
let flushTimer: number | null = null;
let uiTrace: WorkbenchUiTrace | null = null;
@@ -224,9 +225,10 @@ function resourceTimingForApiRequest(route: string, startedAtEpochMs: number, en
const lowerBound = startedAtEpochMs - 2000;
const upperBound = endedAtEpochMs + 2000;
const candidates = entries
.filter((entry) => resourceEntryMatches(entry, target, timeOrigin, lowerBound, upperBound))
.sort((left, right) => Math.abs(timeOrigin + right.startTime - startedAtEpochMs) - Math.abs(timeOrigin + left.startTime - startedAtEpochMs));
const entry = candidates.at(-1);
.map((entry) => resourceTimingCandidate(entry, target, timeOrigin, lowerBound, upperBound, startedAtEpochMs))
.filter((candidate): candidate is ResourceTimingCandidate => candidate !== null)
.sort((left, right) => Number(right.queryExact) - Number(left.queryExact) || left.initiatorRank - right.initiatorRank || left.startDistanceMs - right.startDistanceMs);
const entry = candidates[0]?.entry;
if (!entry) return {};
const result: Partial<WorkbenchPerformanceEvent> = {
resourceDurationMs: roundedNonNegative(entry.duration),
@@ -242,19 +244,39 @@ function resourceTimingForApiRequest(route: string, startedAtEpochMs: number, en
return Object.fromEntries(Object.entries(result).filter(([, value]) => value !== undefined)) as Partial<WorkbenchPerformanceEvent>;
}
function resourceEntryMatches(entry: PerformanceResourceTiming, target: URL, timeOrigin: number, lowerBound: number, upperBound: number): boolean {
if (!entry || entry.initiatorType !== "fetch") return false;
interface ResourceTimingCandidate {
entry: PerformanceResourceTiming;
queryExact: boolean;
initiatorRank: number;
startDistanceMs: number;
}
function resourceTimingCandidate(entry: PerformanceResourceTiming, target: URL, timeOrigin: number, lowerBound: number, upperBound: number, startedAtEpochMs: number): ResourceTimingCandidate | null {
if (!entry) return null;
let url: URL;
try {
url = new URL(entry.name);
} catch {
return false;
return null;
}
if (url.origin !== target.origin) return false;
if (url.pathname !== target.pathname) return false;
if (target.search && url.search !== target.search) return false;
if (url.origin !== target.origin) return null;
if (url.pathname !== target.pathname) return null;
const started = timeOrigin + entry.startTime;
return started >= lowerBound && started <= upperBound;
if (started < lowerBound || started > upperBound) return null;
return {
entry,
queryExact: url.search === target.search,
initiatorRank: resourceInitiatorRank(entry.initiatorType),
startDistanceMs: Math.abs(started - startedAtEpochMs)
};
}
function resourceInitiatorRank(value: string): number {
const initiator = safeText(value).toLowerCase();
if (initiator === "fetch") return 0;
if (initiator === "xmlhttprequest") return 1;
if (!initiator) return 2;
return 3;
}
function roundedDelta(end: number, start: number): number | undefined {
@@ -549,6 +571,7 @@ function enrichWorkbenchEventForFlush(event: WorkbenchPerformanceEvent): Workben
function ensureInstalled(): void {
if (installed || typeof document === "undefined") return;
installed = true;
configureResourceTimingBuffer();
currentWorkbenchUiTrace();
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") {
@@ -562,6 +585,12 @@ function ensureInstalled(): void {
});
}
function configureResourceTimingBuffer(): void {
if (resourceTimingBufferConfigured || typeof performance === "undefined" || typeof performance.setResourceTimingBufferSize !== "function") return;
resourceTimingBufferConfigured = true;
performance.setResourceTimingBufferSize(2000);
}
function afterNextPaint(callback: () => void): void {
if (typeof requestAnimationFrame !== "function") {
callback();