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 +102 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +102 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/types/index.d.ts +12 -0
- package/package.json +1 -1
- package/src/tracker.ts +127 -13
package/dist/types/index.d.ts
CHANGED
|
@@ -109,6 +109,9 @@ declare class HumanBehaviorTracker {
|
|
|
109
109
|
private originalReplaceState;
|
|
110
110
|
private navigationListeners;
|
|
111
111
|
private _connectionBlocked;
|
|
112
|
+
private recordInstance;
|
|
113
|
+
private frequencyUpdateInterval;
|
|
114
|
+
private sessionStartTime;
|
|
112
115
|
/**
|
|
113
116
|
* Initialize the HumanBehavior tracker
|
|
114
117
|
* This is the main entry point - call this once per page
|
|
@@ -240,6 +243,15 @@ declare class HumanBehaviorTracker {
|
|
|
240
243
|
* Get the current URL being tracked
|
|
241
244
|
*/
|
|
242
245
|
getCurrentUrl(): string;
|
|
246
|
+
/**
|
|
247
|
+
* Get current snapshot frequency info
|
|
248
|
+
*/
|
|
249
|
+
getSnapshotFrequencyInfo(): {
|
|
250
|
+
sessionDuration: number;
|
|
251
|
+
currentInterval: number;
|
|
252
|
+
currentThreshold: number;
|
|
253
|
+
phase: string;
|
|
254
|
+
};
|
|
243
255
|
/**
|
|
244
256
|
* Test if the tracker can reach the ingestion server
|
|
245
257
|
*/
|
package/package.json
CHANGED
package/src/tracker.ts
CHANGED
|
@@ -47,6 +47,9 @@ export class HumanBehaviorTracker {
|
|
|
47
47
|
private originalReplaceState: typeof history.replaceState | null = null;
|
|
48
48
|
private navigationListeners: Array<() => void> = [];
|
|
49
49
|
private _connectionBlocked: boolean = false;
|
|
50
|
+
private recordInstance: any = null;
|
|
51
|
+
private frequencyUpdateInterval: any = null;
|
|
52
|
+
private sessionStartTime: number = Date.now();
|
|
50
53
|
|
|
51
54
|
/**
|
|
52
55
|
* Initialize the HumanBehavior tracker
|
|
@@ -759,19 +762,70 @@ export class HumanBehaviorTracker {
|
|
|
759
762
|
// Enable console tracking
|
|
760
763
|
this.enableConsoleTracking();
|
|
761
764
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
765
|
+
// Adaptive snapshot configuration based on session duration
|
|
766
|
+
const sessionStartTime = Date.now();
|
|
767
|
+
let snapshotInterval = 5000; // Start with 5 seconds
|
|
768
|
+
let eventThreshold = 100; // Start with 100 events
|
|
769
|
+
|
|
770
|
+
// Function to update snapshot frequency based on session duration
|
|
771
|
+
const updateSnapshotFrequency = () => {
|
|
772
|
+
const sessionDuration = Date.now() - sessionStartTime;
|
|
773
|
+
const thirtyMinutes = 30 * 60 * 1000;
|
|
774
|
+
const twoHours = 2 * 60 * 60 * 1000;
|
|
775
|
+
const fourHours = 4 * 60 * 60 * 1000;
|
|
776
|
+
|
|
777
|
+
if (sessionDuration > twoHours) {
|
|
778
|
+
// After 2 hours, very infrequent snapshots
|
|
779
|
+
snapshotInterval = 30000; // 30 seconds
|
|
780
|
+
eventThreshold = 500; // 500 events
|
|
781
|
+
logDebug('Reduced snapshot frequency: 30s/500 events (2+ hours)');
|
|
782
|
+
} else if (sessionDuration > thirtyMinutes) {
|
|
783
|
+
// After 30 minutes, moderate frequency
|
|
784
|
+
snapshotInterval = 15000; // 15 seconds
|
|
785
|
+
eventThreshold = 300; // 300 events
|
|
786
|
+
logDebug('Reduced snapshot frequency: 15s/300 events (30+ minutes)');
|
|
787
|
+
}
|
|
788
|
+
// First 30 minutes: 5s/100 events (default)
|
|
789
|
+
};
|
|
790
|
+
|
|
791
|
+
// Update frequency every 5 minutes
|
|
792
|
+
const frequencyUpdateInterval = setInterval(updateSnapshotFrequency, 5 * 60 * 1000);
|
|
793
|
+
|
|
794
|
+
// Start recording with adaptive redaction enabled
|
|
795
|
+
const recordInstance = rrweb.record({
|
|
796
|
+
emit: (event) => {
|
|
797
|
+
// Add additional validation for FullSnapshot events
|
|
798
|
+
if (event.type === 2) { // FullSnapshot event
|
|
799
|
+
if (!event.data || !event.data.node) {
|
|
800
|
+
logWarn('rrweb generated malformed FullSnapshot event:', {
|
|
801
|
+
hasData: !!event.data,
|
|
802
|
+
hasNode: !!(event.data && event.data.node),
|
|
803
|
+
dataType: typeof event.data,
|
|
804
|
+
eventType: event.type,
|
|
805
|
+
timestamp: event.timestamp
|
|
806
|
+
});
|
|
807
|
+
// Don't skip - let the addEvent method handle it
|
|
808
|
+
} else {
|
|
809
|
+
logDebug('Valid FullSnapshot event received from rrweb');
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
this.addEvent(event);
|
|
813
|
+
},
|
|
814
|
+
inlineStylesheet: true,
|
|
815
|
+
recordCanvas: true,
|
|
816
|
+
collectFonts: true,
|
|
817
|
+
inlineImages: true,
|
|
818
|
+
blockClass: 'rr-block',
|
|
819
|
+
ignoreClass: 'rr-ignore',
|
|
820
|
+
maskTextClass: 'rr-ignore',
|
|
821
|
+
// Adaptive configuration
|
|
822
|
+
checkoutEveryNms: snapshotInterval,
|
|
823
|
+
checkoutEveryNth: eventThreshold
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
// Store the record instance and interval for cleanup
|
|
827
|
+
this.recordInstance = recordInstance;
|
|
828
|
+
this.frequencyUpdateInterval = frequencyUpdateInterval;
|
|
775
829
|
}
|
|
776
830
|
|
|
777
831
|
public async stop() {
|
|
@@ -783,6 +837,18 @@ export class HumanBehaviorTracker {
|
|
|
783
837
|
this.flushInterval = null;
|
|
784
838
|
}
|
|
785
839
|
|
|
840
|
+
// Cleanup adaptive snapshot intervals
|
|
841
|
+
if (this.frequencyUpdateInterval) {
|
|
842
|
+
clearInterval(this.frequencyUpdateInterval);
|
|
843
|
+
this.frequencyUpdateInterval = null;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// Stop rrweb recording
|
|
847
|
+
if (this.recordInstance) {
|
|
848
|
+
this.recordInstance();
|
|
849
|
+
this.recordInstance = null;
|
|
850
|
+
}
|
|
851
|
+
|
|
786
852
|
// Disable console tracking
|
|
787
853
|
this.disableConsoleTracking();
|
|
788
854
|
|
|
@@ -793,6 +859,19 @@ export class HumanBehaviorTracker {
|
|
|
793
859
|
public async addEvent(event: any) {
|
|
794
860
|
await this.ensureInitialized();
|
|
795
861
|
|
|
862
|
+
// Validate FullSnapshot events before processing
|
|
863
|
+
if (event.type === 2) { // FullSnapshot event
|
|
864
|
+
if (!event.data || !event.data.node) {
|
|
865
|
+
logWarn('Malformed FullSnapshot event detected, skipping:', {
|
|
866
|
+
hasData: !!event.data,
|
|
867
|
+
hasNode: !!(event.data && event.data.node),
|
|
868
|
+
dataType: typeof event.data,
|
|
869
|
+
eventType: event.type
|
|
870
|
+
});
|
|
871
|
+
return; // Skip malformed FullSnapshot events
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
796
875
|
// Process event through redaction manager if active
|
|
797
876
|
const processedEvent = this.redactionManager.processEvent(event);
|
|
798
877
|
|
|
@@ -1010,6 +1089,41 @@ export class HumanBehaviorTracker {
|
|
|
1010
1089
|
return this.currentUrl;
|
|
1011
1090
|
}
|
|
1012
1091
|
|
|
1092
|
+
/**
|
|
1093
|
+
* Get current snapshot frequency info
|
|
1094
|
+
*/
|
|
1095
|
+
public getSnapshotFrequencyInfo(): {
|
|
1096
|
+
sessionDuration: number;
|
|
1097
|
+
currentInterval: number;
|
|
1098
|
+
currentThreshold: number;
|
|
1099
|
+
phase: string;
|
|
1100
|
+
} {
|
|
1101
|
+
const sessionDuration = Date.now() - this.sessionStartTime;
|
|
1102
|
+
const thirtyMinutes = 30 * 60 * 1000;
|
|
1103
|
+
const twoHours = 2 * 60 * 60 * 1000;
|
|
1104
|
+
|
|
1105
|
+
let phase = 'initial';
|
|
1106
|
+
let interval = 5000;
|
|
1107
|
+
let threshold = 100;
|
|
1108
|
+
|
|
1109
|
+
if (sessionDuration > twoHours) {
|
|
1110
|
+
phase = 'extended';
|
|
1111
|
+
interval = 30000;
|
|
1112
|
+
threshold = 500;
|
|
1113
|
+
} else if (sessionDuration > thirtyMinutes) {
|
|
1114
|
+
phase = 'moderate';
|
|
1115
|
+
interval = 15000;
|
|
1116
|
+
threshold = 300;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
return {
|
|
1120
|
+
sessionDuration,
|
|
1121
|
+
currentInterval: interval,
|
|
1122
|
+
currentThreshold: threshold,
|
|
1123
|
+
phase
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1013
1127
|
/**
|
|
1014
1128
|
* Test if the tracker can reach the ingestion server
|
|
1015
1129
|
*/
|