@logspace/sdk 1.1.4 → 1.1.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/logspace.esm.js CHANGED
@@ -14524,6 +14524,10 @@ let rateLimiter = { count: 0, windowStart: 0 };
14524
14524
  let deduplication = { lastLogHash: null, lastLogCount: 0 };
14525
14525
  let currentSize = 0;
14526
14526
  let rrwebSize = 0;
14527
+ let lastRateLimitWarningTime = 0;
14528
+ const RATE_LIMIT_WARNING_THROTTLE_MS = 1e3;
14529
+ let rrwebRateLimiter = { count: 0, windowStart: 0 };
14530
+ const RRWEB_RATE_LIMIT = 500;
14527
14531
  let idleTimer = null;
14528
14532
  let durationTimer = null;
14529
14533
  let checkpointTimer = null;
@@ -14751,7 +14755,11 @@ function checkRateLimit() {
14751
14755
  rateLimiter.count++;
14752
14756
  if (rateLimiter.count > config.limits.rateLimit) {
14753
14757
  if (config.debug) {
14754
- console.warn("[LogSpace] Rate limit exceeded, dropping log");
14758
+ const now2 = Date.now();
14759
+ if (now2 - lastRateLimitWarningTime >= RATE_LIMIT_WARNING_THROTTLE_MS) {
14760
+ lastRateLimitWarningTime = now2;
14761
+ console.warn("[LogSpace] Rate limit exceeded, dropping log");
14762
+ }
14755
14763
  }
14756
14764
  return false;
14757
14765
  }
@@ -15497,13 +15505,21 @@ async function sendPayload(payload) {
15497
15505
  const type = log.type || "unknown";
15498
15506
  logsByType[type] = (logsByType[type] || 0) + 1;
15499
15507
  }
15508
+ let rrwebDuration = payload.duration;
15509
+ if (payload.rrwebEvents && payload.rrwebEvents.length > 0) {
15510
+ const timestamps = payload.rrwebEvents.map((e) => e.timestamp);
15511
+ const minTs = Math.min(...timestamps);
15512
+ const maxTs = Math.max(...timestamps);
15513
+ rrwebDuration = maxTs - minTs;
15514
+ }
15500
15515
  const metadata = {
15501
15516
  totalLogs: payload.logs.length,
15502
15517
  logsByType,
15503
15518
  videoSize: 0,
15504
15519
  // SDK uses rrweb, not video
15505
15520
  videoType: "rrweb",
15506
- videoDuration: payload.duration,
15521
+ videoDuration: rrwebDuration,
15522
+ // Use actual rrweb duration, not session wall-clock time
15507
15523
  userAgent: payload.userAgent,
15508
15524
  timestamp: payload.startTime,
15509
15525
  // Use actual session start time for correct video seek calculation
@@ -15512,6 +15528,7 @@ async function sendPayload(payload) {
15512
15528
  userId: payload.userId,
15513
15529
  userTraits: payload.userTraits,
15514
15530
  duration: payload.duration,
15531
+ // Keep session wall-clock duration for reference
15515
15532
  stats: payload.stats
15516
15533
  };
15517
15534
  formData.append("log_metadata", JSON.stringify(metadata));
@@ -15565,12 +15582,20 @@ async function sendPayloadToServer(payload) {
15565
15582
  const type = log.type || "unknown";
15566
15583
  logsByType[type] = (logsByType[type] || 0) + 1;
15567
15584
  }
15585
+ let rrwebDuration = payload.duration;
15586
+ if (payload.rrwebEvents && payload.rrwebEvents.length > 0) {
15587
+ const timestamps = payload.rrwebEvents.map((e) => e.timestamp);
15588
+ const minTs = Math.min(...timestamps);
15589
+ const maxTs = Math.max(...timestamps);
15590
+ rrwebDuration = maxTs - minTs;
15591
+ }
15568
15592
  const metadata = {
15569
15593
  totalLogs: payload.logs.length,
15570
15594
  logsByType,
15571
15595
  videoSize: 0,
15572
15596
  videoType: "rrweb",
15573
- videoDuration: payload.duration,
15597
+ videoDuration: rrwebDuration,
15598
+ // Use actual rrweb duration, not session wall-clock time
15574
15599
  userAgent: payload.userAgent,
15575
15600
  timestamp: payload.startTime,
15576
15601
  // Use actual session start time for correct video seek calculation
@@ -15581,6 +15606,7 @@ async function sendPayloadToServer(payload) {
15581
15606
  userId: payload.userId,
15582
15607
  userTraits: payload.userTraits,
15583
15608
  duration: payload.duration,
15609
+ // Keep session wall-clock duration for reference
15584
15610
  stats: payload.stats
15585
15611
  };
15586
15612
  formData.append("log_metadata", JSON.stringify(metadata));
@@ -15670,6 +15696,12 @@ function mergeRecoveredData(recoveredLogs, recoveredEvents) {
15670
15696
  for (const event of newEvents) {
15671
15697
  rrwebSize += JSON.stringify(event).length;
15672
15698
  }
15699
+ if (config?.sampling.enabled && samplingTrimTimer) {
15700
+ stopSamplingTrimTimer();
15701
+ if (config?.debug) {
15702
+ console.log("[LogSpace] Stopped sampling trim timer to preserve recovered rrweb events");
15703
+ }
15704
+ }
15673
15705
  if (config?.debug) {
15674
15706
  console.log(
15675
15707
  `[LogSpace] Merged ${newEvents.length} recovered rrweb events (${recoveredEvents.length - newEvents.length} duplicates skipped)`
@@ -15928,6 +15960,8 @@ const LogSpace = {
15928
15960
  currentSize = 0;
15929
15961
  rrwebSize = 0;
15930
15962
  rateLimiter = { count: 0, windowStart: 0 };
15963
+ rrwebRateLimiter = { count: 0, windowStart: 0 };
15964
+ lastRateLimitWarningTime = 0;
15931
15965
  deduplication = { lastLogHash: null, lastLogCount: 0 };
15932
15966
  endReason = "manual";
15933
15967
  let sessionId;
@@ -15995,7 +16029,17 @@ const LogSpace = {
15995
16029
  },
15996
16030
  (event) => {
15997
16031
  if (!session || session.status !== "recording") return;
15998
- const eventSize = JSON.stringify(event).length;
16032
+ const now = Date.now();
16033
+ if (now - rrwebRateLimiter.windowStart > 1e3) {
16034
+ rrwebRateLimiter.windowStart = now;
16035
+ rrwebRateLimiter.count = 1;
16036
+ } else {
16037
+ rrwebRateLimiter.count++;
16038
+ if (rrwebRateLimiter.count > RRWEB_RATE_LIMIT) {
16039
+ return;
16040
+ }
16041
+ }
16042
+ const eventSize = event.type === 2 ? 5e4 : 500;
15999
16043
  rrwebSize += eventSize;
16000
16044
  const totalSize = currentSize + rrwebSize;
16001
16045
  if (config && totalSize >= config.limits.maxSize) {