-
Notifications
You must be signed in to change notification settings - Fork 144
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
🎨 Instrument fetch and XHR before trying to init consent #2834
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
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. |
Bundles Sizes Evolution
🚀 CPU Performance
🧠 Memory Performance
|
dcbbc67
to
de49625
Compare
There was a problem hiding this 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?
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 */ |
There was a problem hiding this comment.
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 ... */
const oldFetch = window.fetch | ||
const oldXHROpen = XMLHttpRequest.prototype.open | ||
const oldXHRSend = XMLHttpRequest.prototype.send | ||
const oldXHRAbort = XMLHttpRequest.prototype.abort |
There was a problem hiding this comment.
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.
/to-staging |
🚂 Branch Integration: starting soon, median merge time is 10m Commit d3f3bd6f78 will soon be integrated into staging-26. Use |
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) |
There was a problem hiding this comment.
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
})
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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
I have gone over the contributing documentation.