Skip to content

Conversation

jonathanmos
Copy link
Member

@jonathanmos jonathanmos commented Sep 1, 2025

What does this PR do?

Adds support for Apollo GraphQL requests, which is essentially native support for graphQL (until now only available from cross-platform).

Caveats:
Support only for V4 of Apollo-Kotlin. If there will be enough demand for V3 we may extend support there.

How does it work:

  • Added a new ApolloInterceptor plugin under a new integration module: dd-sdk-android-apollo
  • This plugin adds some headers to graphQL requests containing request fields: operationName, operationType, variables and payload.
  • Added logic inside DatadogInterceptor to catch these headers and send them as part of RumResourceScope. After extracting the data from these headers they are removed so they won't be sent onwards to the host.
  • All the fields are sent by default with the exception of payload. To send it the user must set a new configuration option inside the DatadogApolloInterceptor constructor -> DatadogApolloInterceptor(captureGraphQLPayloads = true)
  • To setup, the user adds our ApolloInterceptor plugin to their ApolloClient configuration (as described in the Readme)

Motivation

Add GraphQL support to native.

Additional Notes

Anything else we should know when reviewing?

  • Notice that we can't test this at the moment as part of the sample because it's graphQL. This means that the payload flag is also not added to the sampleApplication because it would have no effect. I'm testing it manually but we'll have to create an automatic testing solution.
  • The new module adds about 4MB in terms of dependency size and two additional MIT dependency licenses (apollo-kotlin and a uuid dependency that apollo-kotlin uses internally).

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)

@jonathanmos jonathanmos marked this pull request as ready for review September 1, 2025 08:53
@jonathanmos jonathanmos requested review from a team as code owners September 1, 2025 08:53
Copy link
Member

@0xnm 0xnm left a comment

Choose a reason for hiding this comment

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

I briefly reviewed the RUM module part of it and left some suggestions.

It is good to see finally GraphQL support in the SDK!

ambushwork
ambushwork previously approved these changes Sep 2, 2025
@urseberry urseberry self-assigned this Sep 2, 2025
@jonathanmos jonathanmos force-pushed the jmoskovich/rum-11196/apollo-integration branch 2 times, most recently from ba2a0f6 to 287327c Compare September 8, 2025 08:44
@jonathanmos jonathanmos force-pushed the jmoskovich/rum-11196/apollo-integration branch from 287327c to e19f43a Compare September 9, 2025 08:24
@codecov-commenter
Copy link

codecov-commenter commented Sep 9, 2025

Codecov Report

❌ Patch coverage is 74.10714% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.61%. Comparing base (8a51cb5) to head (9463462).
⚠️ Report is 18 commits behind head on develop.

Files with missing lines Patch % Lines
...n/com/datadog/android/okhttp/DatadogInterceptor.kt 59.57% 14 Missing and 5 partials ⚠️
...datadog/android/internal/network/GraphQLHeaders.kt 0.00% 5 Missing ⚠️
...datadog/android/apollo/DatadogApolloInterceptor.kt 93.33% 1 Missing and 1 partial ⚠️
...droid/apollo/internal/DefaultVariablesExtractor.kt 60.00% 2 Missing ⚠️
...roid/rum/internal/domain/scope/RumResourceScope.kt 96.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2845      +/-   ##
===========================================
- Coverage    70.81%   70.61%   -0.20%     
===========================================
  Files          809      812       +3     
  Lines        29482    29582     +100     
  Branches      4940     5075     +135     
===========================================
+ Hits         20875    20887      +12     
- Misses        7246     7267      +21     
- Partials      1361     1428      +67     
Files with missing lines Coverage Δ
...roid/rum/internal/domain/scope/RumResourceScope.kt 93.66% <96.00%> (-0.61%) ⬇️
...datadog/android/apollo/DatadogApolloInterceptor.kt 93.33% <93.33%> (ø)
...droid/apollo/internal/DefaultVariablesExtractor.kt 60.00% <60.00%> (ø)
...datadog/android/internal/network/GraphQLHeaders.kt 0.00% <0.00%> (ø)
...n/com/datadog/android/okhttp/DatadogInterceptor.kt 73.08% <59.57%> (-6.36%) ⬇️

... and 93 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

urseberry
urseberry previously approved these changes Sep 9, 2025
Copy link
Member

@0xnm 0xnm left a comment

Choose a reason for hiding this comment

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

Looks alright! I've added a few comments and suggestions.

Comment on lines +218 to +252
private fun chainWithoutDDHeaders(
internalLogger: InternalLogger,
originalChain: Interceptor.Chain
): Interceptor.Chain {
return if (hasGraphQLHeaders(originalChain.request().headers)) {
try {
object : Interceptor.Chain by originalChain {
override fun proceed(request: Request): Response {
val cleanedRequest = request.newBuilder().apply {
removeGraphQLHeaders(this)
}.build()
return originalChain.proceed(cleanedRequest)
}
}
} catch (e: IllegalStateException) {
internalLogger.log(
level = InternalLogger.Level.WARN,
target = InternalLogger.Target.MAINTAINER,
messageBuilder = { ERROR_FAILED_BUILD_REQUEST },
throwable = e
)
originalChain // fallback to the original request
} catch (e: IOException) {
internalLogger.log(
level = InternalLogger.Level.WARN,
target = InternalLogger.Target.MAINTAINER,
messageBuilder = { ERROR_FAILED_BUILD_REQUEST },
throwable = e
)
originalChain // fallback to the original request
}
} else {
originalChain
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need to add such complexity by building the chain. What you can do here is just remove headers before .proceed() call and move them under the Request.tag and take them out from there when response arrives.

By doing this they won't go out and you still have access to the necessary information.

@jonathanmos jonathanmos force-pushed the jmoskovich/rum-11196/apollo-integration branch from d58a8b3 to 9463462 Compare September 15, 2025 08:18
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.

5 participants