humanbehavior-js 0.2.5 → 0.2.7

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/esm/index.js CHANGED
@@ -4956,6 +4956,9 @@ class HumanBehaviorTracker {
4956
4956
  this.originalReplaceState = null;
4957
4957
  this.navigationListeners = [];
4958
4958
  this._connectionBlocked = false;
4959
+ this.recordInstance = null;
4960
+ this.frequencyUpdateInterval = null;
4961
+ this.sessionStartTime = Date.now();
4959
4962
  if (!apiKey) {
4960
4963
  throw new Error('Human Behavior API Key is required');
4961
4964
  }
@@ -5514,9 +5517,50 @@ class HumanBehaviorTracker {
5514
5517
  }, this.FLUSH_INTERVAL_MS);
5515
5518
  // Enable console tracking
5516
5519
  this.enableConsoleTracking();
5517
- // Start recording with redaction enabled
5518
- record({
5520
+ // Adaptive snapshot configuration based on session duration
5521
+ const sessionStartTime = Date.now();
5522
+ let snapshotInterval = 5000; // Start with 5 seconds
5523
+ let eventThreshold = 100; // Start with 100 events
5524
+ // Function to update snapshot frequency based on session duration
5525
+ const updateSnapshotFrequency = () => {
5526
+ const sessionDuration = Date.now() - sessionStartTime;
5527
+ const thirtyMinutes = 30 * 60 * 1000;
5528
+ const twoHours = 2 * 60 * 60 * 1000;
5529
+ if (sessionDuration > twoHours) {
5530
+ // After 2 hours, very infrequent snapshots
5531
+ snapshotInterval = 30000; // 30 seconds
5532
+ eventThreshold = 500; // 500 events
5533
+ logDebug('Reduced snapshot frequency: 30s/500 events (2+ hours)');
5534
+ }
5535
+ else if (sessionDuration > thirtyMinutes) {
5536
+ // After 30 minutes, moderate frequency
5537
+ snapshotInterval = 15000; // 15 seconds
5538
+ eventThreshold = 300; // 300 events
5539
+ logDebug('Reduced snapshot frequency: 15s/300 events (30+ minutes)');
5540
+ }
5541
+ // First 30 minutes: 5s/100 events (default)
5542
+ };
5543
+ // Update frequency every 5 minutes
5544
+ const frequencyUpdateInterval = setInterval(updateSnapshotFrequency, 5 * 60 * 1000);
5545
+ // Start recording with adaptive redaction enabled
5546
+ const recordInstance = record({
5519
5547
  emit: (event) => {
5548
+ // Add additional validation for FullSnapshot events
5549
+ if (event.type === 2) { // FullSnapshot event
5550
+ if (!event.data || !event.data.node) {
5551
+ logWarn('rrweb generated malformed FullSnapshot event:', {
5552
+ hasData: !!event.data,
5553
+ hasNode: !!(event.data && event.data.node),
5554
+ dataType: typeof event.data,
5555
+ eventType: event.type,
5556
+ timestamp: event.timestamp
5557
+ });
5558
+ // Don't skip - let the addEvent method handle it
5559
+ }
5560
+ else {
5561
+ logDebug('Valid FullSnapshot event received from rrweb');
5562
+ }
5563
+ }
5520
5564
  this.addEvent(event);
5521
5565
  },
5522
5566
  inlineStylesheet: true,
@@ -5525,8 +5569,14 @@ class HumanBehaviorTracker {
5525
5569
  inlineImages: true,
5526
5570
  blockClass: 'rr-block',
5527
5571
  ignoreClass: 'rr-ignore',
5528
- maskTextClass: 'rr-ignore'
5572
+ maskTextClass: 'rr-ignore',
5573
+ // Adaptive configuration
5574
+ checkoutEveryNms: snapshotInterval,
5575
+ checkoutEveryNth: eventThreshold
5529
5576
  });
5577
+ // Store the record instance and interval for cleanup
5578
+ this.recordInstance = recordInstance;
5579
+ this.frequencyUpdateInterval = frequencyUpdateInterval;
5530
5580
  });
5531
5581
  }
5532
5582
  stop() {
@@ -5538,6 +5588,16 @@ class HumanBehaviorTracker {
5538
5588
  clearInterval(this.flushInterval);
5539
5589
  this.flushInterval = null;
5540
5590
  }
5591
+ // Cleanup adaptive snapshot intervals
5592
+ if (this.frequencyUpdateInterval) {
5593
+ clearInterval(this.frequencyUpdateInterval);
5594
+ this.frequencyUpdateInterval = null;
5595
+ }
5596
+ // Stop rrweb recording
5597
+ if (this.recordInstance) {
5598
+ this.recordInstance();
5599
+ this.recordInstance = null;
5600
+ }
5541
5601
  // Disable console tracking
5542
5602
  this.disableConsoleTracking();
5543
5603
  // Cleanup navigation tracking
@@ -5547,6 +5607,18 @@ class HumanBehaviorTracker {
5547
5607
  addEvent(event) {
5548
5608
  return __awaiter$1(this, void 0, void 0, function* () {
5549
5609
  yield this.ensureInitialized();
5610
+ // Validate FullSnapshot events before processing
5611
+ if (event.type === 2) { // FullSnapshot event
5612
+ if (!event.data || !event.data.node) {
5613
+ logWarn('Malformed FullSnapshot event detected, skipping:', {
5614
+ hasData: !!event.data,
5615
+ hasNode: !!(event.data && event.data.node),
5616
+ dataType: typeof event.data,
5617
+ eventType: event.type
5618
+ });
5619
+ return; // Skip malformed FullSnapshot events
5620
+ }
5621
+ }
5550
5622
  // Process event through redaction manager if active
5551
5623
  const processedEvent = this.redactionManager.processEvent(event);
5552
5624
  const eventSize = new TextEncoder().encode(JSON.stringify(processedEvent)).length;
@@ -5759,6 +5831,33 @@ class HumanBehaviorTracker {
5759
5831
  getCurrentUrl() {
5760
5832
  return this.currentUrl;
5761
5833
  }
5834
+ /**
5835
+ * Get current snapshot frequency info
5836
+ */
5837
+ getSnapshotFrequencyInfo() {
5838
+ const sessionDuration = Date.now() - this.sessionStartTime;
5839
+ const thirtyMinutes = 30 * 60 * 1000;
5840
+ const twoHours = 2 * 60 * 60 * 1000;
5841
+ let phase = 'initial';
5842
+ let interval = 5000;
5843
+ let threshold = 100;
5844
+ if (sessionDuration > twoHours) {
5845
+ phase = 'extended';
5846
+ interval = 30000;
5847
+ threshold = 500;
5848
+ }
5849
+ else if (sessionDuration > thirtyMinutes) {
5850
+ phase = 'moderate';
5851
+ interval = 15000;
5852
+ threshold = 300;
5853
+ }
5854
+ return {
5855
+ sessionDuration,
5856
+ currentInterval: interval,
5857
+ currentThreshold: threshold,
5858
+ phase
5859
+ };
5860
+ }
5762
5861
  /**
5763
5862
  * Test if the tracker can reach the ingestion server
5764
5863
  */