Skip to content

feat: add rrweb plugin#762

Merged
williazz merged 4 commits intoaws-observability:mainfrom
williazz:dev/session-replay
Feb 12, 2026
Merged

feat: add rrweb plugin#762
williazz merged 4 commits intoaws-observability:mainfrom
williazz:dev/session-replay

Conversation

@williazz
Copy link
Collaborator

@williazz williazz commented Feb 9, 2026

Summary

Add RRWebPlugin to main branch in pre-release mode. This does not get bundled into the CDN release, and is not exposed to top level configuration. RUM users may manually import this module if they would like to try it out, but there is no native support at this time.

Implementation

Add RRWebPlugin, which collects RRWeb events in batches and converts them into RUM SessionReplayEvent batches. On visibilitychange event, we will also flush these events before preparing the final batch before exiting the page.

SessionReplayEvents are not compressed separately via the native packer method. Instead, it is recommended to compress at payload level via #759

Schema

{
    "$id": "com.amazon.rum.session_replay_event",
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "SessionReplayEvent",
    "type": "object",
    "properties": {
        "version": {
            "const": "1.0.0",
            "type": "string",
            "description": "Schema version."
        },
        "events": {
            "type": "array",
            "description": "Batch of rrweb recording events.",
            "items": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "number",
                        "description": "rrweb event type."
                    },
                    "timestamp": {
                        "type": "number",
                        "description": "Unix timestamp in milliseconds."
                    },
                    "data": {
                        "description": "rrweb event payload."
                    }
                },
                "required": ["type", "timestamp", "data"]
            }
        },
        "eventCount": {
            "type": "number",
            "description": "Number of events in this batch."
        }
    },
    "additionalProperties": false,
    "required": ["version", "events", "eventCount"]
}

Default settings

  1. Significant cost savings because each SessionReplayEvent can hold up to 50 RRWebEvents by default
  2. Maximum privacy settings enabled by default. All text is blocked by default
export const RRWEB_CONFIG_PROD: RRWebPluginConfig = {
    additionalSampleRate: 1.0,
    batchSize: 50,
    flushInterval: 5000,
    recordOptions: {
        // Performance — keep payload size manageable
        slimDOMOptions: 'all',
        inlineStylesheet: true,
        inlineImages: false,
        collectFonts: true,
        recordCrossOriginIframes: false,
        // Privacy — mask all text and inputs by default
        // NOTE: blockSelector crashes rrweb 2.0.0-alpha.4 (node.matches bug on text nodes)
        maskAllInputs: true,
        maskTextSelector: '*'
    }
};

Future

  1. blockSelector has known issues in rrweb 2.0.0-alpha.4, which may be needed for deeper privacy masking for images and other non-text elements - [Bug]: use blockSelector to mask img record will throw error: e.matches is not a function rrweb-io/rrweb#1486
  2. [Bug]: SendBeacon 65 KB limit #761
  3. We are unlikely to release until [Feature Request]: Slim Build #507 and other backend requirements are resolved
  4. Compression enablement by default is also required for release
  5. Smoke tests to follow

Bundle Size

156 KB parsed

Testing

Added unit and integration tests. See spa-react-demo for manual testing with compression enabled.

Screenshot 2026-02-09 at 2 12 04 PM

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@williazz williazz changed the title feat: add rrweb plugin to library feat: add rrweb plugin Feb 9, 2026
@williazz williazz requested review from ishajos and ps863 February 9, 2026 22:13
],
allowCookies: true,
enableXRay: true,
enableXRay: false,
Copy link
Contributor

Choose a reason for hiding this comment

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

why are we disabling this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

just for demo purposes. it was polluting the logs

export const TIME_TO_INTERACTIVE_EVENT_TYPE = `${RUM_AMZ_PREFIX}.time_to_interactive_event`;

// RRWeb session recording event
export const RRWEB_EVENT_TYPE = `${RUM_AMZ_PREFIX}.rrweb`;
Copy link
Contributor

Choose a reason for hiding this comment

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

is it conventional to name this event rrweb as opposed to something like session_replay_event?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

i found this to be the best practice in case we want to migrate from rrweb someday

Copy link
Member

Choose a reason for hiding this comment

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

I am a bit confused. The RUM event schema seems to say session_replay_event but we are planning to make the event type com.amazon.rum.rrweb?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

should be rrweb. fixed

"type": "number",
"description": "rrweb event type."
},
"timestamp": {
Copy link
Member

Choose a reason for hiding this comment

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

question: Would events get recorded into a batch here in chronology? Or would backend need to use the timestamp to figure out the ordering

Copy link
Collaborator Author

@williazz williazz Feb 12, 2026

Choose a reason for hiding this comment

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

it's insertion order, which should also be chronological. backend will use rum event timestamp for pagination


/** Configuration options for {@link RRWebPlugin}. */
export type RRWebPluginConfig = {
/** Probability (0–1) of recording replay for a session, applied on top of sessionSampleRate. */
Copy link
Member

Choose a reason for hiding this comment

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

nit: Add docs how this + sessionSample would work together

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated the jsdoc. i'm not updating public docs at this time because this is still in pre-release state.

};

/** Development defaults — privacy masking disabled for easier debugging. */
export const RRWEB_CONFIG_DEV: RRWebPluginConfig = {
Copy link
Member

Choose a reason for hiding this comment

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

comment: I think we should be careful about enabling privacy masking even in the dev config.
Users should have to explicitly enable that and we should not hide it under dev. Additionally storage concerns that exist in prod might be applicable here as well

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is disabling privacy masking, not enabling. but sure i can just remove dev config

export const TIME_TO_INTERACTIVE_EVENT_TYPE = `${RUM_AMZ_PREFIX}.time_to_interactive_event`;

// RRWeb session recording event
export const RRWEB_EVENT_TYPE = `${RUM_AMZ_PREFIX}.rrweb`;
Copy link
Member

Choose a reason for hiding this comment

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

I am a bit confused. The RUM event schema seems to say session_replay_event but we are planning to make the event type com.amazon.rum.rrweb?

@williazz williazz merged commit 7af852d into aws-observability:main Feb 12, 2026
10 of 11 checks passed
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