Skip to content

Issue #1327: apply resourceEventMapper to auto tracked XHR resources - #1328

Open
teplymax wants to merge 2 commits into
DataDog:developfrom
teplymax:teplymax/apply-resourceEventMapper-to-auto-tracked-resources
Open

Issue #1327: apply resourceEventMapper to auto tracked XHR resources#1328
teplymax wants to merge 2 commits into
DataDog:developfrom
teplymax:teplymax/apply-resourceEventMapper-to-auto-tracked-resources

Conversation

@teplymax

@teplymaxteplymax commented Jul 7, 2026

Copy link
Copy Markdown

Issue #1327

What does this PR do?

This PR applies resourceEventMapper to auto-tracked XHR resources before they are started
natively, so applications can sanitize resource URLs before they are reported to Datadog.

For example, a resource URL containing PII can be rewritten before reporting:

https://testurl.com?phone=12345

to:

https://testurl.com?phone=PHONE_PLACEHOLDER

With this change, the mapper can:

  • drop an auto-tracked XHR resource by returning null,
  • inspect and sanitize the resource URL through resourceContext.responseURL,
  • update resource context before native RUM tracking starts,
  • stay in sync when DdRum.registerResourceEventMapper or
    DdRum.unregisterResourceEventMapper is called after SDK initialization.

The main implementation changes are:

  • DdSdkReactNative.initialize passes the configured resourceEventMapper to
    DdRumResourceTracking.startTracking.
  • DdRum.startResource applies the mapper before calling native startResource; if the
    mapper returns null, no native resource is started.
  • DdRum.stopResource no longer sends the _dd.resource.drop_resource marker when the
    mapper returns null, because dropped resources are now skipped before native start.
  • DdRum.registerResourceEventMapper and DdRum.unregisterResourceEventMapper update the
    active XHR tracking proxy.
  • DdRumResourceTracking.updateResourceEventMapper forwards mapper changes to the request
    proxy when resource tracking is active.
  • XHRProxy.onTrackingUpdate supports partial updates, so tracing sample rate and mapper
    updates can be applied independently.
  • ResourceReporter converts Datadog's internal RUMResource into a
    mapper-compatible resource event before running mappers.
  • ResourceEvent is exported and the native resource mapper type now includes
    resourceContext.

Motivation

We need to sanitize resource URLs reported to Datadog to prevent leaking PII through query
parameters or other URL components.

The current automatic XHR resource tracking flow does not give resourceEventMapper enough
control at the point where the native resource is started.

Filtering decisions that depend on the request URL can happen too late: the native resource
has already been started, and dropping the event requires sending a native-side drop marker
later during stopResource.

This makes it difficult to use resourceEventMapper as the single JavaScript-level place for
resource filtering and sanitization. It also creates a gap between frontend and mobile
instrumentation: our frontend can already sanitize resource URLs before reporting them, and we
want mobile apps to support the same privacy guarantees and implementation model.

The main use cases are:

  • replacing PII values in resource URLs with placeholders before reporting,
  • dropping non-first-party resources,
  • dropping resources when an application-level condition is not met,
  • sanitizing the resource URL before it is passed to native RUM tracking,
  • keeping auto-tracked XHR resources aligned with manually tracked resource mapper behavior.

Additional Notes

The important behavior change is that the keep/drop decision now happens before native
startResource.

DdRum.startResource builds a mapper-compatible resource event with the original resource key,
default XHR metadata, context, timestamp, and the request URL exposed as
resourceContext.responseURL:

constmappedEvent=this.resourceEventMapper.applyEventMapper({
key,statusCode: 0,kind: 'xhr',size: -1,
context,
timestampMs,resourceContext: {responseURL: url}asXMLHttpRequest});if(!mappedEvent){returngenerateEmptyPromise();}conststartUrl=mappedEvent.resourceContext?.responseURL??url;

For kept resources, native tracking starts with the original resource key for lifecycle
correlation and the mapped URL/context for reporting:

this.nativeRum.startResource(key,method,startUrl,encodeAttributes(mappedEvent.context),timestampMs);

If the mapper returns null later during stopResource, JavaScript returns without calling
native code. A resource dropped at start time has no native resource entry to stop:

if(!mappedEvent){returngenerateEmptyPromise();}

For auto-tracked XHR resources, ResourceReporter converts the internal RUMResource into the
shape expected by ResourceEventMapper before running mappers:

consttoReportedResourceEvent=(resource: RUMResource): ReportedResourceEvent=>({
...resource,statusCode: resource.response.statusCode,kind: resource.request.kind,size: resource.response.size,context: {},timestampMs: resource.timings.stopTime,resourceContext: resource.resourceContext,attributes: {}});

Mappers run sequentially against the latest mapped resource. Returning null drops the
resource; returning an object merges the mapper output back into the resource:

for(constmapperofthis.getMappers()){constmappedResource=mapper(modifiedResource);if(mappedResource===null){return;}modifiedResource={
...modifiedResource,
...mappedResource};}

