userlens-session-recorder 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export default class SessionRecorder {
8
8
  private maskingOptions;
9
9
  private sessionUuid;
10
10
  private sessionEvents;
11
+ private bufferBytes;
11
12
  private rrwebStop;
12
13
  private debug;
13
14
  private recordCrossOriginIframes;
package/dist/index.esm.js CHANGED
@@ -20669,55 +20669,48 @@ const uploadSessionEvents = async (args) => {
20669
20669
  return "ok";
20670
20670
  };
20671
20671
 
20672
- var _SessionRecorder_instances, _SessionRecorder_trackEventsThrottled, _SessionRecorder_uploading, _SessionRecorder_uploadingMaxTs, _SessionRecorder_log, _SessionRecorder_initRecorder, _SessionRecorder_isUserInteraction, _SessionRecorder_handleEvent, _SessionRecorder_resetSession, _SessionRecorder_createSession, _SessionRecorder_handlePageHide, _SessionRecorder_initListeners, _SessionRecorder_throttle, _SessionRecorder_trackEvents, _SessionRecorder_clearEvents;
20672
+ var _SessionRecorder_instances, _SessionRecorder_uploading, _SessionRecorder_uploadingMaxTs, _SessionRecorder_bufferTimer, _SessionRecorder_log, _SessionRecorder_initRecorder, _SessionRecorder_isUserInteraction, _SessionRecorder_handleEvent, _SessionRecorder_armBufferTimer, _SessionRecorder_flushBuffer, _SessionRecorder_resetSession, _SessionRecorder_createSession, _SessionRecorder_handlePageHide, _SessionRecorder_initListeners, _SessionRecorder_trackEvents, _SessionRecorder_clearEvents;
20673
+ const BUFFER_TIMEOUT_MS = 2000;
20674
+ const MAX_BUFFER_BYTES = 900 * 1024;
20675
+ function estimateEventSize(event) {
20676
+ try {
20677
+ return JSON.stringify(event).length;
20678
+ }
20679
+ catch {
20680
+ return 0;
20681
+ }
20682
+ }
20673
20683
  class SessionRecorder {
20674
20684
  constructor(config) {
20675
20685
  var _a, _b, _c;
20676
20686
  _SessionRecorder_instances.add(this);
20677
20687
  this.sessionEvents = [];
20688
+ this.bufferBytes = 0;
20678
20689
  this.rrwebStop = null;
20679
20690
  this.debug = false;
20680
- _SessionRecorder_trackEventsThrottled.set(this, void 0);
20681
20691
  _SessionRecorder_uploading.set(this, false);
20682
20692
  _SessionRecorder_uploadingMaxTs.set(this, 0);
20693
+ _SessionRecorder_bufferTimer.set(this, null);
20683
20694
  _SessionRecorder_handlePageHide.set(this, () => {
20684
20695
  try {
20685
20696
  if (this.sessionEvents.length === 0)
20686
20697
  return;
20687
- let toUpload;
20698
+ let events;
20688
20699
  if (__classPrivateFieldGet(this, _SessionRecorder_uploading, "f") && __classPrivateFieldGet(this, _SessionRecorder_uploadingMaxTs, "f") > 0) {
20689
- toUpload = this.sessionEvents.filter((e) => e.timestamp > __classPrivateFieldGet(this, _SessionRecorder_uploadingMaxTs, "f"));
20700
+ events = this.sessionEvents.filter((e) => e.timestamp > __classPrivateFieldGet(this, _SessionRecorder_uploadingMaxTs, "f"));
20690
20701
  }
20691
20702
  else {
20692
- toUpload = [...this.sessionEvents];
20703
+ events = [...this.sessionEvents];
20693
20704
  }
20694
- if (toUpload.length === 0)
20705
+ if (events.length === 0)
20695
20706
  return;
20696
- let events;
20697
- if (toUpload[0].type !== 4) {
20698
- let snapshotPair = [];
20699
- for (let i = this.sessionEvents.length - 2; i >= 0; i--) {
20700
- if (this.sessionEvents[i].type === 4 &&
20701
- this.sessionEvents[i + 1].type === 2) {
20702
- snapshotPair = [
20703
- this.sessionEvents[i],
20704
- this.sessionEvents[i + 1],
20705
- ];
20706
- break;
20707
- }
20708
- }
20709
- events = [...snapshotPair, ...toUpload];
20710
- }
20711
- else {
20712
- events = toUpload;
20713
- }
20714
20707
  const state = readSessionState();
20715
20708
  if (!state)
20716
20709
  return;
20717
20710
  const chunk_seq = __classPrivateFieldGet(this, _SessionRecorder_uploading, "f") ? state.chunk_seq + 1 : state.chunk_seq;
20718
20711
  writeSessionState({ ...state, chunk_seq: chunk_seq + 1 });
20719
- const start_ts_ms = toUpload[0].timestamp;
20720
- const end_ts_ms = toUpload[toUpload.length - 1].timestamp;
20712
+ const start_ts_ms = events[0].timestamp;
20713
+ const end_ts_ms = events[events.length - 1].timestamp;
20721
20714
  uploadSessionEvents({
20722
20715
  user_id: this.userId,
20723
20716
  session_uuid: this.sessionUuid,
@@ -20729,6 +20722,7 @@ class SessionRecorder {
20729
20722
  keepalive: true,
20730
20723
  }).catch(() => { });
20731
20724
  this.sessionEvents = [];
20725
+ this.bufferBytes = 0;
20732
20726
  }
20733
20727
  catch (err) {
20734
20728
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "Page hide handling failed", err);
@@ -20761,15 +20755,12 @@ class SessionRecorder {
20761
20755
  saveWriteCode(config.WRITE_CODE);
20762
20756
  this.userId = config.userId;
20763
20757
  const { recordingOptions = {} } = config;
20764
- const { TIMEOUT = 30 * 60 * 1000, BUFFER_SIZE = 10, maskingOptions = ["passwords"], recordCrossOriginIframes = false, } = recordingOptions;
20758
+ const { TIMEOUT = 30 * 60 * 1000, BUFFER_SIZE = 30, maskingOptions = ["passwords"], recordCrossOriginIframes = false, } = recordingOptions;
20765
20759
  this.TIMEOUT = TIMEOUT;
20766
20760
  this.BUFFER_SIZE = BUFFER_SIZE;
20767
20761
  this.maskingOptions = maskingOptions;
20768
20762
  this.recordCrossOriginIframes = recordCrossOriginIframes;
20769
20763
  this.sessionEvents = [];
20770
- __classPrivateFieldSet(this, _SessionRecorder_trackEventsThrottled, __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_throttle).call(this, () => {
20771
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_trackEvents).call(this);
20772
- }, 5000), "f");
20773
20764
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_initRecorder).call(this);
20774
20765
  }
20775
20766
  catch (err) {
@@ -20796,7 +20787,7 @@ class SessionRecorder {
20796
20787
  }
20797
20788
  }
20798
20789
  }
20799
- _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_uploading = new WeakMap(), _SessionRecorder_uploadingMaxTs = new WeakMap(), _SessionRecorder_handlePageHide = new WeakMap(), _SessionRecorder_instances = new WeakSet(), _SessionRecorder_log = function _SessionRecorder_log(message, error) {
20790
+ _SessionRecorder_uploading = new WeakMap(), _SessionRecorder_uploadingMaxTs = new WeakMap(), _SessionRecorder_bufferTimer = new WeakMap(), _SessionRecorder_handlePageHide = new WeakMap(), _SessionRecorder_instances = new WeakSet(), _SessionRecorder_log = function _SessionRecorder_log(message, error) {
20800
20791
  if (!this.debug)
20801
20792
  return;
20802
20793
  if (error) {
@@ -20819,6 +20810,7 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_uploadin
20819
20810
  },
20820
20811
  recordCrossOriginIframes: this.recordCrossOriginIframes,
20821
20812
  plugins: [getRecordConsolePlugin()],
20813
+ checkoutEveryNth: 100,
20822
20814
  });
20823
20815
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_initListeners).call(this);
20824
20816
  }, _SessionRecorder_isUserInteraction = function _SessionRecorder_isUserInteraction(event) {
@@ -20829,7 +20821,6 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_uploadin
20829
20821
  }
