Skip to content

Conversation

rk-for-zulip
Copy link
Contributor

@rk-for-zulip rk-for-zulip commented May 8, 2020

Alternate to #4086. Started life as a continuation of #4086, but has grown sufficiently divergent that it probably shouldn't be unified with that one.

Sentry events created by this code (by forcing 200 OK responses to be seen as errors) can be seen here. (Note that some early events have the Zulip error code sent up as the HTTP status; this may be ignored, as may any earlier events not titled "random error string".)

Notes about the patchset:

  • The first three commits are Remove objectToParams #4090, and should be reviewed there. (Hence the "blocked-on-other-work" label.) (Done!)
  • The commit api: Stop marking failure with breadcrumbs. can be omitted, but I'd suggest retaining it.
  • The final commit is sort of unrelated, but saved me several times from accidentally pushing onto an existing release. I recommend adopting something like it.
  • Although there's a callout to View uploaded files without needing to be logged in to the realm in the browser. #4089, neither of these PRs need to block the other; the notional "merge conflict" can be resolved as a relatively-small followup commit.

Fixes #3864.

@rk-for-zulip rk-for-zulip requested review from chrisbobbe and gnprice May 8, 2020 02:19
@rk-for-zulip rk-for-zulip added the blocked on other work To come back to after another related PR, or some other task. label May 8, 2020
@rk-for-zulip rk-for-zulip removed the blocked on other work To come back to after another related PR, or some other task. label May 8, 2020
The Sentry dashboard is bugging us to upgrade our SDK, so do that. The
changelog [0] suggests that there are no significant alterations from
our perspective -- just dependency upgrades and the occasional bugfix.

(Under the hood, there _has_ been a major-version update to the Sentry
Android SDK. Tests so far have shown no issues, however.)

[0] https://github.com/getsentry/sentry-react-native/blob/3f17c82a44f/CHANGELOG.md
Taken directly from the TypeScript source, with only the substitution
of `Promise` for `PromiseLike`.
All type information taken from Sentry itself (with some minor
copyediting of the comments).
Tell the Sentry service that, when bucketing events, it should (also)
consider the error code and HTTP status of any caught `ApiError`s to
be important distinguishing characteristics.

Partially addresses zulip#3864.

Note that, although this is a response to a change made by Sentry to
no longer use error messages as aggregator-hints (at least for custom
error types?), we don't add `.message` to the event fingerprint. The
contents of the `msg` field are mostly intended for humans, and often
contain instance-specific data [1]; when the error message _was_ used
as part of the fingerprint, we had the opposite problem as today --
namely, dozens of different Sentry issues corresponding to the same
bug.

[1] And in the future, it may even be localized: see issue zulip#3692.
@gnprice
Copy link
Member

gnprice commented May 8, 2020

Thanks!

I think this bucketing / disaggregation strategy will work OK.

In apiFetch I'm a little concerned about the many different things named more or less "params". Some of that is pre-existing, but there's a growth here in types with similar names to each other, also often defined by indirection so it takes several steps to look up what's in them.

One thing in particular I'm sure we can improve is this description in terms of apiFetch:

/**
 * Additional parameters passed to apiFetch.
 *
 * This is a strict subset of `RequestOptions`, the actual argument type of
 * `fetch()`.
 */
type FetchParams = {| method: string, body?: string | FormData |};

when there's another type ApiFetchParams which is different.

 * @param isSilent: True if this fetch should not trigger the network activity
 *    indicator on iOS. Should be `true` only for long-polling API calls.
 *    Deprecated as of iOS 13.

This is interesting new information! Can you link to your source for the deprecation? Probably best added in a separate commit, too.

The build.gradle change at the end looks helpful. Let's move the bulk of it to a function, though -- so the code in that central place can be short, like

        // Unofficial builds normally don't report to Sentry.  If this one will
        // (say, to test Sentry), mark it as distinct from an official build.
        if (project.hasProperty('sentry') && !project.hasProperty('signed')) {
            versionName += localVersionSuffix()
        }

@rk-for-zulip
Copy link
Contributor Author

In apiFetch I'm a little concerned about the many different things named more or less "params".

Ain't that the truth. 😑 I'd say it was much worse before, though – at least now the typechecker will yell at you if you get them crossed.

One thing in particular I'm sure we can improve is this description in terms of apiFetch:

/**
 * Additional parameters passed to apiFetch.

... not least because it was intended to read "Additional parameters passed to fetch()", not "apiFetch". 😓 I remember correcting that, too – it must have gotten lost in one of the many rebase-shuffles. (If that's all that got lost, I'll be happy.)

This is interesting new information! Can you link to your source for the deprecation? Probably best added in a separate commit, too.

Apple's own documentation marks it as deprecated. I haven't found any official note that the deprecation occurred in iOS 13 specifically – Apple's stopped updating "What's New in iOS", alas – though tweets and SO posts are easily found.

The link probably belongs in src/utils/networkActivity.js, regardless.

The build.gradle change at the end looks helpful. Let's move the bulk of it to a function, though

👍

`fetch()` accepts many possible extra parameters [1], all of which are
optional. In the absence of an existing type definition for `fetch()`,
a `params` type of `{}` is a reasonably good reflection of that.

However, nowadays we _do_ have type definitions for `fetch()`. Besides
that, in practice, we use only a very small subset of those parameters.
While it was apparently intended to allow `apiFetch` to be called from
arbitrary call sites, that's not functionality we've ever used; since
antiquity [1], we've always opted to go through `apiGet` and its
siblings.

So, encode the tiny slice of `RequestOptions` that we actually use
into `apiFetch`'s parameter type. Anyone who finds they want a larger
subset can expand it as needed.

(And, incidentally, stop exporting apiFetch.)

[1] 999e20a, 2016-11-11.
There are too many things called "params" here, and we're about to add
a third. Let's disambiguate a bit.

`getFetchParams` takes a type that has `FetchParams` in its name and
returns a type that doesn't. Rename it to use the name of the Flow
library type that it actually returns.
@gnprice
Copy link
Member

gnprice commented May 8, 2020

at least now the typechecker will yell at you if you get them crossed.

True!

I haven't found any official note that the deprecation occurred in iOS 13 specifically – Apple's stopped updating "What's New in iOS", alas – though tweets and SO posts are easily found.

Ah, that's one of their lovely "archived" docs pages.

IME when I've found some Apple docs like that, there is a new up-to-date version -- they just didn't bother to link to it, or migrate the old stuff to keep it all in one place.

In this instance, googling [what's new in ios] finds this page on their new docs site:
https://developer.apple.com/documentation/ios_ipados_release_notes

which has detailed release notes that pick up where that archived page left off.

(Dunno if this particular deprecation is mentioned there, though.)

The link probably belongs in src/utils/networkActivity.js, regardless.

Sure. Then I think the deprecation can be left out in the other place -- it's not really actionable from the perspective of a caller of apiCall.

@rk-for-zulip
Copy link
Contributor Author

rk-for-zulip commented May 8, 2020

In this instance, googling [what's new in ios] finds this page on their new docs site:
https://developer.apple.com/documentation/ios_ipados_release_notes

[...] (Dunno if this particular deprecation is mentioned there, though.)

Sadly, it's not: that page seems to be generally less comprehensive than the older version was. I did eventually find a mention here, though. (Until they silently remove it, at least. Perhaps I should link to the Internet Archive's version.)

Sure. Then I think the deprecation can be left out in the other place -- it's not really actionable from the perspective of a caller of apiCall.

👍

Now that everything is well-typed and more explicitly named, we can
start shuffling things around in preparation for laying new pipe.

In particular, group together the parameters of `apiFetch`, as well as
most of the parameters of `apiCall`. Document accordingly.
Collect API call data in a more human-friendly form on API call
failure, in preparation for logging it to various sources.
Log the version of the route and params found in the `CallData`,
rather than the encoded and possibly concatenated versions found in
the `ApiFetchParams`.
We only log the details of failed API calls in sentry. Say so.

(Note that a summary of all API calls is still logged as a breadcrumb
by Sentry itself, via its interception of `XMLHttpRequest`.)
Sentry error events are often delayed: there may be multiple API
calls to arbitrary routes in between the actual failed call and
the breadcrumb-list being sent.

To avoid any question as to which logged failure resulted in the
current error event, attach the call and response as "extra" data.

See discussion at zulip#4063.
All of this data is now available in other ways; this breadcrumb is
entirely redundant.
At time of writing, this handles all embedded data in all routes in
all API calls used by the mobile app.

However, that won't be true forever. In particular, PR zulip#4089
introduces code for a new endpoint `getTemporaryFileUri` which
contains an arbitrary filename. This endpoint will have to be handled
differently -- either by calling `apiCall` directly, or by adding a
bit more plumbing through `apiGet` and friends.
(See internal comments for motivation.)
As noted in the added comments, the `networkActivityIndicatorVisible`
API has been deprecated.

(This entire file, as well as the upstairs logic that triggers it,
should probably be removed once fewer than 1% of our iOS users are on
versions prior to iOS 13, and possibly sooner.)
@rk-for-zulip rk-for-zulip marked this pull request as ready for review May 8, 2020 21:46
@rk-for-zulip rk-for-zulip changed the title [REVIEWABLE] API errors in Sentry, v2 API errors in Sentry, v2 May 8, 2020
@gnprice
Copy link
Member

gnprice commented May 8, 2020

I did eventually find a mention here, though. (Until they silently remove it, at least. Perhaps I should link to the Internet Archive's version.)

Cool. FTR at least for this thread's sake, here's what it says:

The network activity indicator is deprecated in iOS 13 and on devices with edge-to-edge displays. In iOS 12 and earlier, and on devices without edge-to-edge displays, a network activity indicator spins in the status bar at the top of the screen as networking occurs. It disappears when networking is complete. This indicator looks just like an activity indicator and is noninteractive.

Probably we should just keep setting it until we no longer support iOS versions older than 13, unless we learn that it's causing some kind of trouble on devices where it doesn't have anything to do.

@rk-for-zulip rk-for-zulip changed the title API errors in Sentry, v2 [NEEDS iOS TESTING] API errors in Sentry, v2 May 8, 2020
@rk-for-zulip
Copy link
Contributor Author

Probably we should just keep setting it until we no longer support iOS versions older than 13, unless we learn that it's causing some kind of trouble on devices where it doesn't have anything to do.

I expect it to be only to us, in that every byte of code has a cost. But I don't actually have a strong opinion on that; feel free to trim the parenthetical off that last's commit message, if you like.

The more important thing – which I've just indicated in the PR title – is that ⚠️ this patchset needs to be tested on iOS. ⚠️ I obviously haven't been able to do so, and it contains a Sentry upgrade with a minor version bump.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Distinguish API errors in Sentry

2 participants