@devskin/browser-sdk 1.0.14 → 1.0.16
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/devskin.cjs.js +69 -50
- package/dist/devskin.cjs.js.map +1 -1
- package/dist/devskin.esm.js +69 -50
- package/dist/devskin.esm.js.map +1 -1
- package/dist/devskin.umd.js +69 -50
- package/dist/devskin.umd.js.map +1 -1
- package/dist/devskin.umd.min.js +3 -3
- package/dist/devskin.umd.min.js.map +1 -1
- package/dist/recorder/rrweb.d.ts.map +1 -1
- package/dist/transport.d.ts +1 -0
- package/dist/transport.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/devskin.esm.js
CHANGED
|
@@ -5561,24 +5561,12 @@ class RRWebRecorder {
|
|
|
5561
5561
|
return;
|
|
5562
5562
|
}
|
|
5563
5563
|
try {
|
|
5564
|
-
console.log('[RRWeb] Starting session recording:', this.sessionId);
|
|
5565
|
-
console.log('[RRWeb] SDK Version: 1.0.14');
|
|
5566
5564
|
this.stopFn = record({
|
|
5567
5565
|
emit: (event) => {
|
|
5568
|
-
// DEBUG: Log ALL event types to diagnose issue
|
|
5569
|
-
if (!this.hasFullSnapshot) {
|
|
5570
|
-
console.log('[RRWeb] Event captured:', {
|
|
5571
|
-
type: event.type,
|
|
5572
|
-
timestamp: event.timestamp,
|
|
5573
|
-
hasData: !!event.data
|
|
5574
|
-
});
|
|
5575
|
-
}
|
|
5576
5566
|
this.events.push(event);
|
|
5577
5567
|
// Check if this is a FullSnapshot (type 2)
|
|
5578
5568
|
if (event.type === 2) {
|
|
5579
5569
|
this.hasFullSnapshot = true;
|
|
5580
|
-
console.log('[RRWeb] ✅ FullSnapshot captured! Sending immediately...');
|
|
5581
|
-
console.log('[RRWeb] FullSnapshot data keys:', Object.keys(event.data || {}));
|
|
5582
5570
|
// Send immediately to ensure FullSnapshot reaches backend first
|
|
5583
5571
|
this.flush();
|
|
5584
5572
|
}
|
|
@@ -5632,29 +5620,19 @@ class RRWebRecorder {
|
|
|
5632
5620
|
// Safety check: After 2 seconds, force a full snapshot if none captured
|
|
5633
5621
|
setTimeout(() => {
|
|
5634
5622
|
if (!this.hasFullSnapshot) {
|
|
5635
|
-
console.warn('[RRWeb] ⚠️ No FullSnapshot captured after 2 seconds!');
|
|
5636
|
-
console.warn('[RRWeb] Events captured so far:', this.events.length);
|
|
5637
|
-
console.warn('[RRWeb] Event types:', this.events.map(e => e.type));
|
|
5638
|
-
console.warn('[RRWeb] Forcing a full snapshot via record.takeFullSnapshot()...');
|
|
5639
5623
|
// Try to force a full snapshot using rrweb's API
|
|
5640
5624
|
try {
|
|
5641
|
-
// Call record.takeFullSnapshot() to force a full snapshot
|
|
5642
5625
|
record.takeFullSnapshot();
|
|
5643
|
-
console.log('[RRWeb] ✅ Manual FullSnapshot triggered!');
|
|
5644
5626
|
}
|
|
5645
5627
|
catch (error) {
|
|
5646
|
-
console.error('[RRWeb] Failed to force snapshot:', error);
|
|
5647
5628
|
// If we have events but no FullSnapshot, flush anyway to not lose data
|
|
5648
|
-
// But warn that replay may not work correctly
|
|
5649
5629
|
if (this.events.length > 0) {
|
|
5650
|
-
console.warn('[RRWeb] Flushing existing events WITHOUT FullSnapshot...');
|
|
5651
5630
|
this.hasFullSnapshot = true; // Set to true to allow flushing
|
|
5652
5631
|
this.flush();
|
|
5653
5632
|
}
|
|
5654
5633
|
}
|
|
5655
5634
|
}
|
|
5656
5635
|
}, 2000);
|
|
5657
|
-
console.log('[RRWeb] Recording started successfully');
|
|
5658
5636
|
}
|
|
5659
5637
|
catch (error) {
|
|
5660
5638
|
console.error('[RRWeb] Failed to start recording:', error);
|
|
@@ -5664,17 +5642,13 @@ class RRWebRecorder {
|
|
|
5664
5642
|
if (this.stopFn) {
|
|
5665
5643
|
this.stopFn();
|
|
5666
5644
|
this.stopFn = null;
|
|
5667
|
-
console.log('[RRWeb] Recording stopped');
|
|
5668
5645
|
}
|
|
5669
5646
|
if (this.flushInterval) {
|
|
5670
5647
|
clearInterval(this.flushInterval);
|
|
5671
5648
|
this.flushInterval = null;
|
|
5672
5649
|
}
|
|
5673
|
-
// Flush remaining events
|
|
5650
|
+
// Flush remaining events
|
|
5674
5651
|
if (this.events.length > 0) {
|
|
5675
|
-
if (!this.hasFullSnapshot) {
|
|
5676
|
-
console.warn('[RRWeb] Flushing events without FullSnapshot - recording may not replay correctly');
|
|
5677
|
-
}
|
|
5678
5652
|
this.flush();
|
|
5679
5653
|
}
|
|
5680
5654
|
}
|
|
@@ -5683,12 +5657,6 @@ class RRWebRecorder {
|
|
|
5683
5657
|
return;
|
|
5684
5658
|
const eventsToSend = [...this.events];
|
|
5685
5659
|
this.events = [];
|
|
5686
|
-
// Log event types being sent
|
|
5687
|
-
const typeCounts = {};
|
|
5688
|
-
eventsToSend.forEach(e => {
|
|
5689
|
-
typeCounts[e.type] = (typeCounts[e.type] || 0) + 1;
|
|
5690
|
-
});
|
|
5691
|
-
console.log('[RRWeb] Flushing events:', typeCounts);
|
|
5692
5660
|
if (this.onEventsReady) {
|
|
5693
5661
|
this.onEventsReady(eventsToSend);
|
|
5694
5662
|
}
|
|
@@ -5746,11 +5714,6 @@ class Transport {
|
|
|
5746
5714
|
}
|
|
5747
5715
|
sendRecordingEvents(sessionId, events) {
|
|
5748
5716
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
5749
|
-
// DEBUG: Log event types being sent
|
|
5750
|
-
const eventTypes = events.reduce((acc, e) => {
|
|
5751
|
-
acc[e.type] = (acc[e.type] || 0) + 1;
|
|
5752
|
-
return acc;
|
|
5753
|
-
}, {});
|
|
5754
5717
|
// Calculate payload size
|
|
5755
5718
|
const payload = {
|
|
5756
5719
|
session_id: sessionId,
|
|
@@ -5760,10 +5723,6 @@ class Transport {
|
|
|
5760
5723
|
appId: this.config.appId,
|
|
5761
5724
|
};
|
|
5762
5725
|
const payloadSize = new Blob([JSON.stringify(payload)]).size;
|
|
5763
|
-
const payloadSizeMB = (payloadSize / 1024 / 1024).toFixed(2);
|
|
5764
|
-
console.log(`[DevSkin SDK] Sending ${events.length} recording events:`, eventTypes);
|
|
5765
|
-
console.log(`[DevSkin SDK] Payload size: ${payloadSizeMB} MB (${payloadSize} bytes)`);
|
|
5766
|
-
console.log(`[DevSkin SDK] First 3 events:`, events.slice(0, 3).map(e => ({ type: e.type, timestamp: e.timestamp })));
|
|
5767
5726
|
// Check if this batch contains FullSnapshot (type 2)
|
|
5768
5727
|
const hasFullSnapshot = events.some(e => e.type === 2);
|
|
5769
5728
|
const maxRetries = hasFullSnapshot ? 3 : 1; // Retry FullSnapshot batches up to 3 times
|
|
@@ -5771,25 +5730,35 @@ class Transport {
|
|
|
5771
5730
|
let lastError = null;
|
|
5772
5731
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
5773
5732
|
try {
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5733
|
+
// Use XMLHttpRequest for large payloads (more reliable than fetch for large data)
|
|
5734
|
+
if (payloadSize > 100000) { // > 100KB
|
|
5735
|
+
yield this.sendToBackendXHR('/v1/rum/recordings', {
|
|
5736
|
+
session_id: sessionId,
|
|
5737
|
+
events,
|
|
5738
|
+
timestamp: new Date().toISOString(),
|
|
5739
|
+
});
|
|
5740
|
+
}
|
|
5741
|
+
else {
|
|
5742
|
+
yield this.sendToBackend('/v1/rum/recordings', {
|
|
5743
|
+
session_id: sessionId,
|
|
5744
|
+
events,
|
|
5745
|
+
timestamp: new Date().toISOString(),
|
|
5746
|
+
});
|
|
5747
|
+
}
|
|
5780
5748
|
return; // Success, exit
|
|
5781
5749
|
}
|
|
5782
5750
|
catch (error) {
|
|
5783
5751
|
lastError = error;
|
|
5784
5752
|
if (attempt < maxRetries) {
|
|
5785
5753
|
const delay = attempt * 1000; // 1s, 2s, 3s...
|
|
5786
|
-
console.warn(`[DevSkin SDK] ⚠️ Failed to send recording events (attempt ${attempt}/${maxRetries}), retrying in ${delay}ms...`);
|
|
5787
5754
|
yield new Promise(resolve => setTimeout(resolve, delay));
|
|
5788
5755
|
}
|
|
5789
5756
|
}
|
|
5790
5757
|
}
|
|
5791
5758
|
// All retries failed
|
|
5792
|
-
|
|
5759
|
+
if (this.config.debug) {
|
|
5760
|
+
console.error(`[DevSkin SDK] Failed to send recording events after ${maxRetries} attempts:`, lastError);
|
|
5761
|
+
}
|
|
5793
5762
|
});
|
|
5794
5763
|
}
|
|
5795
5764
|
sendHeatmapData(heatmapData) {
|
|
@@ -5850,6 +5819,56 @@ class Transport {
|
|
|
5850
5819
|
return '/v1/analytics/events';
|
|
5851
5820
|
}
|
|
5852
5821
|
}
|
|
5822
|
+
sendToBackendXHR(endpoint, data) {
|
|
5823
|
+
return __awaiter$1(this, void 0, void 0, function* () {
|
|
5824
|
+
const url = `${this.apiUrl}${endpoint}`;
|
|
5825
|
+
const payload = Object.assign(Object.assign({}, data), { apiKey: this.config.apiKey, appId: this.config.appId, environment: this.config.environment, release: this.config.release });
|
|
5826
|
+
// Apply beforeSend hook if provided
|
|
5827
|
+
if (this.config.beforeSend) {
|
|
5828
|
+
const processed = this.config.beforeSend(payload);
|
|
5829
|
+
if (!processed) {
|
|
5830
|
+
// Hook returned null, don't send
|
|
5831
|
+
return;
|
|
5832
|
+
}
|
|
5833
|
+
}
|
|
5834
|
+
return new Promise((resolve, reject) => {
|
|
5835
|
+
const xhr = new XMLHttpRequest();
|
|
5836
|
+
xhr.open('POST', url, true);
|
|
5837
|
+
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
5838
|
+
xhr.setRequestHeader('Authorization', `Bearer ${this.config.apiKey}`);
|
|
5839
|
+
xhr.onload = () => {
|
|
5840
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
5841
|
+
if (this.config.debug) {
|
|
5842
|
+
console.log('[DevSkin] Data sent successfully via XHR:', endpoint);
|
|
5843
|
+
}
|
|
5844
|
+
resolve();
|
|
5845
|
+
}
|
|
5846
|
+
else {
|
|
5847
|
+
console.error('[DevSkin] XHR HTTP Error:', xhr.status, xhr.responseText);
|
|
5848
|
+
reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));
|
|
5849
|
+
}
|
|
5850
|
+
};
|
|
5851
|
+
xhr.onerror = () => {
|
|
5852
|
+
console.error('[DevSkin] XHR network error:', endpoint);
|
|
5853
|
+
reject(new Error('Network error'));
|
|
5854
|
+
};
|
|
5855
|
+
xhr.ontimeout = () => {
|
|
5856
|
+
console.error('[DevSkin] XHR timeout:', endpoint);
|
|
5857
|
+
reject(new Error('Request timeout'));
|
|
5858
|
+
};
|
|
5859
|
+
// Set a generous timeout for large payloads (30 seconds)
|
|
5860
|
+
xhr.timeout = 30000;
|
|
5861
|
+
try {
|
|
5862
|
+
const body = JSON.stringify(payload);
|
|
5863
|
+
xhr.send(body);
|
|
5864
|
+
}
|
|
5865
|
+
catch (error) {
|
|
5866
|
+
console.error('[DevSkin] Failed to send XHR request:', error);
|
|
5867
|
+
reject(error);
|
|
5868
|
+
}
|
|
5869
|
+
});
|
|
5870
|
+
});
|
|
5871
|
+
}
|
|
5853
5872
|
sendToBackend(endpoint_1, data_1) {
|
|
5854
5873
|
return __awaiter$1(this, arguments, void 0, function* (endpoint, data, useBeacon = false) {
|
|
5855
5874
|
const url = `${this.apiUrl}${endpoint}`;
|