Skip to content

Add addViewLoadingTime() public API#4180

Draft
MaelNamNam wants to merge 1 commit intomainfrom
mael.lilensten/manually_report_view_loading_time
Draft

Add addViewLoadingTime() public API#4180
MaelNamNam wants to merge 1 commit intomainfrom
mael.lilensten/manually_report_view_loading_time

Conversation

@MaelNamNam
Copy link

@MaelNamNam MaelNamNam commented Feb 13, 2026

Motivation

Allow developers to manually report when a view has finished loading, instead of relying solely on auto-detection. This is needed for complex async loading patterns (e.g., SPAs with deferred data fetching, skeleton screens) where the SDK's heuristic-based auto-detection cannot accurately determine when the view is truly ready.

This brings the Browser SDK to parity with the iOS and Android SDKs which already expose this API.

Changes

Adds a new public API DD_RUM.addViewLoadingTime(options?) that:

  • Computes loading time as elapsed time since the current view started
  • Suppresses auto-detected loading time on first manual call
  • Defaults to first-call-wins semantics; supports { overwrite: true } to replace a previously set value
  • Handles pre-start buffering (calls before init() are buffered and drained with preserved timestamps)
  • Emits telemetry usage tracking (addViewLoadingTime feature)
  • Gracefully no-ops when called on ended/expired views

Files changed:

File Change
packages/core/src/domain/telemetry/telemetryEvent.types.ts Add AddViewLoadingTime to browser telemetry union
packages/rum-core/src/domain/view/viewMetrics/trackCommonViewMetrics.ts setManualLoadingTime() with auto-detection suppression
packages/rum-core/src/domain/view/trackViews.ts addLoadingTime() on newView with overwrite policy
packages/rum-core/src/boot/startRum.ts Wire addLoadingTime through startRumEventCollection
packages/rum-core/src/boot/rumPublicApi.ts Public API surface, JSDoc, Strategy type, telemetry
packages/rum-core/src/boot/preStartRum.ts Pre-start buffering with timestamp capture

Test instructions

Running tests

# Unit tests
yarn test:unit --spec packages/rum-core/src/domain/view/trackViews.spec.ts
yarn test:unit --spec packages/rum-core/src/boot/rumPublicApi.spec.ts
yarn test:unit --spec packages/rum-core/src/boot/preStartRum.spec.ts

# E2E (requires setup first)
yarn test:e2e:init
yarn test:e2e -g "has a manual loading time"

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

@MaelNamNam MaelNamNam requested a review from a team as a code owner February 13, 2026 10:27
@github-actions
Copy link


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@cit-pr-commenter-54b7da
Copy link

cit-pr-commenter-54b7da bot commented Feb 13, 2026

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 169.43 KiB 170.24 KiB +829 B +0.48%
Rum Profiler 4.29 KiB 4.29 KiB 0 B 0.00%
Rum Recorder 24.54 KiB 24.54 KiB 0 B 0.00%
Logs 56.72 KiB 56.72 KiB 0 B 0.00%
Flagging 944 B 944 B 0 B 0.00%
Rum Slim 126.26 KiB 127.04 KiB +792 B +0.61%
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.0045 0.0039 -13.33%
RUM - add action 0.0142 0.0132 -7.04%
RUM - add error 0.0133 0.0128 -3.76%
RUM - add timing 0.0028 0.0025 -10.71%
RUM - start view 0.0134 0.0121 -9.70%
RUM - start/stop session replay recording 0.0007 0.0006 -14.29%
Logs - log message 0.0155 0.0142 -8.39%
🧠 Memory Performance
Action Name Base Memory Consumption Local Memory Consumption 𝚫
RUM - add global context 27.68 KiB 27.41 KiB -276 B
RUM - add action 51.86 KiB 51.63 KiB -234 B
RUM - add timing 26.47 KiB 25.84 KiB -644 B
RUM - add error 57.53 KiB 57.67 KiB +143 B
RUM - start/stop session replay recording 25.70 KiB 24.95 KiB -768 B
RUM - start view 453.18 KiB 468.65 KiB +15.46 KiB
Logs - log message 47.21 KiB 46.78 KiB -443 B

🔗 RealWorld

@datadog-datadog-prod-us1
Copy link

datadog-datadog-prod-us1 bot commented Feb 13, 2026

✅ Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

🎯 Code Coverage (details)
Patch Coverage: 77.42%
Overall Coverage: 77.27% (-0.01%)

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

@MaelNamNam MaelNamNam changed the title ✨ feat(rum): add addViewLoadingTime() public API Add addViewLoadingTime() public API Feb 13, 2026
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: f4e10304d9

ℹ️ 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 +755 to +756
no_active_view: isResult && 'no_active_view' in result,
overwritten: isResult && 'overwritten' in result && result.overwritten !== false,

Choose a reason for hiding this comment

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

P2 Badge Default telemetry flags to false for buffered calls

When addViewLoadingTime() is called before init, strategy.addLoadingTime(...) returns undefined, so isResult && ... evaluates to undefined for both no_active_view and overwritten. Those fields are then omitted from the telemetry payload instead of being sent as explicit booleans, which contradicts the AddViewLoadingTime usage schema and makes pre-start telemetry inaccurate. Please coerce these expressions to false when no result is available.

Useful? React with 👍 / 👎.

Add a new public API `DD_RUM.addViewLoadingTime(options?)` that allows
developers to manually report when a view has finished loading.

- Computes loading time as elapsed time since view start
- Suppresses auto-detected loading time on first manual call
- First-call-wins by default; `{ overwrite: true }` to replace
- Pre-start buffering with preserved call timestamps
- Telemetry usage tracking
- Gracefully no-ops on ended/expired views
- Unit tests + E2E test
@MaelNamNam MaelNamNam force-pushed the mael.lilensten/manually_report_view_loading_time branch from f4e1030 to 169989b Compare February 13, 2026 10:32
},
addLoadingTime(callTimestamp?: TimeStamp, overwrite = false) {
if (endClocks) {
return { no_active_view: true as const }
Copy link
Collaborator

Choose a reason for hiding this comment

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

🔨 warning: ‏These are not following the standard naming convention. we use camelCase and convert what need to be to pascal_case just before sending the event.

const hadPreviousManual = isLoadingTimeSetManually
const hadAutoValue = !isLoadingTimeSetManually && commonViewMetrics.loadingTime !== undefined

// Stop auto-detection entirely on first manual call (CONTEXT decision)
Copy link
Collaborator

Choose a reason for hiding this comment

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

❓ question: ‏what does (CONTEXT decision) means?

isLoadingTimeSetManually = true
commonViewMetrics.loadingTime = loadingTime

// Return overwrite source for Phase 2 telemetry
Copy link
Collaborator

Choose a reason for hiding this comment

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

❓ question: ‏what's Phase 2 telemetry?

Comment on lines +752 to +757
addTelemetryUsage({
feature: 'addViewLoadingTime',
no_view: false,
no_active_view: isResult && 'no_active_view' in result,
overwritten: isResult && 'overwritten' in result && result.overwritten !== false,
})
Copy link
Collaborator

Choose a reason for hiding this comment

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

❓ question: TelemetryUsage is meant to understand which API the customer are using and with which option when available. I don't think we should return run-time analysis like this.

Suggested change
addTelemetryUsage({
feature: 'addViewLoadingTime',
no_view: false,
no_active_view: isResult && 'no_active_view' in result,
overwritten: isResult && 'overwritten' in result && result.overwritten !== false,
})
addTelemetryUsage({
feature: 'addViewLoadingTime',
overwrite
})

* elapsed time since the view started. By default, the first call sets the loading time and
* subsequent calls are no-ops. Use `{ overwrite: true }` to replace a previously set value.
*
* See [Override RUM View Loading Time](https://docs.datadoghq.com/real_user_monitoring/browser/advanced_configuration/) for further information.
Copy link
Collaborator

Choose a reason for hiding this comment

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

🔨 warning: "Override RUM View Loading Time" does not exist at that link ‏

/**
* Schema of browser specific features usage
*/
// [MANUAL] AddViewLoadingTime added pending upstream rum-events-format schema sync
Copy link
Collaborator

Choose a reason for hiding this comment

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

❓ question: ‏I did not find any PR related to that in rum-event-format

const result = strategy.addLoadingTime(callTimestamp, options?.overwrite ?? false)

// For pre-start buffered calls, result is undefined so we emit best-guess default values.
const isResult = result && typeof result === 'object'
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 suggestion: ‏use Types to prevent runtime assertion

@MaelNamNam MaelNamNam marked this pull request as draft February 13, 2026 19:10
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.

2 participants