in packages/rum-core/src/performance-monitoring/metrics/metrics.js [224:307]
export function captureObserverEntries(list, { isHardNavigation, trStart }) {
const longtaskEntries = list.getEntriesByType(LONG_TASK).filter(entry => {
return entry.startTime >= trStart
})
const longTaskSpans = createLongTaskSpans(longtaskEntries, metrics.longtask)
const result = {
spans: longTaskSpans,
marks: {}
}
/**
* Web vitals including CLS, FID, LCP and other paint metrics are only
* available for hard navigation
*/
if (!isHardNavigation) {
return result
}
/**
* Largest Contentful Paint is a draft spec and its not W3C standard yet
* Spec - https://wicg.github.io/largest-contentful-paint/
*/
const lcpEntries = list.getEntriesByType(LARGEST_CONTENTFUL_PAINT)
/**
* There can be multiple LCP present on a single page load,
* We need to always use the last one which takes all the lazy loaded
* elements in to account
*/
const lastLcpEntry = lcpEntries[lcpEntries.length - 1]
if (lastLcpEntry) {
/**
* `startTime` - equals to renderTime if it's nonzero, otherwise equal to loadTime.
* `renderTime` will not be available for Image element and for the element
* that is loaded cross-origin without the `Timing-Allow-Origin` header.
*/
const lcp = parseInt(lastLcpEntry.startTime)
metrics.lcp = lcp
result.marks.largestContentfulPaint = lcp
}
/**
* Paint Timing API
* First Contentful Paint is available only during Page load
* SPEC - https://www.w3.org/TR/paint-timing/
*/
const timing = PERF.timing
/**
*
* To avoid capturing the unload event handler effect
* as part of the page-load transaction duration
*/
let unloadDiff = timing.fetchStart - timing.navigationStart
if (isRedirectInfoAvailable(timing)) {
// this makes sure the FCP startTime includes the redirect time
// otherwise the mark would not show up properly in the UI waterfall
unloadDiff = 0
}
const fcpEntry = list.getEntriesByName(FIRST_CONTENTFUL_PAINT)[0]
if (fcpEntry) {
const fcp = parseInt(
unloadDiff >= 0 ? fcpEntry.startTime - unloadDiff : fcpEntry.startTime
)
metrics.fcp = fcp
result.marks.firstContentfulPaint = fcp
}
/**
* Capture First Input Delay (FID) as span
*/
const fidEntries = list.getEntriesByType(FIRST_INPUT)
const fidSpan = createFirstInputDelaySpan(fidEntries)
if (fidSpan) {
metrics.fid = fidSpan.duration()
result.spans.push(fidSpan)
}
calculateTotalBlockingTime(longtaskEntries)
const clsEntries = list.getEntriesByType(LAYOUT_SHIFT)
calculateCumulativeLayoutShift(clsEntries)
return result
}