sentry-javascript
sentry-javascript copied to clipboard
feat(browser): Add ElementTiming instrumentation and spans
This PR adds support for instrumenting and sending spans from ElementTiming API entries. Just like with web vitals and long tasks/animation frames, we register a PerformanceObserver and extract spans from newly emitted ET entries.
Important:
- We'll by default emit ET spans. Users can opt out by setting
enableElementTiming: falseinbrowserTracingIntegration - We for now only emit an ET span, if there is an active parent span. Happy to adjust this but considering the limitations from below I'm not sure if we actually want all spans after the pageload span. For now, we'll also emit spans on other transactions that pageload (most prominently
navigationspans as well). We could also go the route of only sending until the first navigation as with standalone CLS/LCP spans. Happy to accept any direction we wanna take this.
Some noteworthy findings while working on this:
- ET is only emitted for text and image nodes.
- For image nodes, we get the
loadTimewhich is the relative timestamp to the browser'stimeOrigin, when the image finished loading. For text nodes,loadTimeis always0, since nothing needs to be loaded. - For all nodes, we get
renderTimewhich is the relative timestamp to the browser'stimeOrigin, when the node finished rendering (i.e. was painted by the browser). - In any case, we do not get start times for rendering or loading. Consequently, the span duration is
-
renderTime - loadTimefor image nodes -
0for text nodes
-
- The span start time is:
-
timeOrigin + loadTimefor image nodes -
timeOrigin + renderTimefor text nodes
-
In addition to the raw span and conventional attributes, we also collect a bunch of ET-specific attributes:
-
element.type- tag name of the element (e.g.imgorp) -
element.size- width x height of the element -
element.render-time-entry.renderTime -
element.load-time-entry.loadTime -
element.url- url of the loaded image (undefinedfor text nodes) -
element.identifier- the identifier passed to theelementtiming=identifierHTML attribute -
element.paint-type- the node paint type (image-paintortext-paint)
also some additional sentry-sepcific attributes:
-
route- the route name, either from the active root span (if available) or from the scope'stransactionName -
sentry.span-start-time-source- the data point we used as the span start time
More than happy to adjust any of this logic or attribute names, based on review feedback :)
closes #13675 also ref https://github.com/getsentry/sentry-javascript/issues/7292
size-limit report 📦
| Path | Size | % Change | Change |
|---|---|---|---|
| @sentry/browser | 23.99 kB | - | - |
| @sentry/browser - with treeshaking flags | 23.76 kB | - | - |
| @sentry/browser (incl. Tracing) | 39.59 kB | +1.41% | +547 B 🔺 |
| @sentry/browser (incl. Tracing, Replay) | 77.69 kB | +0.68% | +522 B 🔺 |
| @sentry/browser (incl. Tracing, Replay) - with treeshaking flags | 70.78 kB | +0.74% | +513 B 🔺 |
| @sentry/browser (incl. Tracing, Replay with Canvas) | 82.45 kB | +0.63% | +510 B 🔺 |
| @sentry/browser (incl. Tracing, Replay, Feedback) | 94.57 kB | +0.57% | +535 B 🔺 |
| @sentry/browser (incl. Feedback) | 40.75 kB | - | - |
| @sentry/browser (incl. sendFeedback) | 28.7 kB | - | - |
| @sentry/browser (incl. FeedbackAsync) | 33.59 kB | - | - |
| @sentry/react | 25.76 kB | - | - |
| @sentry/react (incl. Tracing) | 41.58 kB | +1.4% | +574 B 🔺 |
| @sentry/vue | 28.37 kB | - | - |
| @sentry/vue (incl. Tracing) | 41.4 kB | +1.3% | +530 B 🔺 |
| @sentry/svelte | 24.01 kB | - | - |
| CDN Bundle | 25.5 kB | - | - |
| CDN Bundle (incl. Tracing) | 39.6 kB | +1.23% | +479 B 🔺 |
| CDN Bundle (incl. Tracing, Replay) | 75.5 kB | +0.64% | +479 B 🔺 |
| CDN Bundle (incl. Tracing, Replay, Feedback) | 80.96 kB | +0.61% | +490 B 🔺 |
| CDN Bundle - uncompressed | 74.5 kB | - | - |
| CDN Bundle (incl. Tracing) - uncompressed | 117.63 kB | +0.82% | +956 B 🔺 |
| CDN Bundle (incl. Tracing, Replay) - uncompressed | 231.68 kB | +0.42% | +956 B 🔺 |
| CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed | 244.5 kB | +0.4% | +956 B 🔺 |
| @sentry/nextjs (client) | 43.22 kB | +1.35% | +574 B 🔺 |
| @sentry/sveltekit (client) | 40.04 kB | +1.36% | +535 B 🔺 |
| @sentry/node | 154.31 kB | +0.01% | +2 B 🔺 |
| @sentry/node - without tracing | 98.64 kB | +0.01% | +2 B 🔺 |
| @sentry/aws-serverless | 124.4 kB | +0.01% | +2 B 🔺 |