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