Skip to content

⚗️ Add Canvas image capture [3/n] - #4980

Open
BeltranBulbarellaDD wants to merge 25 commits into
mainfrom
beltran.bulbarella/canvas_support-3-capture-pixels
Open

⚗️ Add Canvas image capture [3/n]#4980
BeltranBulbarellaDD wants to merge 25 commits into
mainfrom
beltran.bulbarella/canvas_support-3-capture-pixels

Conversation

@BeltranBulbarellaDD

@BeltranBulbarellaDD BeltranBulbarellaDD commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Motivation

Session Replay does not capture the contents of <canvas> elements, so they show up blank in the replay. Building on #4947 (opt-in configuration) and #4949 (dirty-canvas tracking), this PR turns dirty canvases into PNG images plus a hash that tells us when their content actually changed.

Design diagram: View the Mermaid diagram

Changes

New trackCanvasCapture tracker: every 1s / maxFramesPerSecond, for each dirty, connected, non-tainted canvas whose privacy level is allow — take a downscaled snapshot, hash it, drop it if the hash matches the last one emitted for that canvas, otherwise encode a PNG and emit { nodeId, changeHash, image }. Snapshotting and hashing live in canvas/canvasSnapshot.ts and canvas/canvasHash.ts, each with its own spec; the tracker only orchestrates. Two new options: maxImageDimension (default 1000) for the recorded image and hashingMaxDimension (default 100) for the change-detection thumbnail.

Decisions

One immutable snapshot per capture, reused for hashing and encoding, so the emitted hash always describes the emitted bytes even if a draw lands mid-capture — the next PR uses that hash as a dedup key. A draw during a capture leaves the canvas dirty for the next tick.

The hash is computed on a ~100px thumbnail, so change detection costs the same at any canvas size. The canvas dimensions are part of it, so a resize always counts as a change.

The snapshot is a 2D canvas, not createImageBitmap. The latter resizes off the main thread, but it fails on 2 of the 5 browsers in browsers.conf.ts:

Browser Result
Chrome 80, Edge 80, Chrome Android works
Firefox 78 has the API, but not the (image, options) overload → synchronous TypeError
Safari 14.1 no createImageBitmap at all (Baseline only since Sept 2021, i.e. Safari 15)

Neither throw is a SecurityError, so those canvases would be retried on every tick forever. Supporting them means keeping a drawImage path anyway, and the numbers say the fast path does not earn a second code path (Chrome 151, macOS, GPU on, medians of 8 runs, ms):

Source → snapshot snapshot via createImageBitmap snapshot via drawImage hash from ImageBitmap hash from canvas encode via transfer + toBlob encode via toBlob
800×600 → 800×600 0.0 0.1 0.9 0.6 4.6 4.8
1920×1080 → 1000×563 0.1 0.0 0.8 0.5 7.2 6.9
3840×2160 → 1000×563 0.1 0.0 0.9 0.4 7.5 6.7

The snapshot is free either way even from 4K because drawImage downscaling is GPU-accelerated, hashing is ~2× faster from a canvas, and the PNG encode dominates at 5–7.5 ms in both. If a machine without GPU acceleration turns that synchronous downscale into a real cost, createImageBitmap comes back as a feature-detected fast path.

CanvasManager goes from tracking dirty canvases to owning capture state: in-flight capture, last emitted hash and tainted set, all in one WeakMap behind 6 methods. capture(canvas, run) owns the in-flight lifecycle and hands out an attempt whose settle/fail are guarded internally, so a caller cannot leak it or act on a capture that is no longer current.

Once tainted, always tainted. The platform would allow a retry after a bitmap reset, but that means a failed capture on every resize; the trade-off is that a canvas which stops being tainted stays frozen in the replay until recording restarts.

The attempt is the single staleness signal. Privacy level and node id are read once, at capture start; nothing re-validates the node id mid-flight because it cannot change without invalidating the attempt (processRemovedNodes calls forgetCanvas, resetIds calls reset()).

crypto.subtle has a non-crypto fallback: it is secure-context-only, so it is missing on plain HTTP pages in every browser, current Chrome included. No browser matrix can exercise that, so a mocked spec does.

