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

Document Apollo3 GraphQL client errors #7135

Merged
merged 24 commits into from
Jun 15, 2023
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
efbd5cb
Document Apollo3 GraphQL client errors
marandaneto Jun 13, 2023
0ccc1d2
fix
marandaneto Jun 13, 2023
2235724
add grouping note
marandaneto Jun 13, 2023
cfe2208
Update src/platforms/android/configuration/integrations/apollo3.mdx
marandaneto Jun 14, 2023
2def437
Update src/platforms/android/configuration/integrations/apollo3.mdx
marandaneto Jun 14, 2023
d264bb1
Update src/platforms/android/configuration/integrations/apollo3.mdx
marandaneto Jun 14, 2023
1ba2035
Update src/platforms/android/configuration/integrations/apollo3.mdx
marandaneto Jun 14, 2023
b9d9c1a
Update src/platforms/android/configuration/integrations/apollo3.mdx
marandaneto Jun 14, 2023
8218c37
Update src/platforms/android/configuration/integrations/apollo3.mdx
marandaneto Jun 14, 2023
7da4eaa
Update src/platforms/android/configuration/integrations/apollo3.mdx
marandaneto Jun 14, 2023
5a0123e
Use correct license identifer in package.json (#7141)
cleptric Jun 13, 2023
ec90a51
Add hint about electron SDK version in source maps troubleshooting do…
lforst Jun 13, 2023
230e395
Bump API schema to f88c7be1 (#7146)
getsentry-release Jun 13, 2023
7790df5
Fix: Move team plan banner for metric alerts (#7147)
vivianyentran Jun 13, 2023
3191a86
add redirects for sourcemaps best practices (#7148)
shanamatthews Jun 13, 2023
23dcbcd
Add redirects (#7149)
shanamatthews Jun 13, 2023
26fe322
Remove link to Apple debug symbols (#7142)
kahest Jun 14, 2023
5c51859
Add React Router Info to Onboarding Wizard (#7136)
ale-cota Jun 14, 2023
5bd1813
Re-add troubleshooting guide for legacy source map upload (#7126)
lforst Jun 14, 2023
b27558c
Restore troubleshooting sourcemaps docs for platforms that support de…
lforst Jun 14, 2023
466c281
Add iOS source context info to RN debug symbols page (#7143)
krystofwoldrich Jun 14, 2023
c14aaea
fix
marandaneto Jun 14, 2023
f7cd85a
Add Apple Debug Symbols Sentry CLI link to RN manual setup page (#7151)
krystofwoldrich Jun 14, 2023
bd9f68e
Merge branch 'master' into chore/apollo3-graphql-errors
marandaneto Jun 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 88 additions & 1 deletion src/platforms/android/configuration/integrations/apollo3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ Add `Interceptors` to `ApolloClient.Builder` using `ApolloBuilderExtensions`:
import com.apollographql.apollo3.ApolloClient;
import io.sentry.apollo3.SentryApolloBuilderExtensionsKt;

ApolloClient apollo = SentryApolloBuilderExtensionsKt.sentryTracing(new ApolloClient.Builder())
ApolloClient apollo = SentryApolloBuilderExtensionsKt
Copy link
Member

Choose a reason for hiding this comment

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

m: is there a reason why we use a different snippet here than below?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just did indentation here, the code already exists, not sure I follow the question.
There's a difference between Kotlin vs Java as well.

Copy link
Member

Choose a reason for hiding this comment

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

Oh right, you only need SentryApolloBuilderExtensionsKt on Java, and the snippets below are only in Kotlin, sorry for the confusion. Should we add Java snippets for client errors as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be honest, I think we should go Kotlin first and only, less to maintain, nowadays IDEs auto convert the code on copy and paste.
Also, the Apollo3 is designed for KMP, Kotlin first, 90%+ won't be using Kotlin anymore most likely.

Copy link
Member

Choose a reason for hiding this comment

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

That's fair, we could add a section "you can also use this in Java like this: " and the other snippets only in Kotlin. But not necesserily in ths PR

.sentryTracing(new ApolloClient.Builder())
.serverUrl("https://your-api-host/")
.build();
```
Expand Down Expand Up @@ -118,3 +119,89 @@ val apollo = ApolloClient.builder()
}
.build()
```

## GraphQL Client Errors

Once enabled, this feature will automatically capture GraphQL client errors such as bad operations and response codes, and report them to Sentry as error events. Each error event will contain the `request` and `response` data, including the `url`, `status_code`, and `data` (stringified `query`).

Sentry will group GraphQL client errors by the `operationName`, `operationType`, and `statusCode`, so that you can easily see the number of errors that happened for each.

This is an opt-in feature and can be enabled by setting the `captureFailedRequests` option to `true`:

```kotlin
import com.apollographql.apollo3.ApolloClient
import io.sentry.apollo3.sentryTracing

val apollo = ApolloClient.builder()
.serverUrl("https://your-api-host/")
.sentryTracing(captureFailedRequests = true)
.build()
```

By default, only GraphQL client errors with a response that includes the [errors](https://spec.graphql.org/October2021/#sec-Errors) array will be captured as error events.

GraphQL client errors from every target (`.*` regular expression) are automatically captured, but you can change this behavior by setting the `failedRequestTargets` option with either a regular expression or a plain `String`. A plain string must contain at least one of the items from the list. Plain strings don't have to be full matches, meaning the URL of a request is matched when it contains a string provided through the option.

```kotlin
import com.apollographql.apollo3.ApolloClient
import io.sentry.apollo3.sentryTracing

val apollo = ApolloClient.builder()
.serverUrl("https://your-api-host/")
.sentryTracing(captureFailedRequests = true, failedRequestTargets = listOf("myapi.com"))
.build()
```

By default, error events won't contain `Headers` or `Cookies`, but you can change this behavior by setting the `sendDefaultPii` option to `true`:

```xml {filename:AndroidManifest.xml}
<application>
<meta-data android:name="io.sentry.send-default-pii" android:value="true" />
</application>
```

Error events will contain the raw bodies of GraphQL requests and responses, which may include sensitive data. To avoid this, parameterize your queries using the [variables](https://spec.graphql.org/October2021/#sec-Language.Variables) field. [Relay](/product/relay) will then run [PII Data Scrubbing](/product/relay/#pii-data-scrubbing), automatically transforming values into `[Filtered]`.

Alternatively, you can customize the event and scrub the data yourself.

### Customize or Drop the Error Event

To customize or drop the error event, you'll need to do a [manual initialization](/platforms/android/configuration/manual-init/) of the Sentry Android SDK. The captured error event can then be customized or dropped with a `BeforeSendCallback`:

```kotlin
import io.sentry.android.core.SentryAndroid
import io.sentry.SentryOptions.BeforeSendCallback
import com.apollographql.apollo3.api.http.HttpRequest
import com.apollographql.apollo3.api.http.HttpResponse
import io.sentry.TypeCheckHint.APOLLO_REQUEST
import io.sentry.TypeCheckHint.APOLLO_RESPONSE

SentryAndroid.init(this) { options ->
// Add a callback that will be used before the event is sent to Sentry.
// With this callback, you can modify the event or, when returning null, also discard the event.
options.beforeSend = BeforeSendCallback { event, hint ->
val request = hint.getAs(APOLLO_REQUEST, HttpRequest::class.java)
val response = hint.getAs(APOLLO_RESPONSE, HttpResponse::class.java)

// customize or drop the event
event
}
}
```

### Automatically and Manually Captured GraphQL Client Errors

When `captureFailedRequests` is enabled, some GraphQL client libraries will throw unchecked exceptions, such as the `ApolloException` and its implementations. This means the error event will be captured by both the GraphQL client library and the Sentry Android SDK. To avoid this, we recommend identifying these errors and using the `Sentry.captureException` method instead of capturing them manually:

```kotlin
import io.sentry.Sentry
import com.apollographql.apollo3.exception.ApolloException

try {
// If this API call returns the `errors` array, it will be captured as an error event by the `SentryApollo3HttpInterceptor`.
return apolloClient.query(LaunchDetailsQuery(launchId)).execute()
} catch (e: ApolloException) {
// Do not manually capture this exception to avoid duplicated error events.
// Sentry.captureException(e)
}
```