Skip to content

[RUM-17907] Add optional global Fetch resource tracking - #1360

Merged
marco-saia-datadog merged 2 commits into
developfrom
carlosnogueira/RUM-17907/expo-fetch-resource-tracking
Aug 13, 2026
Merged

[RUM-17907] Add optional global Fetch resource tracking#1360
marco-saia-datadog merged 2 commits into
developfrom
carlosnogueira/RUM-17907/expo-fetch-resource-tracking

Conversation

@cdn34dd

@cdn34dd cdn34dd commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Adds optional resource tracking for global Fetch implementations, including Expo Fetch, through the new trackFetchResources configuration option.

XHR instrumentation remains enabled independently so requests made through Axios or direct XMLHttpRequest calls continue to be tracked. The Fetch and XHR proxies coordinate to prevent duplicate resource events when the active Fetch implementation is itself backed by XHR.

Motivation

Expo Fetch can bypass the SDK’s existing XHR instrumentation, which means those network requests are currently missing from RUM resource tracking.

This change allows users to explicitly enable Fetch instrumentation while preserving the existing XHR coverage and avoiding duplicate events across different Fetch implementations.

Changes

  • Adds the optional trackFetchResources SDK configuration, disabled by default.
  • Adds a Fetch proxy that reports global Fetch requests as RUM resources.
  • Reuses the existing resource reporting, tracing, baggage, GraphQL, and filtering logic.
  • Keeps XHR instrumentation enabled for Axios and direct XHR requests.
  • Prevents duplicate events when the active Fetch implementation uses XHR internally.
  • Supports programmatic, automatic, and file-based SDK configuration.
  • Adds unit and integration coverage for Fetch tracking and Fetch/XHR coordination.
  • Documents the new configuration option and expected behavior.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests
  • 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)
  • If this PR is auto-generated, please make sure also to manually update the code related to the change

Add trackFetchResources configuration to instrument Expo and other
global Fetch implementations while keeping XHR tracking  enabled.
Coordinate Fetch and XHR proxies to prevent duplicate events for
XHR-backed Fetch requests.
@cdn34dd

cdn34dd commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

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

Copy link
Copy Markdown

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: 9f45729efb

ℹ️ 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".

