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

🎨 Instrument fetch and XHR before trying to init consent #2834

Merged

Conversation

N-Boutaib
Copy link
Contributor

@N-Boutaib N-Boutaib commented Jun 26, 2024

Motivation

When RUM's initialisation is delayed because of consent not being granted initially, some libraries (such as Apollo Client) do store some methods aside to be re-used (mainly window.fetch), which leads to the un-instrumented method being used for http requests, even after consent being granted.

Changes

Instrument fetch method on sdk initialisation. The instrumentation process is idempotent.

Testing

  • Local
  • Staging
  • Unit
  • End to end

I have gone over the contributing documentation.

@codecov-commenter
Copy link

codecov-commenter commented Jun 26, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 93.09%. Comparing base (fab7ead) to head (14807bd).
Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2834      +/-   ##
==========================================
- Coverage   93.10%   93.09%   -0.02%     
==========================================
  Files         248      248              
  Lines        7242     7246       +4     
  Branches     1624     1624              
==========================================
+ Hits         6743     6746       +3     
- Misses        499      500       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

cit-pr-commenter bot commented Jun 26, 2024

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 160.40 KiB 160.42 KiB 18 B +0.01%
Logs 58.02 KiB 58.04 KiB 18 B +0.03%
Rum Slim 108.92 KiB 108.94 KiB 18 B +0.02%
Worker 25.21 KiB 25.21 KiB 0 B 0.00%
🚀 CPU Performance
Action Name Base Average Cpu Time (ms) Local Average Cpu Time (ms) 𝚫
addglobalcontext 0.001 0.002 0.000
addaction 0.031 0.037 0.006
adderror 0.032 0.035 0.003
addtiming 0.001 0.001 0.000
startview 0.898 0.998 0.100
startstopsessionreplayrecording 0.860 0.952 0.092
logmessage 0.019 0.021 0.002
🧠 Memory Performance
Action Name Base Consumption Memory (bytes) Local Consumption Memory (bytes) 𝚫 (bytes)
addglobalcontext 19.53 KiB 17.88 KiB -1698 B
addaction 72.93 KiB 68.45 KiB -4583 B
adderror 86.17 KiB 85.68 KiB -500 B
addtiming 19.72 KiB 16.54 KiB -3251 B
startview 314.43 KiB 320.54 KiB 6.11 KiB
startstopsessionreplayrecording 15.25 KiB 14.13 KiB -1155 B
logmessage 71.76 KiB 69.40 KiB -2424 B

🔗 RealWorld

@N-Boutaib N-Boutaib force-pushed the najib.boutaib/RUM-5012-instrument-fetch-as-soon-as-possible branch from dcbbc67 to de49625 Compare June 26, 2024 13:38
@N-Boutaib N-Boutaib marked this pull request as ready for review June 26, 2024 13:46
@N-Boutaib N-Boutaib requested a review from a team as a code owner June 26, 2024 13:46
Copy link
Collaborator

@thomas-lebeau thomas-lebeau left a comment

Choose a reason for hiding this comment

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

🔨 warning: ‏ I think we have the same issue with logs, don't we?

❓ question: ‏ What about other instrumented methods? It might be less common for them to be used that way, but we could have the same issue if that happens, no?

@BenoitZugmeyer
Copy link
Member

🔨 warning: ‏ I think we have the same issue with logs, don't we?

❓ question: ‏ What about other instrumented methods? It might be less common for them to be used that way, but we could have the same issue if that happens, no?

For both subjects: I would wait for requests to do so before acting on it, as we don't want to over-instrument if we don't need to (in other words, it is better to not instrument if we never have user consent).

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/unbound-method */
Copy link
Member

Choose a reason for hiding this comment

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

💬 suggestion: ‏don't disable ESLint rules for the whole file. You can wrap your code between comments:

/* eslint-disable ... */
xxx
/* eslint-enable ... */

Comment on lines 41 to 44
const oldFetch = window.fetch
const oldXHROpen = XMLHttpRequest.prototype.open
const oldXHRSend = XMLHttpRequest.prototype.send
const oldXHRAbort = XMLHttpRequest.prototype.abort
Copy link
Member

Choose a reason for hiding this comment

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

💬 suggestion: ‏move this at the start of your test case.
Some other tests executing earlier could instrument those methods and not properly clean them up.

@N-Boutaib
Copy link
Contributor Author

/to-staging

@dd-devflow
Copy link
Contributor

dd-devflow bot commented Jun 27, 2024

🚂 Branch Integration: starting soon, median merge time is 10m

Commit d3f3bd6f78 will soon be integrated into staging-26.

Use /to-staging -c to cancel this operation!

@dd-devflow
Copy link
Contributor

dd-devflow bot commented Jun 27, 2024

⚠️ Branch Integration: This commit was already integrated

Commit d3f3bd6f78 had already been merged into staging-26

If you need support, contact us on Slack #devflow!

// This is needed in case the consent is not granted and some cutsomer
// library (Apollo Client) is storing uninstrumented fetch to be used later
// The subscrption is needed so that the instrumentation process is completed
initFetchObservable().subscribe(noop)
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 suggestion:
Thesubscribe(noop) feels a bit hacky.
You could change the createFetchObservable as follow to avoid having to call the subscribe.

function createFetchObservable() {
  let instrumentation: (call: any) => void = noop
  const { stop } = instrumentMethod(window, 'fetch', (call) => instrumentation(call), { computeHandlingStack: true })

  return new Observable<FetchContext>((observable) => {
    if (!window.fetch) {
      return
    }
    instrumentation = (call) => beforeSend(call, observable)

    return stop
  })
}

Copy link
Member

Choose a reason for hiding this comment

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

We talked a bit about it during standup. I'll try to sum it up here.

On one side, we all agree that .subscribe(noop) is a bit suprising (but not necessarily hacky). On the other side, changing this would make things more complex in fetchObservable.ts.

What you are suggesting is incorrect because if stop is called because there is no more subscriber, then the observable is subscribed again, we wouldn't re-instrument fetch. In practice this probably does not happen, but for a newcomer reading this code without context this might be seen as a bug.

So we would need another way to clean the instrumentation? Or maybe don't clean the instrumentation? It doesn't feel great either.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well I think .subscribe(noop) does not convey the intention of what it does and raise more questions about the implementation for new newcomer reading this code.
I put the stop in the observable only to avoid modifying too much the tests. We could have also extended the resetFetchObservable to reset the instrumentation. Since the removal of the instrumentation and the reset of the observable are only done for testing purposes, this approach would have been reasonable. I feel like we're choosing a confusing implementation just to avoid refactoring the tests.

@N-Boutaib N-Boutaib merged commit 401e8e9 into main Jul 4, 2024
20 checks passed
@N-Boutaib N-Boutaib deleted the najib.boutaib/RUM-5012-instrument-fetch-as-soon-as-possible branch July 4, 2024 08:13
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.

5 participants