Skip to content

💥 always collect early requests#4285

Open
BenoitZugmeyer wants to merge 5 commits intov7from
benoit/enable-early-request-collection
Open

💥 always collect early requests#4285
BenoitZugmeyer wants to merge 5 commits intov7from
benoit/enable-early-request-collection

Conversation

@BenoitZugmeyer
Copy link
Member

@BenoitZugmeyer BenoitZugmeyer commented Mar 5, 2026

Motivation

Resources initiated early in the page lifecycle (before the SDK is fully initialized) were
previously missed unless trackEarlyRequests was explicitly enabled. This change makes that
behavior the default, ensuring all requests are captured regardless of when they start.

Changes

  • Remove the legacy matchRequestResourceEntry path (polling performance.getEntriesByName)
    — the registry-based approach is now the only path
  • Remove trackEarlyRequests option (now always enabled, option is a breaking removal)
  • Remove ResponseBodyAction.WAIT — no longer needed since timing always comes from PerformanceResourceTiming
  • Unify RumFetchResourceEventDomainContext, RumXhrResourceEventDomainContext, and RumOtherResourceEventDomainContext
    into a single RumResourceEventDomainContext

Test instructions

yarn dev-server start
yarn dev-server intake clear

Create sandbox/test-early-requests.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Test early requests</title>
    <script>fetch('/ok')</script>
    <script src="/datadog-rum.js"></script>
    <script>
      window.domainContexts = []
      DD_RUM.init({
        clientToken: 'xxx', applicationId: 'xxx', trackResources: true, proxy: '/proxy',
        beforeSend(event, context) {
          if (event.type === 'resource') window.domainContexts.push({ url: event.resource.url, context })
        },
      })
    </script>
  </head>
  <body>
    <button id="fetch-btn" onclick="fetch('/ok')">Make fetch</button>
    <button id="xhr-btn" onclick="var x=new XMLHttpRequest();x.open('GET','/ok');x.send()">Make XHR</button>
  </body>
</html>
agent-browser open http://localhost:8080/test-early-requests.html
agent-browser click '#fetch-btn'
agent-browser click '#xhr-btn'
agent-browser tab new

# 1. Verify pre-init fetch is collected (method: null = no request context = pre-init)
yarn dev-server intake rum-resources | jq '[.resource.url, .resource.type, .resource.method]'
# Expected: includes ["http://localhost:8080/ok","fetch",null] (pre-init), ["http://localhost:8080/ok","fetch","GET"], ["http://localhost:8080/ok","xhr","GET"]

# 2. Verify unified domain context shape
agent-browser tab 0
agent-browser eval 'window.domainContexts.map(({url,context})=>({url,keys:Object.keys(context).sort(),isManual:context.isManual,xhrIsXMLHttpRequest:context.xhr instanceof XMLHttpRequest,handlingStackType:typeof context.handlingStack}))'
# Expected: all resources share keys [error,handlingStack,isAborted,isManual,performanceEntry,requestInit,requestInput,response,xhr]
# XHR resource has xhrIsXMLHttpRequest:true, post-init fetch has handlingStackType:"string"

yarn dev-server stop
rm sandbox/test-early-requests.html

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

@datadog-datadog-prod-us1
Copy link

datadog-datadog-prod-us1 bot commented Mar 5, 2026

⚠️ Tests

Fix all issues with BitsAI or with Cursor

⚠️ Warnings

🧪 2 Tests failed

rum resources › fetch abort support › track aborted fetch from rum/resources.scenario.ts (Datadog) (Fix with Cursor)
resources.scenario.ts:199:15 track aborted fetch

[Webkit] › rum/resources.scenario.ts:199:15 › rum resources › fetch abort support › track aborted fetch 

    Error: expect(received).toBeTruthy()

    Received: undefined

      217 |
      218 |         const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'fetch')
...
rum resources › XHR abort support › track aborted XHR from rum/resources.scenario.ts (Datadog) (Fix with Cursor)
resources.scenario.ts:96:15 track aborted XHR

[Webkit] › rum/resources.scenario.ts:96:15 › rum resources › XHR abort support › track aborted XHR 

    Error: expect(received).toBeTruthy()

    Received: undefined

      182 |     function expectXHR(intakeRegistry: IntakeRegistry) {
      183 |       const resourceEvent = intakeRegistry.rumResourceEvents.find((event) => event.resource.type === 'xhr')
...

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 85.71%
Overall Coverage: 77.30% (+0.09%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 5aa1db1 | Docs | Datadog PR Page | Was this helpful? React with 👍/👎 or give us feedback!

@cit-pr-commenter-54b7da
Copy link

cit-pr-commenter-54b7da bot commented Mar 5, 2026

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 170.95 KiB 169.91 KiB -1.04 KiB -0.61%
Rum Profiler 6.18 KiB 6.18 KiB 0 B 0.00%
Rum Recorder 27.48 KiB 27.48 KiB 0 B 0.00%
Logs 56.51 KiB 56.42 KiB -89 B -0.15%
Rum Slim 128.19 KiB 127.16 KiB -1.03 KiB -0.80%
Worker 23.63 KiB 23.63 KiB 0 B 0.00%
🚀 CPU Performance
Action Name Base CPU Time (ms) Local CPU Time (ms) 𝚫%
RUM - add global context 0.0069 0.0041 -40.58%
RUM - add action 0.019 0.0144 -24.21%
RUM - add error 0.0167 0.014 -16.17%
RUM - add timing 0.0033 0.0026 -21.21%
RUM - start view 0.0154 0.0126 -18.18%
RUM - start/stop session replay recording 0.001 0.0007 -30.00%
Logs - log message 0.0223 0.0189 -15.25%
🧠 Memory Performance
Action Name Base Memory Consumption Local Memory Consumption 𝚫
RUM - add global context 27.55 KiB 32.38 KiB +4.83 KiB
RUM - add action 51.99 KiB 57.33 KiB +5.34 KiB
RUM - add timing 26.39 KiB 34.20 KiB +7.81 KiB
RUM - add error 55.79 KiB 61.45 KiB +5.66 KiB
RUM - start/stop session replay recording 25.34 KiB 33.90 KiB +8.56 KiB
RUM - start view 462.57 KiB 468.61 KiB +6.03 KiB
Logs - log message 44.62 KiB 48.70 KiB +4.08 KiB

🔗 RealWorld

the old `matchRequestResourceEntry` approach (polling `performance.getEntriesByName` on
request completion) is superseded by the registry-based path that was behind the
`trackEarlyRequests` flag. remove the flag and always use the registry, which also
drops the `pageStateHistory` dependency and the frozen-state duration workaround.
The WAIT action was introduced so that fetch request duration could be
derived from waiting for the response body to be fully consumed. Now that
resource timing always comes from PerformanceResourceTiming (early
request collection is the only path), waiting for the body before
reporting a resource is no longer necessary.

This also simplifies readBytesFromStream, which is now always called to
collect bytes (never just to wait).
Early request collection is now always enabled, making this option a
no-op. Remove it from the public API, internal configuration, and
telemetry.
now that fetch and xhr resources always have a performance entry and may or may
not have request information, separate context types per request type make less
sense. replace RumFetchResourceEventDomainContext, RumXhrResourceEventDomainContext
and RumOtherResourceEventDomainContext with a single RumResourceEventDomainContext.
@BenoitZugmeyer BenoitZugmeyer force-pushed the benoit/enable-early-request-collection branch from 8c3d1f0 to c99a9b7 Compare March 17, 2026 16:53
@BenoitZugmeyer BenoitZugmeyer marked this pull request as ready for review March 17, 2026 16:54
@BenoitZugmeyer BenoitZugmeyer requested a review from a team as a code owner March 17, 2026 16:54
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: c99a9b768b

ℹ️ 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 42 to 45
const performanceResourceSubscription = createPerformanceObservable(configuration, {
type: RumPerformanceEntryType.RESOURCE,
buffered: true,
}).subscribe((entries) => {

Choose a reason for hiding this comment

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

P1 Badge Restore request fallback when resource timings are unavailable

This change makes resource collection depend exclusively on PerformanceObserver entries, so when a fetch/xhr timing is missing or filtered out (for example the negative-duration entries explicitly dropped in packages/rum-core/src/browser/performanceObservable.ts:306-310), no resource event is emitted even though REQUEST_COMPLETED was observed. Prior to this commit, the request-based path still produced a resource in that scenario, so this regresses resource/tracing/GraphQL data completeness in affected browsers and edge cases.

Useful? React with 👍 / 👎.

- mention reviewing all PR commits, not just the latest diff
- document `agent-browser tab 0` + `agent-browser eval` for inspecting window state
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.

1 participant