response: Response;
resourceReporter: ResourceReporter;
}) => {
resourceReporter.reportResource({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Extract GraphQL errors before reporting Fetch resources

When DatadogLink({ trackErrors: true }) sends a GraphQL request through the global Fetch path, processRequestHeader records context.graphql.trackErrors, but this function reports immediately without reading the response body. Unlike reportXhr, it therefore never populates context.graphql.errors, so enabling trackFetchResources makes the documented GraphQL response errors disappear from RUM for Fetch/Apollo requests; parse and filter a clone of the response before reporting when the operation type and error-tracking flag are set.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Addressed in 839644b

Comment on lines +80 to +82
this.context = null;
this.originalFetch = null;
this.installedFetch = null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep retained Fetch wrappers callable after tracking stops

When another library installs a Fetch wrapper after Datadog and captures the current global.fetch, the identity check intentionally leaves that later wrapper installed, but clearing originalFetch makes the captured Datadog wrapper pass null into trackFetch. Subsequent calls through the later wrapper then throw at originalFetch.call(...) instead of making a network request; the retained wrapper must either keep its original delegate or bypass instrumentation after tracking stops.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Addressed in 839644b

@cdn34dd
cdn34dd marked this pull request as ready for review August 10, 2026 08:27
@cdn34dd
cdn34dd requested a review from a team as a code owner August 10, 2026 08:27
Copilot AI lite review requested due to automatic review settings August 10, 2026 08:27
@cdn34dd
cdn34dd requested a review from a team as a code owner August 10, 2026 08:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an opt-in RUM resource-tracking capability for global Fetch implementations (including Expo’s global fetch) via a new trackFetchResources configuration flag, while keeping existing XHR instrumentation enabled and coordinating the two to reduce duplicate resource events for XHR-backed fetch implementations.

Changes:

  • Introduces a new FetchProxy and shared “common” request-context/header/reporting utilities to reuse existing tracing, baggage, GraphQL metadata, and filtering logic across Fetch and XHR.
  • Adds the trackFetchResources configuration option across programmatic, auto-instrumentation, and file-based configuration (including schema + docs); default remains false.
  • Adds unit/integration tests covering Fetch tracking behavior and Fetch/XHR de-duplication behavior.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/core/src/sdk/DatadogProvider/tests/initialization.test.tsx Updates initialization expectations to include trackFetchResources default.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.ts Refactors XHR proxy to use shared request context/header logic and suppress XHR reporting during Fetch-proxy synchronous execution to reduce duplicates.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/tests/ResourceReporter.test.ts Points tests at the shared ResourceReporter.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/tests/internalDevResourceBlocklist.test.ts Updates tests to use the shared dev-resource blocklist.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/tests/XHRProxy.test.ts Updates XHR proxy tests to use the shared ResourceReporter.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/FetchProxy/FetchProxy.ts Adds Fetch proxy implementation that reports global fetch requests as RUM resources and injects instrumentation headers.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/FetchProxy/tests/FetchProxy.test.ts Adds unit tests for Fetch proxy reporting, header handling, sampling updates, and unwrapping behavior.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/common/resourceTiming.ts Cleans up timing helper comments while keeping behavior intact.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/common/ResourceReporter.ts Adjusts imports and constructor parameter naming for the shared reporter.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/common/requestHeaders.ts Adds shared header processing and instrumentation header generation (tracing, baggage, GraphQL, tracked-by).
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/common/RequestContext.ts Adds shared request context builder (timer, tracing attrs, baggage aggregation, GraphQL attrs).
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/common/internalDevResourceBlocklist.ts Relocates dev-resource filtering to shared location and updates import paths.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/common/FetchProxyState.ts Adds shared state to mark synchronous execution under Fetch proxy for XHR de-duplication.
packages/core/src/rum/instrumentation/resourceTracking/DdRumResourceTracking.tsx Installs both XHR and optional Fetch proxies; manages lifecycle/update/stop across multiple proxies.
packages/core/src/rum/instrumentation/resourceTracking/tests/DdRumResourceTracking.test.ts Adds coverage for enabling/disabling Fetch tracking and Fetch/XHR coordination (including XHR-backed fetch).
packages/core/src/DdSdkReactNative.tsx Plumbs trackFetchResources from configuration into resource tracking start.
packages/core/src/config/FileBasedConfiguration.type.ts Extends JSON config typing to include trackFetchResources.
packages/core/src/config/FileBasedConfiguration.ts Serializes trackFetchResources into file-based JSON config output.
packages/core/src/config/features/RumConfiguration.type.ts Adds typed trackFetchResources option with documentation.
packages/core/src/config/features/RumConfiguration.ts Adds default + instance field for trackFetchResources.
packages/core/src/config/async/AutoInstrumentationConfiguration.ts Adds trackFetchResources into auto-instrumentation config defaults/parameters.
packages/core/src/config/tests/FileBasedConfiguration.test.ts Updates file-based config tests for trackFetchResources.
packages/core/src/config/tests/fixtures/configuration-all-fields.json Adds fixture coverage for trackFetchResources.
packages/core/src/tests/DdSdkReactNativeConfiguration.test.ts Updates configuration expectations to include trackFetchResources default.
packages/core/src/tests/DdSdkReactNative.test.tsx Updates tests to pass trackFetchResources through SDK init and validate plumbing.
packages/core/README.md Documents trackFetchResources behavior and relationship to XHR tracking.
packages/core/datadog-configuration.schema.json Adds schema support for trackFetchResources under RUM configuration.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI review requested due to automatic review settings August 13, 2026 14:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (2)

packages/core/src/rum/instrumentation/resourceTracking/requestProxy/FetchProxy/FetchProxy.ts:71

  • FetchProxy.onTrackingStop() restores global fetch, but any previously captured reference to the installed wrapper will continue to report resources because the wrapper closes over the initial context argument (options: context) instead of consulting this.context. This means instrumentation can remain active after DdRumResourceTracking.stopTracking() if another library retained the wrapper.
                originalFetch,
                fetchThis: this.providers.fetchGlobal,
                headersType: this.providers.headersType,
                resourceReporter: this.providers.resourceReporter,
                options: context

packages/core/src/rum/instrumentation/resourceTracking/DdRumResourceTracking.tsx:91

  • DdRumResourceTracking only checks globalThis.fetch before installing FetchProxy, but FetchProxy.createWithResourceReporter() dereferences the global Headers constructor. In runtimes where fetch exists but Headers is missing/undefined, enabling trackFetchResources will throw during installation instead of safely no-oping.
            } else {
                const fetchProxy = FetchProxy.createWithResourceReporter();
                fetchProxy.onTrackingStart(requestProxyOptions);
                this._requestProxies.push(fetchProxy);
                InternalLog.log(

@datadog-prod-us1-5

datadog-prod-us1-5 Bot commented Aug 13, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 839644b | Docs | Datadog PR Page | Give us feedback!

const responseSize = calculateResponseSize(xhrProxy);

const context = xhrProxy._datadog_xhr;
if (!context) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Super nit: on line 150 we renamed this as requestContext, maybe it would be nice to keep naming the same here, as they are both referring to the contents of xhrProxy._datadog_xhr.

@marco-saia-datadog
marco-saia-datadog merged commit 7520981 into develop Aug 13, 2026
12 checks passed
@marco-saia-datadog
marco-saia-datadog deleted the carlosnogueira/RUM-17907/expo-fetch-resource-tracking branch August 13, 2026 15:54
@sbarrio sbarrio mentioned this pull request Aug 14, 2026
4 tasks
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