20830
20822
  return false;
20831
20823
  }, _SessionRecorder_handleEvent = function _SessionRecorder_handleEvent(event, _isCheckout) {
20832
- var _a;
20833
20824
  try {
20834
20825
  const now = Date.now();
20835
20826
  const state = readSessionState();
@@ -20844,13 +20835,29 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_uploadin
20844
20835
  }
20845
20836
  }
20846
20837
  this.sessionEvents.push(event);
20847
- if (this.sessionEvents.length >= this.BUFFER_SIZE) {
20848
- (_a = __classPrivateFieldGet(this, _SessionRecorder_trackEventsThrottled, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
20838
+ this.bufferBytes += estimateEventSize(event);
20839
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_armBufferTimer).call(this);
20840
+ if (this.bufferBytes >= MAX_BUFFER_BYTES) {
20841
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_flushBuffer).call(this);
20849
20842
  }
20850
20843
  }
20851
20844
  catch (err) {
20852
20845
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "Event handling failed", err);
20853
20846
  }
20847
+ }, _SessionRecorder_armBufferTimer = function _SessionRecorder_armBufferTimer() {
20848
+ if (__classPrivateFieldGet(this, _SessionRecorder_bufferTimer, "f") !== null) {
20849
+ clearTimeout(__classPrivateFieldGet(this, _SessionRecorder_bufferTimer, "f"));
20850
+ }
20851
+ __classPrivateFieldSet(this, _SessionRecorder_bufferTimer, setTimeout(() => {
20852
+ __classPrivateFieldSet(this, _SessionRecorder_bufferTimer, null, "f");
20853
+ __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_flushBuffer).call(this);
20854
+ }, BUFFER_TIMEOUT_MS), "f");
20855
+ }, _SessionRecorder_flushBuffer = function _SessionRecorder_flushBuffer() {
20856
+ if (__classPrivateFieldGet(this, _SessionRecorder_bufferTimer, "f") !== null) {
20857
+ clearTimeout(__classPrivateFieldGet(this, _SessionRecorder_bufferTimer, "f"));
20858
+ __classPrivateFieldSet(this, _SessionRecorder_bufferTimer, null, "f");
20859
+ }
20860
+ void __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_trackEvents).call(this);
20854
20861
  }, _SessionRecorder_resetSession = function _SessionRecorder_resetSession() {
20855
20862
  clearSessionState();
20856
20863
  __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_clearEvents).call(this);
