diff --git a/src/platforms/android/configuration/integrations/apollo3.mdx b/src/platforms/android/configuration/integrations/apollo3.mdx index 9764da9cef0284..2d134fc16891ff 100644 --- a/src/platforms/android/configuration/integrations/apollo3.mdx +++ b/src/platforms/android/configuration/integrations/apollo3.mdx @@ -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 + .sentryTracing(new ApolloClient.Builder()) .serverUrl("https://your-api-host/") .build(); ``` @@ -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} + + + +``` + +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) +} +```