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

perf: Prevent Sentry from auto-generating spans for requests to Sentry #28613

Merged

Conversation

MajorLift
Copy link
Contributor

@MajorLift MajorLift commented Nov 21, 2024

Motivation

The Sentry browser tracing integration intercepts all outgoing fetch requests, and measures their duration in automatically-generated http.client spans.

Currently, our Sentry configuration does not exclude POST requests to Sentry DSN endpoints from this process. Unfortunately, these requests appear to have been taking up not just a non-negligible, but an outright dominating footprint in our Sentry performance quota and budget.

Based on usage data over the past 90 days in our metamask Sentry project, we can make the following observations (the following data only covers requests sent to sentry.io, and doesn't include requests sent to hostnames under that domain e.g. *.ingest.us.sentry.io):

  • In both the /home.html and /popup.html traces, the auto-generated spans for sentry POST requests collectively rank in 3rd place by the "Time Spent" metric, only coming in behind the ui.long-task and pageload spans, and actually being ahead of navigation as well as all other legitimate requests to resource API endpoints.
Screenshot 2024-11-21 at 8 16 04 AM

https://metamask.sentry.io/performance/summary/spans/?project=273505&query=&statsPeriod=90d&transaction=%2Fpopup.html

Screenshot 2024-11-21 at 8 17 20 AM

https://metamask.sentry.io/performance/summary/spans/?project=273505&query=&statsPeriod=90d&transaction=%2Fhome.html

  • While the average duration of the Sentry spans is around 0.5s, there are instances where they last for much longer (30s - 1m).
    • An argument could be made that we should leave the Sentry spans to measure these edge cases. However, I think it would be a safe assumption that drastic delays like these will be accompanied by and captured through similar delays in other outgoing network requests. Unless we have reason to target delayed communications that only affect Sentry, filtering out these spans wouldn't result in meaningful information being lost.
Screenshot 2024-11-21 at 8 18 37 AM

https://metamask.sentry.io/performance/summary/spans/http.client:8ee04019c21406cc/?project=273505&query=&sort=-span.duration&statsPeriod=90d&transaction=%2Fpopup.html

Screenshot 2024-11-21 at 8 18 43 AM

https://metamask.sentry.io/performance/summary/spans/http.client:8ee04019c21406cc/?project=273505&query=&sort=-span.duration&statsPeriod=90d&transaction=%2Fhome.html

Description

To fix this, we need to filter out communications with Sentry itself from the monitoring data that is logged to the Sentry dashboard.

This commit achieves this by configuring Sentry's browser tracing integration with its shouldCreateSpanForRequest option.

Open in GitHub Codespaces

Related issues

Manual testing steps

  1. Initialize the MetaMask extension with Sentry enabled.
  2. [Optional] Take actions that are measured by custom spans (e.g. toggle between account overview tabs, load the account list). This isn't necessary, as communications with Sentry will already have taken place in the first step.
  3. Verify in the Sentry dashboard that no recent http.client spans for 'sentry.io' have been logged.

Screenshots/Recordings

Before

Note the three http.client spans for 'sentry.io':

Screenshot 2024-11-21 at 8 37 55 AM

After

No auto-generated http.client spans show up in the Sentry dashboard for POST requests to the Sentry DSN endpoint, even though the requests are still going out.

http.client spans for other URLs are still being created and measured.

Screenshot 2024-11-21 at 7 49 39 AM

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

…Integration` and filter spans for requests to 'sentry.io'
Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@MajorLift MajorLift self-assigned this Nov 21, 2024
@MajorLift MajorLift added team-tiger Tiger team (for tech debt reduction + performance improvements) area-Sentry error reporting to sentry area-performance Issues relating to slowness of app, cpu usage, and/or blank screens. and removed team-wallet-framework labels Nov 21, 2024
@MajorLift MajorLift marked this pull request as ready for review November 21, 2024 14:02
@MajorLift MajorLift requested a review from a team as a code owner November 21, 2024 14:02
@metamaskbot
Copy link
Collaborator

Builds ready [9142f93]
Page Load Metrics (1967 ± 79 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint17622305196616177
domContentLoaded17432293193315172
load17542309196716579
domInteractive178240178
backgroundConnect1189342713
firstReactRender783921467536
getState56017188
initialActions01000
loadScripts12611769143113866
setupStore68614199
uiStartup195027812234243117
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 0 Bytes (0.00%)
  • common: 59 Bytes (0.00%)

Comment on lines 89 to 94
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a 'sentry.io' domain.
return !url.match(/sentry\.io\/?$/u);
},
}),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For comparison, this is the code example from the docs:

shouldCreateSpanForRequest

This function can be used to filter out unwanted spans such as XHRs running health checks or something similar. If this function isn't specified, spans will be created for all requests.

   Sentry.browserTracingIntegration({
     shouldCreateSpanForRequest: (url) => {
       // Do not create spans for outgoing requests to a `/health/` endpoint
       return !url.match(/\/health\/?$/);
     },
   }),

https://docs.sentry.io/platforms/javascript/tracing/instrumentation/automatic-instrumentation/#shouldcreatespanforrequest

Copy link
Contributor

Choose a reason for hiding this comment

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

This regex is incorrect. Because it has the $, it will only match URLs that end in sentry.io/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right! This could be fixed by making the regex more specific:

Suggested change
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a 'sentry.io' domain.
return !url.match(/sentry\.io\/?$/u);
},
}),
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a 'sentry.io' domain.
return !url.match(
/^https?:\/\/(\w+@)?(\w+\.ingest\.\w{2,3}\.)?sentry\.io(\/api)?/u,
);
},
}),

But I guess a simpler, more permissive regex would be better performance-wise (less backtracking and potentially exponential-time greedy matching).

Suggested change
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a 'sentry.io' domain.
return !url.match(/sentry\.io\/?$/u);
},
}),
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a 'sentry.io' domain.
return !url.match(/sentry\.io/u);
},
}),

What do you think? The only possible problem I can think of from taking the second approach would be false positives being filtered out, but that's probably not an issue with the Sentry domain.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the question is... is there some attack possible if someone makes a URL like badplace.com/sentry.io? I guess it would hide this information from us, but we do already have the privacy-snapshot.json for this.

Copy link
Contributor Author

@MajorLift MajorLift Nov 22, 2024

Choose a reason for hiding this comment

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

That's a good point. Maybe we could strike a middle ground by just checking that we're in the right domain?

Suggested change
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a 'sentry.io' domain.
return !url.match(/sentry\.io\/?$/u);
},
}),
Sentry.browserTracingIntegration({
shouldCreateSpanForRequest: (url) => {
// Do not create spans for outgoing requests to a 'sentry.io' domain.
return !url.match(
/^https?:\/\/([\w\d.@-]+\.)?sentry\.io(\/|$)/u
);
},
}),

(Not sure if the $ in capture group at the end is correct syntax)
Edit: Looks like it is. https://ingest.us.sentry.ioapi is rejected by https://regex101.com/

Or we could just go more specific, since the security concern seems like a higher priority than performance gains here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I think this one works

HowardBraham
HowardBraham previously approved these changes Nov 22, 2024
@metamaskbot
Copy link
Collaborator

Builds ready [0552f10]
Page Load Metrics (2053 ± 102 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint30327981780626301
domContentLoaded17662700202418991
load177228462053212102
domInteractive16217604321
backgroundConnect8112353215
firstReactRender981631232110
getState56119199
initialActions00000
loadScripts12952135150016981
setupStore65813157
uiStartup198031962298251121
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 0 Bytes (0.00%)
  • ui: 0 Bytes (0.00%)
  • common: 88 Bytes (0.00%)

@MajorLift MajorLift changed the title perf: Configure shouldCreateSpanForRequest option for Sentry browserTracingIntegration perf: Prevent Sentry from auto-generating spans for requests to Sentry Nov 27, 2024
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

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

LGTM!

@MajorLift MajorLift added this pull request to the merge queue Nov 27, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 27, 2024
@MajorLift MajorLift added this pull request to the merge queue Nov 27, 2024
Merged via the queue into develop with commit 7a9793f Nov 27, 2024
87 checks passed
@MajorLift MajorLift deleted the jongsun/perf/trace/241121-filter-fetch-request-spans branch November 27, 2024 17:42
@github-actions github-actions bot locked and limited conversation to collaborators Nov 27, 2024
@metamaskbot metamaskbot added the release-12.9.0 Issue or pull request that will be included in release 12.9.0 label Nov 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-performance Issues relating to slowness of app, cpu usage, and/or blank screens. area-Sentry error reporting to sentry release-12.9.0 Issue or pull request that will be included in release 12.9.0 team-tiger Tiger team (for tech debt reduction + performance improvements)
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants