Skip to content

Distinguish redirects from user-initiated nagivations #15286

Description

@Lms24

Problem Statement

Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

  • Web vitals are currently only added to a pageload span.
    • If this span is cancelled before the vitals are emitted, users end up without any web vitals
    • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
  • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
    • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
    • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

Goal

We want to find a way to distinguish such automatic redirects from user-triggered navigations.

  • In case of a redirect:
    • Do not start a new trace (as of today)
    • Do not start a new idle span (as of today)
    • Instead, start a child navigation span of the ongoing idle span
      • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
  • In case of a user-triggered navigation:
    • Continue cancelling the ongoing idle span (i.e. today's behaviour)

Options Considered

1. Distinguishing based on Heuristics

"User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

  • navigations before the first click are considered application-triggered
  • navigations afterwards user-triggered
  • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

Pros:

  • realtively easy to implement
  • solves the initial classic "check for auth and redirect to dashboard/login" case

Cons:

  • Does not solve the redirect-after-user-triggered-navigation case
  • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

1.1 Reset heuristic on every user-initiated navigation

Same as above but reset the click listener and upper bound after each user-initiated navigation

Additional Pros:

  • Also solves the redirect-after-user-triggered-navigation case

2. Leverage the framework/router

Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

  • We solve this "best effort"-wise for the routers where we get this information from
  • We accept that this does not solve the problem for specific routers or the default instrumentation

Pros:

  • less risk of false positives/negatives as we don't rely on a heuristic

Cons:

  • Not applicable to all framework routers
  • Not applicable to the default instrumentation
  • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

3. Provide users a manual pageload end reporting API.

Proposed in #14810.

Pro:

  • full control for users, no idle mechanism, no heuristics

Cons:

  • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
  • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

4. Do nothing / null option

  • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
  • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

Pros:

  • less code/bundle size as no need for a heuristic or any other special treatment

Cons:

  • Both projects aren't completed and will not ship tomorrow.
  • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    , 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
     blocks
    (function() {
    function addCopyButtons() {
    document.querySelectorAll('pre code').forEach(function(codeBlock) {
    if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
    codeBlock.parentElement.setAttribute('data-copy-added', 'true');
    var btn = document.createElement('button');
    btn.textContent = 'Copy';
    btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
    btn.onmouseover = function() { this.style.opacity = '1'; };
    btn.onmouseout = function() { this.style.opacity = '0.7'; };
    btn.onclick = function() {
    navigator.clipboard.writeText(codeBlock.textContent).then(function() {
    btn.textContent = 'Copied!';
    setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
    });
    };
    codeBlock.parentElement.style.position = 'relative';
    codeBlock.parentElement.appendChild(btn);
    });
    }
    addCopyButtons();
    // Re-run on dynamic content
    var observer = new MutationObserver(addCopyButtons);
    observer.observe(document.body, { childList: true, subtree: true });
    })();
    }
    } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
    })();
    (function(){
    try {
    var __m = "github.com";
    var __re = new RegExp('^' + "github\\.com" + '
    Distinguish redirects from user-initiated nagivations · Issue #15286 · getsentry/sentry-javascript · GitHub
    Skip to content

    Distinguish redirects from user-initiated nagivations #15286

    Description

    @Lms24

    Problem Statement

    Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

    For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

    • Web vitals are currently only added to a pageload span.
      • If this span is cancelled before the vitals are emitted, users end up without any web vitals
      • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
    • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
      • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
      • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

    Goal

    We want to find a way to distinguish such automatic redirects from user-triggered navigations.

    • In case of a redirect:
      • Do not start a new trace (as of today)
      • Do not start a new idle span (as of today)
      • Instead, start a child navigation span of the ongoing idle span
        • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
    • In case of a user-triggered navigation:
      • Continue cancelling the ongoing idle span (i.e. today's behaviour)

    Options Considered

    1. Distinguishing based on Heuristics

    "User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

    • navigations before the first click are considered application-triggered
    • navigations afterwards user-triggered
    • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

    Pros:

    • realtively easy to implement
    • solves the initial classic "check for auth and redirect to dashboard/login" case

    Cons:

    • Does not solve the redirect-after-user-triggered-navigation case
    • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

    1.1 Reset heuristic on every user-initiated navigation

    Same as above but reset the click listener and upper bound after each user-initiated navigation

    Additional Pros:

    • Also solves the redirect-after-user-triggered-navigation case

    2. Leverage the framework/router

    Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

    • We solve this "best effort"-wise for the routers where we get this information from
    • We accept that this does not solve the problem for specific routers or the default instrumentation

    Pros:

    • less risk of false positives/negatives as we don't rely on a heuristic

    Cons:

    • Not applicable to all framework routers
    • Not applicable to the default instrumentation
    • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

    3. Provide users a manual pageload end reporting API.

    Proposed in #14810.

    Pro:

    • full control for users, no idle mechanism, no heuristics

    Cons:

    • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
    • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

    4. Do nothing / null option

    • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
    • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

    Pros:

    • less code/bundle size as no need for a heuristic or any other special treatment

    Cons:

    • Both projects aren't completed and will not ship tomorrow.
    • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

    Metadata

    Metadata

    Assignees

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Distinguish redirects from user-initiated nagivations · Issue #15286 · getsentry/sentry-javascript · GitHub
      Skip to content

      Distinguish redirects from user-initiated nagivations #15286

      Description

      @Lms24

      Problem Statement

      Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

      For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

      • Web vitals are currently only added to a pageload span.
        • If this span is cancelled before the vitals are emitted, users end up without any web vitals
        • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
      • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
        • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
        • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

      Goal

      We want to find a way to distinguish such automatic redirects from user-triggered navigations.

      • In case of a redirect:
        • Do not start a new trace (as of today)
        • Do not start a new idle span (as of today)
        • Instead, start a child navigation span of the ongoing idle span
          • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
      • In case of a user-triggered navigation:
        • Continue cancelling the ongoing idle span (i.e. today's behaviour)

      Options Considered

      1. Distinguishing based on Heuristics

      "User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

      • navigations before the first click are considered application-triggered
      • navigations afterwards user-triggered
      • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

      Pros:

      • realtively easy to implement
      • solves the initial classic "check for auth and redirect to dashboard/login" case

      Cons:

      • Does not solve the redirect-after-user-triggered-navigation case
      • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

      1.1 Reset heuristic on every user-initiated navigation

      Same as above but reset the click listener and upper bound after each user-initiated navigation

      Additional Pros:

      • Also solves the redirect-after-user-triggered-navigation case

      2. Leverage the framework/router

      Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

      • We solve this "best effort"-wise for the routers where we get this information from
      • We accept that this does not solve the problem for specific routers or the default instrumentation

      Pros:

      • less risk of false positives/negatives as we don't rely on a heuristic

      Cons:

      • Not applicable to all framework routers
      • Not applicable to the default instrumentation
      • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

      3. Provide users a manual pageload end reporting API.

      Proposed in #14810.

      Pro:

      • full control for users, no idle mechanism, no heuristics

      Cons:

      • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
      • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

      4. Do nothing / null option

      • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
      • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

      Pros:

      • less code/bundle size as no need for a heuristic or any other special treatment

      Cons:

      • Both projects aren't completed and will not ship tomorrow.
      • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

      Metadata

      Metadata

      Assignees

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions

        , 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Distinguish redirects from user-initiated nagivations · Issue #15286 · getsentry/sentry-javascript · GitHub
        Skip to content

        Distinguish redirects from user-initiated nagivations #15286

        Description

        @Lms24

        Problem Statement

        Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

        For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

        • Web vitals are currently only added to a pageload span.
          • If this span is cancelled before the vitals are emitted, users end up without any web vitals
          • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
        • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
          • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
          • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

        Goal

        We want to find a way to distinguish such automatic redirects from user-triggered navigations.

        • In case of a redirect:
          • Do not start a new trace (as of today)
          • Do not start a new idle span (as of today)
          • Instead, start a child navigation span of the ongoing idle span
            • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
        • In case of a user-triggered navigation:
          • Continue cancelling the ongoing idle span (i.e. today's behaviour)

        Options Considered

        1. Distinguishing based on Heuristics

        "User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

        • navigations before the first click are considered application-triggered
        • navigations afterwards user-triggered
        • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

        Pros:

        • realtively easy to implement
        • solves the initial classic "check for auth and redirect to dashboard/login" case

        Cons:

        • Does not solve the redirect-after-user-triggered-navigation case
        • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

        1.1 Reset heuristic on every user-initiated navigation

        Same as above but reset the click listener and upper bound after each user-initiated navigation

        Additional Pros:

        • Also solves the redirect-after-user-triggered-navigation case

        2. Leverage the framework/router

        Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

        • We solve this "best effort"-wise for the routers where we get this information from
        • We accept that this does not solve the problem for specific routers or the default instrumentation

        Pros:

        • less risk of false positives/negatives as we don't rely on a heuristic

        Cons:

        • Not applicable to all framework routers
        • Not applicable to the default instrumentation
        • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

        3. Provide users a manual pageload end reporting API.

        Proposed in #14810.

        Pro:

        • full control for users, no idle mechanism, no heuristics

        Cons:

        • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
        • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

        4. Do nothing / null option

        • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
        • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

        Pros:

        • less code/bundle size as no need for a heuristic or any other special treatment

        Cons:

        • Both projects aren't completed and will not ship tomorrow.
        • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

        Metadata

        Metadata

        Assignees

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Distinguish redirects from user-initiated nagivations · Issue #15286 · getsentry/sentry-javascript · GitHub
          Skip to content

          Distinguish redirects from user-initiated nagivations #15286

          Description

          @Lms24

          Problem Statement

          Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

          For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

          • Web vitals are currently only added to a pageload span.
            • If this span is cancelled before the vitals are emitted, users end up without any web vitals
            • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
          • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
            • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
            • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

          Goal

          We want to find a way to distinguish such automatic redirects from user-triggered navigations.

          • In case of a redirect:
            • Do not start a new trace (as of today)
            • Do not start a new idle span (as of today)
            • Instead, start a child navigation span of the ongoing idle span
              • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
          • In case of a user-triggered navigation:
            • Continue cancelling the ongoing idle span (i.e. today's behaviour)

          Options Considered

          1. Distinguishing based on Heuristics

          "User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

          • navigations before the first click are considered application-triggered
          • navigations afterwards user-triggered
          • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

          Pros:

          • realtively easy to implement
          • solves the initial classic "check for auth and redirect to dashboard/login" case

          Cons:

          • Does not solve the redirect-after-user-triggered-navigation case
          • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

          1.1 Reset heuristic on every user-initiated navigation

          Same as above but reset the click listener and upper bound after each user-initiated navigation

          Additional Pros:

          • Also solves the redirect-after-user-triggered-navigation case

          2. Leverage the framework/router

          Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

          • We solve this "best effort"-wise for the routers where we get this information from
          • We accept that this does not solve the problem for specific routers or the default instrumentation

          Pros:

          • less risk of false positives/negatives as we don't rely on a heuristic

          Cons:

          • Not applicable to all framework routers
          • Not applicable to the default instrumentation
          • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

          3. Provide users a manual pageload end reporting API.

          Proposed in #14810.

          Pro:

          • full control for users, no idle mechanism, no heuristics

          Cons:

          • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
          • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

          4. Do nothing / null option

          • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
          • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

          Pros:

          • less code/bundle size as no need for a heuristic or any other special treatment

          Cons:

          • Both projects aren't completed and will not ship tomorrow.
          • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

          Metadata

          Metadata

          Assignees

          Projects

          No projects

            Milestone

            No milestone

            Relationships

            None yet

            Development

            No branches or pull requests

            Issue actions

            , 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Distinguish redirects from user-initiated nagivations · Issue #15286 · getsentry/sentry-javascript · GitHub
            Skip to content

            Distinguish redirects from user-initiated nagivations #15286

            Description

            @Lms24

            Problem Statement

            Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

            For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

            • Web vitals are currently only added to a pageload span.
              • If this span is cancelled before the vitals are emitted, users end up without any web vitals
              • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
            • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
              • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
              • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

            Goal

            We want to find a way to distinguish such automatic redirects from user-triggered navigations.

            • In case of a redirect:
              • Do not start a new trace (as of today)
              • Do not start a new idle span (as of today)
              • Instead, start a child navigation span of the ongoing idle span
                • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
            • In case of a user-triggered navigation:
              • Continue cancelling the ongoing idle span (i.e. today's behaviour)

            Options Considered

            1. Distinguishing based on Heuristics

            "User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

            • navigations before the first click are considered application-triggered
            • navigations afterwards user-triggered
            • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

            Pros:

            • realtively easy to implement
            • solves the initial classic "check for auth and redirect to dashboard/login" case

            Cons:

            • Does not solve the redirect-after-user-triggered-navigation case
            • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

            1.1 Reset heuristic on every user-initiated navigation

            Same as above but reset the click listener and upper bound after each user-initiated navigation

            Additional Pros:

            • Also solves the redirect-after-user-triggered-navigation case

            2. Leverage the framework/router

            Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

            • We solve this "best effort"-wise for the routers where we get this information from
            • We accept that this does not solve the problem for specific routers or the default instrumentation

            Pros:

            • less risk of false positives/negatives as we don't rely on a heuristic

            Cons:

            • Not applicable to all framework routers
            • Not applicable to the default instrumentation
            • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

            3. Provide users a manual pageload end reporting API.

            Proposed in #14810.

            Pro:

            • full control for users, no idle mechanism, no heuristics

            Cons:

            • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
            • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

            4. Do nothing / null option

            • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
            • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

            Pros:

            • less code/bundle size as no need for a heuristic or any other special treatment

            Cons:

            • Both projects aren't completed and will not ship tomorrow.
            • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

            Metadata

            Metadata

            Assignees

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Distinguish redirects from user-initiated nagivations · Issue #15286 · getsentry/sentry-javascript · GitHub
              Skip to content

              Distinguish redirects from user-initiated nagivations #15286

              Description

              @Lms24

              Problem Statement

              Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

              For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

              • Web vitals are currently only added to a pageload span.
                • If this span is cancelled before the vitals are emitted, users end up without any web vitals
                • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
              • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
                • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
                • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

              Goal

              We want to find a way to distinguish such automatic redirects from user-triggered navigations.

              • In case of a redirect:
                • Do not start a new trace (as of today)
                • Do not start a new idle span (as of today)
                • Instead, start a child navigation span of the ongoing idle span
                  • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
              • In case of a user-triggered navigation:
                • Continue cancelling the ongoing idle span (i.e. today's behaviour)

              Options Considered

              1. Distinguishing based on Heuristics

              "User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

              • navigations before the first click are considered application-triggered
              • navigations afterwards user-triggered
              • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

              Pros:

              • realtively easy to implement
              • solves the initial classic "check for auth and redirect to dashboard/login" case

              Cons:

              • Does not solve the redirect-after-user-triggered-navigation case
              • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

              1.1 Reset heuristic on every user-initiated navigation

              Same as above but reset the click listener and upper bound after each user-initiated navigation

              Additional Pros:

              • Also solves the redirect-after-user-triggered-navigation case

              2. Leverage the framework/router

              Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

              • We solve this "best effort"-wise for the routers where we get this information from
              • We accept that this does not solve the problem for specific routers or the default instrumentation

              Pros:

              • less risk of false positives/negatives as we don't rely on a heuristic

              Cons:

              • Not applicable to all framework routers
              • Not applicable to the default instrumentation
              • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

              3. Provide users a manual pageload end reporting API.

              Proposed in #14810.

              Pro:

              • full control for users, no idle mechanism, no heuristics

              Cons:

              • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
              • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

              4. Do nothing / null option

              • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
              • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

              Pros:

              • less code/bundle size as no need for a heuristic or any other special treatment

              Cons:

              • Both projects aren't completed and will not ship tomorrow.
              • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

              Metadata

              Metadata

              Assignees

              Projects

              No projects

                Milestone

                No milestone

                Relationships

                None yet

                Development

                No branches or pull requests

                Issue actions

                , 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Distinguish redirects from user-initiated nagivations · Issue #15286 · getsentry/sentry-javascript · GitHub
                Skip to content

                Distinguish redirects from user-initiated nagivations #15286

                Description

                @Lms24

                Problem Statement

                Our Browser SDKs by default create op: pageload and op: navigation idle spans to record spans and browser metrics during (hard) page loads and (soft) navigations (most commonly via client-side SPA routers). In most of our browserTracingIntegrations, including the default one, we cancel (i.e. end) an ongoing idle span if there is still an active span. While this makes sense if you assume the new navigation is intentionally triggered (e.g. by a user clicking a link/button), it falls apart for automatic redirections. Such redirects are fairly common shortly after the pageload. A popular example is users opening a page on / which causes the router to checks if they're authenticated. If yes, they're redirected to a /dashboard page and otherwise t oa /login page.

                For redirects (or more generally for "non-user-triggered navigations"), this cancellation behavior has a variety of problems:

                • Web vitals are currently only added to a pageload span.
                  • If this span is cancelled before the vitals are emitted, users end up without any web vitals
                  • Likewise, the value of LCP or CLS likely is only the initial value and might miss important updates after a redirection
                • Semantically, the cancellation of the prior idle span splits the ongoing action into two distinct traces, where the separation might even seem arbitrary.
                  • As of today, users have no way to connect the previous and current/next idle span. This will be addressed by trace links but one can argue that this separation should not exist at all for redirects.
                  • It's worth noting that this doesn't only concern redirects after an initial pageload but potentially also redirects from a user-triggered navigation. For example, a user clicks on a link but misses the authorization/role to access the page and hence gets redirected to a "request authorization" page (looking at you Google Docs 👀)

                Goal

                We want to find a way to distinguish such automatic redirects from user-triggered navigations.

                • In case of a redirect:
                  • Do not start a new trace (as of today)
                  • Do not start a new idle span (as of today)
                  • Instead, start a child navigation span of the ongoing idle span
                    • [TBD] We probably don't want to start a new root span here, to 1. avoid race conditions which root span (old idle vs. new root) gets resource and performance spans and 2. to keep a linear chain of traces
                • In case of a user-triggered navigation:
                  • Continue cancelling the ongoing idle span (i.e. today's behaviour)

                Options Considered

                1. Distinguishing based on Heuristics

                "User-triggered" navigation implies a click. We can listen globally to a click event and treat every navigation before the first click as a redirect/application-triggered navigation.

                • navigations before the first click are considered application-triggered
                • navigations afterwards user-triggered
                • We probably need an upper bound for how long we consider a navigation application-triggered. Not all applications require a user interaction in the classic sense to trigger a user-intended or -perceived navigation (e.g. websites running on monitors that cycle through different pages)

                Pros:

                • realtively easy to implement
                • solves the initial classic "check for auth and redirect to dashboard/login" case

                Cons:

                • Does not solve the redirect-after-user-triggered-navigation case
                • Might need custom implementation for specific routing instrumentations that don't call startBrowserTracingNavigationSpan (?)

                1.1 Reset heuristic on every user-initiated navigation

                Same as above but reset the click listener and upper bound after each user-initiated navigation

                Additional Pros:

                • Also solves the redirect-after-user-triggered-navigation case

                2. Leverage the framework/router

                Some routers provide our instrumentation with enough information to distinguish between application- vs. user-initiated navigations (e.g. Ember, Angular, more?)

                • We solve this "best effort"-wise for the routers where we get this information from
                • We accept that this does not solve the problem for specific routers or the default instrumentation

                Pros:

                • less risk of false positives/negatives as we don't rely on a heuristic

                Cons:

                • Not applicable to all framework routers
                • Not applicable to the default instrumentation
                • Developers might not use the router-provided redirection mechanism but instead redirect as if users initiated the redirect

                3. Provide users a manual pageload end reporting API.

                Proposed in #14810.

                Pro:

                • full control for users, no idle mechanism, no heuristics

                Cons:

                • users need to handle a lot of "pageload ended" points on their own. For example, report pageload end on each page the router redirects to, whenever an error occurs, whenever users start a navigation, etc. A LOT of room for error and missed cases.
                • Given the above, this can never become SDK default behaviour and really only should be used in special cases. Which to an extent, users can already do today anyway as pointed out in Programatic way to indicate that a pageload / navigation transaction has completed #14810 (comment).

                4. Do nothing / null option

                • With the introduction of [trace links], we can connect multiple traces in a chain, meaning the cancelled trace/idle span would be the previous trace of the navigation. We can build a UX in the product that identifies likely redirection trace pairs, based on a end/start timestamp window in combination with span status.
                • With our effort to send some web vitals as standalone spans (Send LCP & CLS as standalone spans #12714) we avoid depending on the pageload span running until we have the "final" web vital values.

                Pros:

                • less code/bundle size as no need for a heuristic or any other special treatment

                Cons:

                • Both projects aren't completed and will not ship tomorrow.
                • The semantic concern of splitting the trace (see above) is not addressed fully. No matter how/if we adjust the product to deal with this, data-wise it is still confusing.

                Metadata

                Metadata

                Assignees

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions