Skip to content

✨[PANA-5156] Expose better session replay internal API#4018

Merged
sethfowler-datadog merged 1 commit intomainfrom
seth.fowler/PANA-5156-expose-better-session-replay-internal-api
Dec 17, 2025
Merged

✨[PANA-5156] Expose better session replay internal API#4018
sethfowler-datadog merged 1 commit intomainfrom
seth.fowler/PANA-5156-expose-better-session-replay-internal-api

Conversation

@sethfowler-datadog
Copy link
Contributor

Motivation

The session replay code in the browser SDK currently exposes a small internal API. This API's primary use case is to support unit testing of Datadog-internal code that integrates with session replay in some way.

Today, unfortunately, this API is quite unstable and hard to use correctly. The reason is that the function we expose (serializeNodeWithId) is too low-level. Using this function requires constructing a very complex configuration object, involving constants and functions with types that aren't exposed outside of the SDK code. Worse, the details of this configuration object have been changing quite a bit lately, so keeping up with the changes is becoming harder and harder.

Instead of exposing an unstable internal function, let's define an explicit, stable internal API that callers in other repos can depend on. (Of course, stability is relative here; this API is explicitly not subject to semver.)

Changes

This PR exposes two new internal API functions:

  • takeFullSnapshot() takes a snapshot of the entire document.
  • takeNodeSnapshot() snapshots the DOM subtree of an individual node.

Both require no configuration at all, though you can pass in a partial RumConfiguration to override the defaults if you want.

I've added tests for these functions to demonstrate usage and show that they work as expected.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.

@sethfowler-datadog sethfowler-datadog requested a review from a team as a code owner December 9, 2025 15:44
export * from '../types'

export { serializeNode, serializeNode as serializeNodeWithId } from '../domain/record'
export { takeFullSnapshot, takeNodeSnapshot, serializeNode as serializeNodeWithId } from '../domain/record'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

serializeNode() was just added in a previous PR in this PR stack, so nothing's using it yet. takeNodeSnapshot() is a superior alternative, so I've removed serializeNode() in favor of the new function. I plan to remove serializeNodeWithId(), too, once we've switched all callers over to the new APIs.

doTakeFullSnapshot(
timeStampNow(),
SerializationKind.INITIAL_FULL_SNAPSHOT,
emitRecord,
Copy link
Contributor

Choose a reason for hiding this comment

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

We must be sure that doTakeFullSnapshot will always be synchronous for this to work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed! In the near term, for better or worse, I think we'll be stuck with that limitation anyway, because if we yield, the DOM might mutate out from under us. (It'd be interesting to investigate a full snapshot algorithm that could tolerate that, though...)

Base automatically changed from seth.fowler/PANA-5123-assign-node-ids-top-down-when-serializing to main December 15, 2025 22:02
@sethfowler-datadog sethfowler-datadog requested a review from a team as a code owner December 15, 2025 22:02
@cit-pr-commenter
Copy link

cit-pr-commenter bot commented Dec 15, 2025

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 164.34 KiB 164.34 KiB +1 B +0.00%
Rum Profiler 4.32 KiB 4.32 KiB 0 B 0.00%
Rum Recorder 20.02 KiB 20.03 KiB +16 B +0.08%
Logs 56.14 KiB 56.14 KiB 0 B 0.00%
Flagging 944 B 944 B 0 B 0.00%
Rum Slim 121.62 KiB 121.62 KiB 0 B 0.00%
Worker 23.63 KiB 23.63 KiB 0 B 0.00%
🚀 CPU Performance

Pending...

🧠 Memory Performance
Action Name Base Memory Consumption Local Memory Consumption 𝚫
RUM - add global context 25.67 KiB 25.06 KiB -628 B
RUM - add action 48.08 KiB 47.51 KiB -583 B
RUM - add timing 24.94 KiB 25.59 KiB +665 B
RUM - add error 53.95 KiB 52.10 KiB -1.84 KiB
RUM - start/stop session replay recording 24.68 KiB 23.83 KiB -875 B
RUM - start view 422.07 KiB 421.97 KiB -102 B
Logs - log message 43.39 KiB 43.86 KiB +475 B

🔗 RealWorld

@datadog-datadog-prod-us1
Copy link

datadog-datadog-prod-us1 bot commented Dec 15, 2025

⚠️ Tests

Fix all issues with Cursor

⚠️ Warnings

❄️ 1 New flaky test detected

action collection › associate a long tasks to its action › bundle from rum/actions.scenario.ts (Datadog) (Fix with Cursor)
createTest.ts:244:3 bundle

[chromium] › ../lib/framework/createTest.ts:244:3 › action collection › associate a long tasks to its action › bundle 

    Error: expect(received).toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 1

    @@ -6,11 +6,11 @@
...

ℹ️ Info

🧪 All tests passed

🎯 Code Coverage
Patch Coverage: 95.45%
Overall Coverage: 92.68% (-0.00%)

View detailed report

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

@sethfowler-datadog sethfowler-datadog force-pushed the seth.fowler/PANA-5156-expose-better-session-replay-internal-api branch from 42d52d9 to 7dc5b2e Compare December 16, 2025 14:36
Copy link
Collaborator

Choose a reason for hiding this comment

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

I’m a bit confused. Why is there so much logic tied to internalAPI? FMU, internal.ts was meant to expose the underlying APIs as-is, not to add internal-specific code.

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 is the downside of dependency injection; we need to configure all the dependencies for this code! All of the logic is just calls to factory functions, or direct construction of "noop" versions of dependencies in cases where we don't need the full versions.

@sethfowler-datadog sethfowler-datadog merged commit 3d6697f into main Dec 17, 2025
21 checks passed
@sethfowler-datadog sethfowler-datadog deleted the seth.fowler/PANA-5156-expose-better-session-replay-internal-api branch December 17, 2025 13:40
@github-actions github-actions bot locked and limited conversation to collaborators Dec 17, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants