Wouldn't it make sense to make use of navigator.sendBeacon() if available? It should be possible to implement that in a few lines of code and fall back to the current way.
The Beacon standard is designed for use-cases like logging, analytics, etc. It allows to send ("small") HTTP Requests without caring about the response. It seems like a pretty lightweight way to do what raven.js needs to do.
What are we trying to solve here? sendBeacon
is for sending data to a web server prior to the unloading of the document. Although that is great for analytics where we want to avoid a navigation delay, I'm not sure it makes sense in the context of Sentry-js.
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/Beacon/Overview.html
I think the idea is more-or-less that we can better guarantee data is sent instead of being aborted or waiting to hear back from Sentry if we're in the middle of sending something.
It's also, IMO, a better API than loading a fake image that we do nothing with.
I'd at least like to play with it and see if it's worth it or not.
Also... actually, sendBeacon
uses a POST
method. This might be useful since we have lots of limitations with a GET
because querystring length.
And XHR based POST
has to deal with CORS. I assume sendBeacon
is not subject to CORS since it's just fire and forget.
With that said, I'm open to a patch if you'd like to attempt this so we can see what it looks like. :)
Sure, it is worth to try out. : )
But I don't like the missing support for Safari and Internet Explore.
Oh, I really skipped the "prior to the unloading of the document" part of the spec. Thats kind of sad because I thought of it as a lightweight XHR POST Request.
This implementation could cause problems for single-page-apps though, because the page (that might have errors which need to be loggen) never gets unloaded.
So, after reading that important part of the spec, I think my idea might be rubbish/waste of time.
Not sure if that's accurate.
According to: http://www.w3.org/TR/beacon/#sec-sendBeacon-method, it states:
The User Agent SHOULD transmit data at the earliest available opportunity, but MAY prioritize the transmission of data lower compared to other network traffic. The User Agent SHOULD make a best effort attempt to eventually transmit the data.
This is obviously testable. But I don't think it's tied to _only_ sending data on unload. I think that's just a common use case to do so and a common pattern for other beacons.
To be still an effective mechanism for developers, the User Agent should make the best effort to
transmit the data including making multiple attempts to transmit the data in presence of transient
network or server errors, even though it uses POST to transmit the data.
Makes it sound like a valid solution. I'm not quite familiar with the sentry/raven protocol. Does the payload contain a time? Because when using sendBeacon, the data may be transmitted later, in case with bad connection even hours later. The spec doesn't specify how long the browser has to try to send the beacon.
Additionally, CORS-Rules apply as well, but that - naturally - only counts for headers (like Cookie, etc) since theres no body read (MUST ignore any entity bodies returned in the response
). If I'm correct, this means Beacons are really just a fire&forget XHR POST request thats queued & clever timed by the UA.
A simple polyfill should be pretty easy.
Packets are definitely time based. It's optional to send a timestamp attribute with the data, if it's not sent server time will be applied.
IMO this is a reasonable idea to polyfill, especially if modern versions of Chrome support it.
Main use case for this IMO is to catch errors which happen on or before unloading - errors in an unload handler, errors in a beforeunload handler, or errors in a click handler that would prevent the browser from navigating away (but due to the error it doesn't). Since the browser starts unloading as soon as the error occurs, image requests might or might not be sent depending on the browser and the timing. Also, some browsers delay unloading if there is a pending image request, which degrades perceived page performance.
Just a heads up: as far as I know navigator.sendBeacon
doesn't support setting custom headers (such as X-Sentry-Auth
), so Sentry might need to continue support authorization via query parameters.
I don't see us using sendBeacon
for a few reasons:
Main use case for this IMO is to catch errors which happen on or before unloading
The only way I see this working is if we ourselves instrument unload/beforeunload
to record that, "yes, the page is unloading". Then we could switch to sendBeacon
knowing that it might be the only reliable way to transmit data from that point, and we don't care about the response anyways (the callback would never fire since we're changing pages).
Looks like Google Analytics let you set sendBeacon
as the transport:
Furthermore they say,
Currently, analytics.js only uses navigator.sendBeacon if the transport mechanism is set to 'beacon'. However, in the future, analytics.js will likely switch to using 'beacon' as the default mechanism in browsers that support it.
Agree with Ben on this one. It seems like a lot of overhead without providing enough functionality to justify it. I'll leave it marked as a "Feature" so we can get back to this discussion one day if we decide that it's a good time to revisit this.
Question. How can we reasonably ensure that errors are logged to sentry that occur shortly before (or during) unloading? The beacon API seemed the best way to achieve this...
We had a beacon transport in the past, it worked fine until Chromium disabled it without notice. Our SDK didn't work properly so we decided to drop the beacon transport again. It will most likely stay like this until it's considered standard.