diff --git a/.changeset/friendly-rockets-live.md b/.changeset/friendly-rockets-live.md new file mode 100644 index 0000000000..ce157e7de2 --- /dev/null +++ b/.changeset/friendly-rockets-live.md @@ -0,0 +1,6 @@ +--- +"rrweb": patch +"@rrweb/types": patch +--- + +Implement configurable throttling on mutation emission using a new `sampling.mutation` setting diff --git a/docs/recipes/optimize-storage.md b/docs/recipes/optimize-storage.md index 9a67d10331..7d384fffa9 100644 --- a/docs/recipes/optimize-storage.md +++ b/docs/recipes/optimize-storage.md @@ -21,7 +21,7 @@ Some common patterns may emit lots of events are: ## Sampling -Use the sampling config in the recording can reduce the storage size by dropping some events: +Use the sampling config in the recording can reduce the storage size by dropping or merging some events: **Scenario 1** @@ -35,6 +35,8 @@ rrweb.record({ mouseInteraction: false // set the interval of scrolling event scroll: 150 // do not emit twice in 150ms + // set the interval of mutation events (page changes) + mutation: 50 // do not emit more than 20 mutations per second // set the interval of media interaction event media: 800 // set the timing of record input diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index 08e927a98f..67753cfad3 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -31,6 +31,7 @@ import { inDom, getShadowHost, closestElementOfNode, + throttle, } from '../utils'; import dom from '@rrweb/utils'; @@ -184,6 +185,7 @@ export default class MutationBuffer { private recordCanvas: observerParam['recordCanvas']; private inlineImages: observerParam['inlineImages']; private slimDOMOptions: observerParam['slimDOMOptions']; + private sampling: observerParam['sampling']; private dataURLOptions: observerParam['dataURLOptions']; private doc: observerParam['doc']; private mirror: observerParam['mirror']; @@ -210,6 +212,7 @@ export default class MutationBuffer { 'recordCanvas', 'inlineImages', 'slimDOMOptions', + 'sampling', 'dataURLOptions', 'doc', 'mirror', @@ -223,6 +226,10 @@ export default class MutationBuffer { // just a type trick, the runtime result is correct this[key] = options[key] as never; }); + + if (this.sampling.mutation) { + this.emit = throttle(this.emit, this.sampling.mutation); + } } public freeze() { diff --git a/packages/rrweb/src/types.ts b/packages/rrweb/src/types.ts index a03e326b6f..d0cd3d3fd9 100644 --- a/packages/rrweb/src/types.ts +++ b/packages/rrweb/src/types.ts @@ -143,6 +143,7 @@ export type MutationBufferParam = Pick< | 'recordCanvas' | 'inlineImages' | 'slimDOMOptions' + | 'sampling' | 'dataURLOptions' | 'doc' | 'mirror' diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index bba276e483..20acc39ed9 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -201,9 +201,15 @@ export type SamplingStrategy = Partial<{ */ mouseInteraction: boolean | Record; /** - * number is the throttle threshold of recording scroll + * number is the throttle threshold of recording scroll in ms + * default: 100 */ scroll: number; + /** + * number is the throttle threshold of mutation emission in ms + * off by default + */ + mutation: number; /** * number is the throttle threshold of recording media interactions */