Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(replay): Capture slow clicks (experimental) #8052

Merged
merged 7 commits into from May 15, 2023
Merged

Conversation

mydea
Copy link
Member

@mydea mydea commented May 5, 2023

This adds an experimental config to allow capturing slow clicks in the UI.

Enable via:

new Replay({
  _experiments: {
    slowClicks: {
      threshold: 300, // min. duration for when we capture a click
      timeout: 5000, // stop waiting for an event after this time
      scrollTimeout: 300, // for scroll events, we only wait until this time is passed, then stop listening
      ignoreSelectors: string[], // do not detect slow clicks for elements matching these
    }
  }
}) 

Currently, we consider for this:

  • clicks on <button>, <a>, <input type='button'>, <input type='submit'>
  • We wait for either a DOM mutation to happen, or a scroll right after the click, or until the timeout
  • When the time is > threshold time, then we create a breadcrumb that looks like this:
{
  category: 'ui.slowClickDetected',
  data: {
    endReason: 'mutation',
    node: {
      attributes: {
        id: 'mutationButton',
      },
      id: expect.any(Number),
      tagName: 'button',
      textContent: '******* ********',
    },
    nodeId: expect.any(Number),
    timeAfterClickMs: expect.any(Number),
    url: 'http://sentry-test.io/index.html',
  },
  message: 'body > button#mutationButton',
  timestamp: expect.any(Number),
}

For <a> elements, we only consider them if they do not have download attribute, or a target !== '_self'. As downloads or links opened in other tabs should not result in a slow click. This should cover the most relevant cases for <a>, as links with a hash (e.g. #heading1) should be covered by the scroll detection.

Closes #8021

@mydea mydea self-assigned this May 5, 2023
@github-actions
Copy link
Contributor

github-actions bot commented May 5, 2023

size-limit report 📦

Path Size
@sentry/browser - ES5 CDN Bundle (gzipped + minified) 21.03 KB (+0.03% 🔺)
@sentry/browser - ES5 CDN Bundle (minified) 65.63 KB (+0.02% 🔺)
@sentry/browser - ES6 CDN Bundle (gzipped + minified) 19.57 KB (+0.04% 🔺)
@sentry/browser - ES6 CDN Bundle (minified) 58.09 KB (+0.02% 🔺)
@sentry/browser - Webpack (gzipped + minified) 21.17 KB (0%)
@sentry/browser - Webpack (minified) 69.04 KB (0%)
@sentry/react - Webpack (gzipped + minified) 21.19 KB (0%)
@sentry/nextjs Client - Webpack (gzipped + minified) 49.11 KB (0%)
@sentry/browser + @sentry/tracing - ES5 CDN Bundle (gzipped + minified) 28.65 KB (+0.02% 🔺)
@sentry/browser + @sentry/tracing - ES6 CDN Bundle (gzipped + minified) 26.88 KB (+0.03% 🔺)
@sentry/replay ES6 CDN Bundle (gzipped + minified) 48.13 KB (+1.08% 🔺)
@sentry/replay - Webpack (gzipped + minified) 42.02 KB (+1.35% 🔺)
@sentry/browser + @sentry/tracing + @sentry/replay - ES6 CDN Bundle (gzipped + minified) 67.08 KB (+0.87% 🔺)
@sentry/browser + @sentry/replay - ES6 CDN Bundle (gzipped + minified) 59.99 KB (+1.02% 🔺)

@mydea mydea changed the title WIP(replay): Capture slow clicks feat(replay): Capture slow clicks (experimental) May 9, 2023
@mydea mydea marked this pull request as ready for review May 9, 2023 09:48
@mydea mydea requested review from billyvg, ryan953 and Lms24 May 9, 2023 09:48
@cmanallen
Copy link
Member

Related: getsentry/sentry#48259

Comment on lines +43 to +45
const event = isClick && (handlerData.event as PointerEvent);
// Ignore clicks if ctrl/alt/meta keys are held down as they alter behavior of clicks (e.g. open in new tab)
if (isClick && slowClickConfig && event && !event.altKey && !event.metaKey && !event.ctrlKey) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this to ignore clicks made while alt/meta/ctrl are held down since they can alter behavior that would consider it a dead click.

Comment on lines +117 to +144
const SLOW_CLICK_IGNORE_TAGS = ['SELECT', 'OPTION'];

function ignoreElement(node: HTMLElement, config: SlowClickConfig): boolean {
// If <input> tag, we only want to consider input[type='submit'] & input[type='button']
if (node.tagName === 'INPUT' && !['submit', 'button'].includes(node.getAttribute('type') || '')) {
return true;
}

if (SLOW_CLICK_IGNORE_TAGS.includes(node.tagName)) {
return true;
}

// If <a> tag, detect special variants that may not lead to an action
// If target !== _self, we may open the link somewhere else, which would lead to no action
// Also, when downloading a file, we may not leave the page, but still not trigger an action
if (
node.tagName === 'A' &&
(node.hasAttribute('download') || (node.hasAttribute('target') && node.getAttribute('target') !== '_self'))
) {
return true;
}

if (config.ignoreSelector && node.matches(config.ignoreSelector)) {
return true;
}

return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this so that we include more tags while in experimental phase.

@billyvg billyvg merged commit bd48cf2 into develop May 15, 2023
59 checks passed
@billyvg billyvg deleted the fn/captureSlowClick branch May 15, 2023 11:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Capture Replay dead click as breadcrumb
4 participants