From 34dcac98ba775665179f70217950e96152c1c1c4 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Fri, 17 Jul 2026 14:44:00 +0200 Subject: [PATCH] feat(apollo): Apply outgoing request body policy Use the Data Collection outgoing request body decision when attaching failed GraphQL request content in Apollo 3 and 4. Retain request body size metadata and continue applying GraphQL document and variable controls when body collection is enabled. Co-Authored-By: Claude --- .../apollo3/SentryApollo3HttpInterceptor.kt | 22 ++++++++++--------- .../SentryApollo3InterceptorClientErrors.kt | 19 ++++++++++++++++ .../apollo4/SentryApollo4HttpInterceptor.kt | 22 ++++++++++--------- ...pollo4BuilderExtensionsClientErrorsTest.kt | 19 ++++++++++++++++ 4 files changed, 62 insertions(+), 20 deletions(-) diff --git a/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt b/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt index c59166f850..835c0d7576 100644 --- a/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt +++ b/sentry-apollo-3/src/main/java/io/sentry/apollo3/SentryApollo3HttpInterceptor.kt @@ -365,16 +365,18 @@ constructor( request.body?.let { bodySize = it.contentLength - val buffer = Buffer() - - try { - it.writeTo(buffer) - data = GraphqlUtils.filterRequestBody(buffer.readUtf8(), scopes.options) - } catch (e: Throwable) { - scopes.options.logger.log(SentryLevel.ERROR, "Error reading the request body.", e) - // continue because the response body alone can already give some insights - } finally { - buffer.close() + if (scopes.options.dataCollectionResolver.isOutgoingRequestBody) { + val buffer = Buffer() + + try { + it.writeTo(buffer) + data = GraphqlUtils.filterRequestBody(buffer.readUtf8(), scopes.options) + } catch (e: Throwable) { + scopes.options.logger.log(SentryLevel.ERROR, "Error reading the request body.", e) + // continue because the response body alone can already give some insights + } finally { + buffer.close() + } } } } diff --git a/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorClientErrors.kt b/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorClientErrors.kt index 8e9e083a47..46c93a8313 100644 --- a/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorClientErrors.kt +++ b/sentry-apollo-3/src/test/java/io/sentry/apollo3/SentryApollo3InterceptorClientErrors.kt @@ -5,6 +5,7 @@ import com.apollographql.apollo3.api.http.HttpRequest import com.apollographql.apollo3.api.http.HttpResponse import com.apollographql.apollo3.exception.ApolloException import io.sentry.Hint +import io.sentry.HttpBodyType import io.sentry.IScopes import io.sentry.SentryIntegrationPackageStorage import io.sentry.SentryOptions @@ -268,6 +269,24 @@ class SentryApollo3InterceptorClientErrors { ) } + @Test + fun `data collection can disable outgoing request body`() { + val sut = + fixture.getSut(responseBody = fixture.responseBodyNotOk) { + dataCollection.httpBodies = setOf(HttpBodyType.INCOMING_RESPONSE) + } + executeQuery(sut) + + verify(fixture.scopes) + .captureEvent( + check { + assertEquals(193L, it.request!!.bodySize) + assertNull(it.request!!.data) + }, + any(), + ) + } + @Test fun `data collection can disable the GraphQL document independently`() { val sut = diff --git a/sentry-apollo-4/src/main/java/io/sentry/apollo4/SentryApollo4HttpInterceptor.kt b/sentry-apollo-4/src/main/java/io/sentry/apollo4/SentryApollo4HttpInterceptor.kt index cca1175918..afb3c9cba7 100644 --- a/sentry-apollo-4/src/main/java/io/sentry/apollo4/SentryApollo4HttpInterceptor.kt +++ b/sentry-apollo-4/src/main/java/io/sentry/apollo4/SentryApollo4HttpInterceptor.kt @@ -364,16 +364,18 @@ constructor( request.body?.let { bodySize = it.contentLength - val buffer = Buffer() - - try { - it.writeTo(buffer) - data = GraphqlUtils.filterRequestBody(buffer.readUtf8(), scopes.options) - } catch (e: Throwable) { - scopes.options.logger.log(SentryLevel.ERROR, "Error reading the request body.", e) - // continue because the response body alone can already give some insights - } finally { - buffer.close() + if (scopes.options.dataCollectionResolver.isOutgoingRequestBody) { + val buffer = Buffer() + + try { + it.writeTo(buffer) + data = GraphqlUtils.filterRequestBody(buffer.readUtf8(), scopes.options) + } catch (e: Throwable) { + scopes.options.logger.log(SentryLevel.ERROR, "Error reading the request body.", e) + // continue because the response body alone can already give some insights + } finally { + buffer.close() + } } } } diff --git a/sentry-apollo-4/src/test/java/io/sentry/apollo4/SentryApollo4BuilderExtensionsClientErrorsTest.kt b/sentry-apollo-4/src/test/java/io/sentry/apollo4/SentryApollo4BuilderExtensionsClientErrorsTest.kt index 42637a4092..625838225a 100644 --- a/sentry-apollo-4/src/test/java/io/sentry/apollo4/SentryApollo4BuilderExtensionsClientErrorsTest.kt +++ b/sentry-apollo-4/src/test/java/io/sentry/apollo4/SentryApollo4BuilderExtensionsClientErrorsTest.kt @@ -8,6 +8,7 @@ import com.apollographql.apollo.api.http.HttpRequest import com.apollographql.apollo.api.http.HttpResponse import com.apollographql.apollo.exception.ApolloException import io.sentry.Hint +import io.sentry.HttpBodyType import io.sentry.IScopes import io.sentry.SentryIntegrationPackageStorage import io.sentry.SentryOptions @@ -282,6 +283,24 @@ abstract class SentryApollo4BuilderExtensionsClientErrorsTest( ) } + @Test + fun `data collection can disable outgoing request body`() { + val sut = + fixture.getSut(responseBody = fixture.responseBodyNotOk) { + dataCollection.httpBodies = setOf(HttpBodyType.INCOMING_RESPONSE) + } + executeQuery(sut) + + verify(fixture.scopes) + .captureEvent( + check { + assertEquals(193L, it.request!!.bodySize) + assertNull(it.request!!.data) + }, + any(), + ) + } + @Test fun `data collection can disable the GraphQL document independently`() { val sut =