Assigning width or height resets the bitmap and drops the last hash, so the next tick re-captures the canvas — including when the value is unchanged, since canvas.width = canvas.width is the standard idiom for clearing a canvas. Hence the check runs before the "no change since the last snapshot" early return in serializeMutations.

Scope

This PR adds the capture primitive and callback interface. Wiring captured blobs into Session Replay event serialization and intake delivery is a follow-up step.

Test instructions

yarn test:unit \
  --spec packages/browser-rum-core/src/domain/configuration/configuration.spec.ts \
  --spec packages/browser-rum/src/domain/record/record.spec.ts \
  --spec packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.spec.ts \
  --spec packages/browser-rum/src/domain/record/trackers/trackCanvasContent.spec.ts

yarn typecheck

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

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Aug 25, 2026

Copy link
Copy Markdown

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 181.63 KiB 181.74 KiB +122 B +0.07%
Rum Profiler 8.43 KiB 8.43 KiB 0 B 0.00%
Rum Recorder 25.32 KiB 28.16 KiB +2.84 KiB +11.23% ⚠️
Logs 57.93 KiB 57.93 KiB 0 B 0.00%
Rum Salesforce N/A 139.81 KiB N/A N/A N/A
Rum Slim 139.68 KiB 139.80 KiB +122 B +0.09%
Worker 22.96 KiB 22.96 KiB 0 B 0.00%
Rum Shopify N/A 208.94 KiB N/A N/A N/A
Rum-shopify Profiler N/A 8.43 KiB N/A N/A N/A
Rum-shopify Recorder N/A 3.74 KiB N/A N/A N/A

⚠️ The increase is particularly high and exceeds 5.00%. Please check the changes.

@datadog-prod-us1-3

datadog-prod-us1-3 Bot commented Aug 25, 2026

Copy link
Copy Markdown

Tests

All CI checks and tests passed.

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 81.01%
Overall Coverage: 77.08% (+0.05%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 3115990 | Docs | View more details | Give us feedback!

@BeltranBulbarellaDD BeltranBulbarellaDD changed the title Beltran.bulbarella/canvas support 3 capture pixels ⚗️ Add Session Replay canvas image capture Aug 25, 2026
@BeltranBulbarellaDD BeltranBulbarellaDD changed the title ⚗️ Add Session Replay canvas image capture ⚗️ Add Canvas image capture Aug 25, 2026
@BeltranBulbarellaDD BeltranBulbarellaDD changed the title ⚗️ Add Canvas image capture ⚗️ Add Canvas image capture [3/n] Aug 25, 2026
@BeltranBulbarellaDD
BeltranBulbarellaDD force-pushed the beltran.bulbarella/canvas_support-3-capture-pixels branch from 144fbb9 to af5efab Compare August 25, 2026 10:18
@BeltranBulbarellaDD
BeltranBulbarellaDD marked this pull request as ready for review August 25, 2026 14:44
@BeltranBulbarellaDD
BeltranBulbarellaDD requested review from a team as code owners August 25, 2026 14:44

@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: e88d1dda23

ℹ️ 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 thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated

@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: 04324e8b22

ℹ️ 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 thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/record.ts
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated

@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: fc5306758c

ℹ️ 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 thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/canvas/canvasManager.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated

@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: 1eed2ca243

ℹ️ 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 thread packages/browser-rum/src/domain/record/canvas/canvasManager.ts Outdated
Comment thread packages/browser-rum-core/src/domain/configuration/configuration.ts
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated

@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: d830fc9856

ℹ️ 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 thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T17:15:07.281365Z 3115990 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: b3b3f5c59b

ℹ️ 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 thread packages/browser-rum/src/domain/record/serialization/serializeMutations.ts Outdated
Comment thread packages/browser-rum/src/domain/record/trackers/trackCanvasCapture.ts Outdated

@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: 02f8ab1a5e

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

@BeltranBulbarellaDD

Copy link
Copy Markdown
Contributor Author

@codex pls review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 31159906d8

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

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.

3 participants