File size: 1,554 Bytes
dbb1bf9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | export type LcpDebugDetail = Record<string, string | number | boolean | null | undefined>;
export type LcpMarkSnapshot = {
detail?: LcpDebugDetail;
name: string;
startTime: number;
};
const MAX_MARKS = 120;
type LcpDebugMarkTarget = {
enabled?: boolean;
marks?: LcpMarkSnapshot[];
};
export function markLcpDebug(name: string, detail?: LcpDebugDetail): void {
// Opt-in only: when the LCP debug recorder is not installed (the default for
// all production traffic), this is a single property read + early return. We
// deliberately do NOT call performance.mark() unless debug is enabled — an
// unconditional native mark on every boot-path call site would pollute the
// User Timing buffer that RUM/Sentry/analytics read and add main-thread cost
// to the very metric this instrumentation measures (#4512 review).
if (typeof window === 'undefined') return;
const state = (window as unknown as { __wmLcpDebug?: LcpDebugMarkTarget }).__wmLcpDebug;
if (!state?.enabled || !Array.isArray(state.marks)) return;
if (typeof performance !== 'undefined' && typeof performance.mark === 'function') {
try {
performance.mark(name);
} catch {
// A malformed mark name should never break dashboard startup.
}
}
state.marks.push({
detail,
name,
startTime: Math.round(typeof performance !== 'undefined' && typeof performance.now === 'function'
? performance.now()
: Date.now()),
});
if (state.marks.length > MAX_MARKS) state.marks.splice(0, state.marks.length - MAX_MARKS);
}
|