If the mapper sanitizes resourceContext.responseURL, that sanitized URL is used when
reporting the resource:

reportResource({
...modifiedResource,request: {
...modifiedResource.request,url:
modifiedResource.resourceContext?.responseURL??modifiedResource.request.url}});

Runtime mapper registration is forwarded to active resource tracking:

registerResourceEventMapper(resourceEventMapper: ResourceEventMapper){this.resourceEventMapper=generateResourceEventMapper(resourceEventMapper);DdRumResourceTracking.updateResourceEventMapper(resourceEventMapper);}unregisterResourceEventMapper(){this.resourceEventMapper=generateResourceEventMapper(undefined);DdRumResourceTracking.updateResourceEventMapper(undefined);}

The chages were tested with appropriate patch being applied to production app:

@datadog+mobile-react-native+3.5.1.patch

Everything works as expected.

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

CopilotAI review requested due to automatic review settings July 7, 2026 08:54
@teplymax
teplymax requested a review from a team as a code ownerJuly 7, 2026 08:54
@teplymax
teplymaxforce-pushed the teplymax/apply-resourceEventMapper-to-auto-tracked-resources branch from 686202b to 440d774CompareJuly 7, 2026 08:55

CopilotAI 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 updates React Native RUM resource instrumentation so resourceEventMapper can sanitize or drop auto-tracked XHR resources before native RUM startResource is invoked, aligning auto-tracked behavior with manually tracked resources and improving privacy controls (e.g., URL PII redaction).

Changes:

  • Apply resourceEventMapper earlier in the resource lifecycle (notably in DdRum.startResource) and propagate mapper updates to active XHR tracking.
  • Extend resource event shapes/types to include resourceContext and export ResourceEvent for mapper compatibility.
  • Update XHR auto-tracking pipeline (XHRProxy/ResourceReporter) and add/adjust unit tests for the new behavior.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/XHRProxy.tsPass mapper into ResourceReporter and support partial tracking updates (sample rate vs mapper).
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/ResourceReporter.tsConvert internal RUMResource to mapper-compatible shape; run mappers and allow URL override via resourceContext.responseURL.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/internalDevResourceBlocklist.tsUpdate mapper typing to match the new ResourceMapper signature.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/XHRProxy/DatadogRumResource/tests/ResourceReporter.test.tsAdd coverage for mapper-driven URL sanitization and runtime mapper updates.
packages/core/src/rum/instrumentation/resourceTracking/requestProxy/interfaces/RequestProxy.tsAllow partial updates in onTrackingUpdate (optional sample rate + optional mapper).
packages/core/src/rum/instrumentation/resourceTracking/DdRumResourceTracking.tsxAccept mapper at tracking start and add updateResourceEventMapper forwarding to the proxy.
packages/core/src/rum/instrumentation/resourceTracking/tests/DdRumResourceTracking.test.tsAdd coverage for registering/unregistering resource mapper after tracking starts.
packages/core/src/rum/eventMappers/resourceEventMapper.tsExport ResourceEvent and include resourceContext in the native mapper type path.
packages/core/src/rum/DdRum.tsApply mapper at startResource (using resourceContext.responseURL) and forward mapper updates to resource tracking.
packages/core/src/rum/tests/DdRum.test.tsUpdate expectations for drop behavior (no native start/stop when mapper returns null).
packages/core/src/DdSdkReactNative.tsxPass configured resourceEventMapper into DdRumResourceTracking.startTracking.
packages/core/src/tests/DdSdkReactNative.test.tsxAdjust expectations for the updated resource tracking initialization and start behavior.
Comments suppressed due to low confidence (1)

packages/core/src/rum/tests/DdRum.test.ts:1680

  • Current tests only cover the case where the resource mapper returns null for both start and stop. Add a test for the case where the mapper keeps the event at startResource() but returns null at stopResource() (e.g., based on statusCode), to ensure the native resource is still properly stopped/dropped and doesn't leak.
 it('does not start or stop the resource if the mapper returns null', async () => {
const resourceEventMapper: ResourceEventMapper = resource => {
return null;
};

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadpackages/core/src/rum/DdRum.ts Outdated
Comment threadpackages/core/src/rum/DdRum.ts
Comment threadpackages/core/src/rum/DdRum.ts
Comment threadpackages/core/src/rum/DdRum.ts Outdated
CopilotAI review requested due to automatic review settings July 7, 2026 09:05

CopilotAI 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 12 out of 12 changed files in this pull request and generated 4 comments.

Comment threadpackages/core/src/rum/DdRum.ts Outdated
Comment threadpackages/core/src/rum/DdRum.ts
CopilotAI review requested due to automatic review settings July 8, 2026 12:32

CopilotAI 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 14 out of 14 changed files in this pull request and generated 2 comments.

Comment threadpackages/core/src/rum/DdRum.ts
Sign up for freeto 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.

2 participants

@teplymax