@@ -20875,15 +20882,6 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_uploadin
20875
20882
  }
20876
20883
  }, _SessionRecorder_initListeners = function _SessionRecorder_initListeners() {
20877
20884
  window.addEventListener("pagehide", __classPrivateFieldGet(this, _SessionRecorder_handlePageHide, "f"));
20878
- }, _SessionRecorder_throttle = function _SessionRecorder_throttle(func, delay) {
20879
- let lastCall = 0;
20880
- return (...args) => {
20881
- const now = Date.now();
20882
- if (now - lastCall >= delay) {
20883
- lastCall = now;
20884
- func.apply(this, args);
20885
- }
20886
- };
20887
20885
  }, _SessionRecorder_trackEvents = async function _SessionRecorder_trackEvents() {
20888
20886
  if (__classPrivateFieldGet(this, _SessionRecorder_uploading, "f"))
20889
20887
  return;
@@ -20911,17 +20909,9 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_uploadin
20911
20909
  initial_url: chunk_seq === 0 ? state.initial_url : undefined,
20912
20910
  events,
20913
20911
  });
20914
- const remaining = this.sessionEvents.slice(snapshot_count);
20915
- this.sessionEvents = [];
20916
- try {
20917
- takeFullSnapshot(true);
20918
- }
20919
- catch (err) {
20920
- __classPrivateFieldGet(this, _SessionRecorder_instances, "m", _SessionRecorder_log).call(this, "takeFullSnapshot failed", err);
20921
- }
20922
- if (remaining.length > 0) {
20923
- this.sessionEvents.push(...remaining);
20924
- }
20912
+ const removedBytes = events.reduce((sum, e) => sum + estimateEventSize(e), 0);
20913
+ this.sessionEvents = this.sessionEvents.slice(snapshot_count);
20914
+ this.bufferBytes = Math.max(0, this.bufferBytes - removedBytes);
20925
20915
  const after = readSessionState();
20926
20916
  if (after &&
20927
20917
  after.session_uuid === state.session_uuid &&
@@ -20938,6 +20928,11 @@ _SessionRecorder_trackEventsThrottled = new WeakMap(), _SessionRecorder_uploadin
20938
20928
  }
20939
20929
  }, _SessionRecorder_clearEvents = function _SessionRecorder_clearEvents() {
20940
20930
  this.sessionEvents = [];
20931
+ this.bufferBytes = 0;
20932
+ if (__classPrivateFieldGet(this, _SessionRecorder_bufferTimer, "f") !== null) {
20933
+ clearTimeout(__classPrivateFieldGet(this, _SessionRecorder_bufferTimer, "f"));
20934
+ __classPrivateFieldSet(this, _SessionRecorder_bufferTimer, null, "f");
20935
+ }
20941
20936
  };
20942
20937
 
20943
20938
  export { SessionRecorder as default };