feat(utils): Refactor addInstrumentationHandler to dedicated methods#9542
feat(utils): Refactor addInstrumentationHandler to dedicated methods#9542
addInstrumentationHandler to dedicated methods#9542Conversation
| let to: string | undefined = handlerData.to; | ||
| const parsedLoc = parseUrl(WINDOW.location.href); | ||
| let parsedFrom = parseUrl(from); | ||
| let parsedFrom = from ? parseUrl(from) : undefined; |
There was a problem hiding this comment.
this was actually incorrect because from can technically be undefined.
| addHistoryInstrumentationHandler(({ from, to }) => { | ||
| // Don't create an additional session for the initial route or if the location did not change | ||
| if (!(from === undefined || from === to)) { | ||
| if (from !== undefined && from !== to) { |
There was a problem hiding this comment.
this condition is a bit easier to read IMHO
| isClick && | ||
| replay.clickDetector && | ||
| event && | ||
| event.target && |
There was a problem hiding this comment.
it was technically possible to have no target here (which was surfaced by a test with changed setup) if you have a syntethic event like new Event('click').
|
|
||
| export interface SentryWrappedXMLHttpRequest { | ||
| __sentry_xhr_v2__?: SentryXhrData; | ||
| __sentry_xhr_v3__?: SentryXhrData; |
There was a problem hiding this comment.
bumped this because method & url are required now.
| * Use at your own risk, this might break without changelog notice, only used internally. | ||
| * @hidden | ||
| */ | ||
| export function addClickKeypressInstrumentationHandler(handler: (data: HandlerDataDom) => void): void { |
There was a problem hiding this comment.
this name is pretty explicit, alternatively we could do addDomEventInstrumentationHandler?
| WINDOW.onpopstate = function (this: WindowEventHandlers, ...args: any[]): any { | ||
| const to = WINDOW.location.href; | ||
| // keep track of the current URL state, as we always receive only the updated state | ||
| const from = lastHref; |
There was a problem hiding this comment.
due to this, from can actually be undefined the first time this is run.
| const method = isString(args[0]) ? args[0].toUpperCase() : undefined; | ||
| const url = parseUrl(args[1]); | ||
|
|
||
| if (!method || !url) { |
There was a problem hiding this comment.
this should never happen, but in the spirit of being very cautious...
|
|
||
| const xhrInfo = this[SENTRY_XHR_DATA_KEY]; | ||
|
|
||
| if (xhrInfo && isString(header) && isString(value)) { |
There was a problem hiding this comment.
Being explicit in checking the types here, as theoretically a user could do xhr.setRequestHeader(1, 1) (that may/should fail, but shouldn't fail on our end).
| } | ||
|
|
||
| const handlerData: HandlerDataXhr = { | ||
| args: [sentryXhrData.method, sentryXhrData.url], |
There was a problem hiding this comment.
we used to just pass args: args as [string, string] here which is actually "wrong" or not really what is expected (I think), because args in here is the args passed to send, which is the body (that we capture separately above).
size-limit report 📦
|
| // but since URL is not available in IE11, we do not check for it, | ||
| // but simply assume it is an URL and return `toString()` from it (which returns the full URL) | ||
| // If that fails, we just return undefined | ||
| return (url as URL).toString(); |
There was a problem hiding this comment.
We did not handle this case at all, but it is a valid usage of open() according to MDN.
billyvg
left a comment
There was a problem hiding this comment.
These changes seem reasonable to me, I only really looked through the replay changes but they seem pretty straightforward
AbhiPrasad
left a comment
There was a problem hiding this comment.
good refactor, feels way better to work with
| return; | ||
| } | ||
|
|
||
| if (shouldIgnoreOnError() || (error && error.__sentry_own_request__)) { |
There was a problem hiding this comment.
Note here: __sentry_own_request__ is not actually set anymore anywhere except on the XHR object itself. So I figured we can remove this check here and above for the global errors, as no error can/should ever get this property anymore 🤔
This is mostly an internal utility, but changes a bit. This improves the actual type safety a lot, because currently we've been duplicating the types everywhere, sometimes in slightly differing ways, leading to potential issues.
This is mostly an internal utility, but changes a bit. The previous implementation for adding instrumentation had a few issues:
This PR splits up
addInstrumentationHandlerinto e.g.addFetchInstrumentationHandleretc. methods, which improves the actual type safety a lot, because currently we've been duplicating the types everywhere, sometimes in slightly differing ways, leading to potential issues. We had a bunch of issues with xhr & fetch data in Replay recently, so I figured it would finally be a good time to clean this up so we can ensure that the data we get is consistent & reliable. Hopefully this change will prevent issues like we have/had in replay from popping up in the future.Some additional notes:
addClickKeypressInstrumentationHandler(). I'm open for other naming ideas, but I foundaddDomInstrumentationa bit too broad, as this could mean a lot of things - and we are strictly only instrumenting clicks and keypresses here. Another name (if we want to be a bit broader) could be e.g.addDomEventInstrumentationor something like this?urlcan be aURLinstead of a string, which we now convert.argsthat 1. is not really used and 2. was actually "buggy", as we always returned the args, but foropenandsendthe args are very different things (but we pretended it's always the "open" args). Now, this is actually always the method & url, and I also deprecated this for v8.datafield, which I removed (this was not set anywhere)addInstrumentationHandler()method, for removal in v8.