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);
}