Skip to content

RUM-13441: [Cronet] Migrating okHttp to new instrumentation API#3180

Open
satween wants to merge 3 commits intodevelopfrom
tvaleev/feature/RUM-13441-Okhttp-instrumentation
Open

RUM-13441: [Cronet] Migrating okHttp to new instrumentation API#3180
satween wants to merge 3 commits intodevelopfrom
tvaleev/feature/RUM-13441-Okhttp-instrumentation

Conversation

@satween
Copy link
Contributor

@satween satween commented Feb 16, 2026

What does this PR do?

  • Moves OkHttp instrumentation to the new networking-library agnostic approach.
  • Introduces a new plugin-based instrumentation API for OkHttp network monitoring, replacing the legacy DatadogInterceptor/TracingInterceptor/DatadogEventListener
    approach (all classes kept for the backward compatibility)
    with a single unified entry point:
OkHttpClient.Builder()
  .configureDatadogInstrumentation(
      rumInstrumentationConfiguration = RumNetworkInstrumentationConfiguration(),
      apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(tracedHosts)
  )
  .build()

same as for Cronet

CronetEngine.Builder()
  .configureDatadogInstrumentation(
      rumInstrumentationConfiguration = RumNetworkInstrumentationConfiguration(),
      apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(tracedHosts)
  )
  .build()

Motivation

  • Moving instrumentation logic into library-agnostic approach
  • Simplifying and unifying instrumentation configuration for all networking libraries
  • Making Datadog instrumentation configuration latest in the configuration chain

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)

@satween satween requested a review from a team as a code owner February 16, 2026 22:10
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 57939dbb75

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +44 to +45
val tracingState = registry.update(call) { _, state ->
apmNetworkInstrumentation.onRequest(state.requestInfo)

Choose a reason for hiding this comment

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

P1 Badge Trace the current network request instead of cached state

RequestTracingStateRegistry.register() stores call.request() only once, but this interceptor later calls onRequest(state.requestInfo) and then proceeds with tracingState.requestInfo. For redirects/retries (where OkHttp invokes network interceptors again with a follow-up request) or when earlier interceptors mutate the request, this reuses a stale request and can drop URL/header/body changes (for example auth/signature headers), causing incorrect outbound calls and spans. The tracing state should be refreshed from chain.request() on each intercept.

Useful? React with 👍 / 👎.

Comment on lines +26 to +27
val requestInfo = registry.get(call)?.requestInfo
val okHttpRequest = (requestInfo as? OkHttpRequestInfo)?.originalRequest

Choose a reason for hiding this comment

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

P1 Badge Proceed RUM interception with the live chain request

This adapter reads requestInfo from the registry (initialized from call.request() before application interceptors run) and then calls chain.proceed(okHttpRequest), so any request mutations made by interceptors earlier in the chain are discarded. In practice, headers or URL rewrites added upstream can be lost, which can break authenticated requests and make RUM track a different request than the one the app intended to send. Use chain.request() as the source of truth and keep the registry for correlation metadata only.

Useful? React with 👍 / 👎.

@satween satween force-pushed the tvaleev/feature/RUM-13974-APM-DNI branch from 8f048a3 to 91ec6c5 Compare February 17, 2026 03:18
@satween satween force-pushed the tvaleev/feature/RUM-13441-Okhttp-instrumentation branch from 57939db to 404f86e Compare February 17, 2026 03:23

@Test
@Repeat(10)
fun executionResultsMustBeSimilarWhen_rateLimited_okhttp_comparison() = asyncTest {
Copy link
Member

Choose a reason for hiding this comment

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

Seems the unit test is testing the equality not similarity, if so it should be renamed to executionResultsMustBeSameWhen_rateLimited_okhttp_comparison. Also, is it needed to execute 10 times on CI?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test tests that different instrumentation produces similar spans for requests. Technically speaking they are not 100% same (because spanId and traceId are unique), but spans structure (parent-child) structure, some http attributes (status codes, url, etc) should be the same. So it's called "similar". Let me know if you think this is confusing

@satween satween force-pushed the tvaleev/feature/RUM-13974-APM-DNI branch 6 times, most recently from cb8e557 to 62046e7 Compare February 20, 2026 17:52
@satween satween requested a review from a team as a code owner February 26, 2026 09:44
@satween satween force-pushed the tvaleev/feature/RUM-13974-APM-DNI branch 2 times, most recently from d4a5e23 to f3b2a1e Compare February 27, 2026 10:55
Base automatically changed from tvaleev/feature/RUM-13974-APM-DNI to develop February 27, 2026 13:30
@satween satween force-pushed the tvaleev/feature/RUM-13441-Okhttp-instrumentation branch from 404f86e to bc7f3d2 Compare March 2, 2026 16:44
@satween satween force-pushed the tvaleev/feature/RUM-13441-Okhttp-instrumentation branch from bc7f3d2 to 9e872b7 Compare March 11, 2026 13:47
*/
@ExperimentalTraceApi
@ExperimentalRumApi
fun OkHttpClient.Builder.configureDatadogInstrumentation(
Copy link
Member

Choose a reason for hiding this comment

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

We need to deprecate then existing interceptors in favor of this

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 would do that after dogfooding (before release) in a separate PR

@0xnm
Copy link
Member

0xnm commented Mar 12, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e872b76aa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +31 to +34
val taggedRequest = OkHttpRequestInfoBuilder(call.request().newBuilder())
.addTag(UUID::class.java, UUID.randomUUID())

requestTracingStateByCall[call] = RequestTracingState(taggedRequest)

Choose a reason for hiding this comment

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

P2 Badge Track RUM state from post-interceptor request

The registry is initialized from call.request() before application interceptors run, and in RUM-only mode there is no subsequent registry.update(...) to refresh it with the final request seen by RumInstrumentationOkHttpAdapter.startResource(...). If an upstream app interceptor rewrites method/URL/body, timing events (sendWaitForResourceTimingEvent / sendTiming) are emitted with a different resource key than the started resource, so resource timing can be dropped for those calls.

Useful? React with 👍 / 👎.

) {
internal val method: String
get() = requestParams.method

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this on purpose?

assertThat(engine.distributedTracingInstrumentation).isNull()
}

@OptIn(ExperimentalRumApi::class)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this needed? The CronetIntegrationPluginTest class already has this annotation.

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