@tracelog/lib 0.11.3 → 0.11.4

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.
@@ -681,7 +681,7 @@ declare class ScrollHandler extends StateManager {
681
681
  private minDepthChange;
682
682
  private minIntervalMs;
683
683
  private maxEventsPerSession;
684
- private retryTimeoutId;
684
+ private containerDiscoveryTimeoutId;
685
685
  constructor(eventManager: EventManager);
686
686
  startTracking(): void;
687
687
  stopTracking(): void;
@@ -681,7 +681,7 @@ declare class ScrollHandler extends StateManager {
681
681
  private minDepthChange;
682
682
  private minIntervalMs;
683
683
  private maxEventsPerSession;
684
- private retryTimeoutId;
684
+ private containerDiscoveryTimeoutId;
685
685
  constructor(eventManager: EventManager);
686
686
  startTracking(): void;
687
687
  stopTracking(): void;
@@ -13,6 +13,7 @@ var MAX_THROTTLE_CACHE_ENTRIES = 1e3;
13
13
  var THROTTLE_ENTRY_TTL_MS = 3e5;
14
14
  var THROTTLE_PRUNE_INTERVAL_MS = 3e4;
15
15
  var EVENT_EXPIRY_HOURS = 2;
16
+ var PERSISTENCE_THROTTLE_MS = 1e3;
16
17
  var MAX_EVENTS_QUEUE_LENGTH = 100;
17
18
  var REQUEST_TIMEOUT_MS = 1e4;
18
19
  var SIGNIFICANT_SCROLL_DELTA = 10;
@@ -1080,6 +1081,7 @@ var StateManager = class {
1080
1081
  var SenderManager = class extends StateManager {
1081
1082
  storeManager;
1082
1083
  lastPermanentErrorLog = null;
1084
+ recoveryInProgress = false;
1083
1085
  constructor(storeManager) {
1084
1086
  super();
1085
1087
  this.storeManager = storeManager;
@@ -1125,6 +1127,11 @@ var SenderManager = class extends StateManager {
1125
1127
  }
1126
1128
  }
1127
1129
  async recoverPersistedEvents(callbacks) {
1130
+ if (this.recoveryInProgress) {
1131
+ log("debug", "Recovery already in progress, skipping duplicate attempt");
1132
+ return;
1133
+ }
1134
+ this.recoveryInProgress = true;
1128
1135
  try {
1129
1136
  const persistedData = this.getPersistedData();
1130
1137
  if (!persistedData || !this.isDataRecent(persistedData) || persistedData.events.length === 0) {
@@ -1147,6 +1154,8 @@ var SenderManager = class extends StateManager {
1147
1154
  return;
1148
1155
  }
1149
1156
  log("error", "Failed to recover persisted events", { error });
1157
+ } finally {
1158
+ this.recoveryInProgress = false;
1150
1159
  }
1151
1160
  }
1152
1161
  stop() {
@@ -1273,6 +1282,16 @@ var SenderManager = class extends StateManager {
1273
1282
  }
1274
1283
  persistEvents(body) {
1275
1284
  try {
1285
+ const existing = this.getPersistedData();
1286
+ if (existing && existing.timestamp) {
1287
+ const timeSinceExisting = Date.now() - existing.timestamp;
1288
+ if (timeSinceExisting < PERSISTENCE_THROTTLE_MS) {
1289
+ log("debug", "Skipping persistence, another tab recently persisted events", {
1290
+ data: { timeSinceExisting }
1291
+ });
1292
+ return true;
1293
+ }
1294
+ }
1276
1295
  const persistedData = {
1277
1296
  ...body,
1278
1297
  timestamp: Date.now()
@@ -1563,6 +1582,9 @@ var EventManager = class extends StateManager {
1563
1582
  this.removeProcessedEvents(eventIds);
1564
1583
  this.clearSendInterval();
1565
1584
  this.emitEventsQueue(body);
1585
+ } else {
1586
+ this.removeProcessedEvents(eventIds);
1587
+ this.clearSendInterval();
1566
1588
  }
1567
1589
  return success;
1568
1590
  } else {
@@ -1573,7 +1595,11 @@ var EventManager = class extends StateManager {
1573
1595
  this.emitEventsQueue(body);
1574
1596
  },
1575
1597
  onFailure: () => {
1576
- log("warn", "Async flush failed", {
1598
+ this.removeProcessedEvents(eventIds);
1599
+ if (this.eventsQueue.length === 0) {
1600
+ this.clearSendInterval();
1601
+ }
1602
+ log("warn", "Async flush failed, removed from queue and persisted for recovery on next page load", {
1577
1603
  data: { eventCount: eventsToSend.length }
1578
1604
  });
1579
1605
  }
@@ -1593,7 +1619,11 @@ var EventManager = class extends StateManager {
1593
1619
  this.emitEventsQueue(body);
1594
1620
  },
1595
1621
  onFailure: () => {
1596
- log("warn", "Events send failed, keeping in queue", {
1622
+ this.removeProcessedEvents(eventIds);
1623
+ if (this.eventsQueue.length === 0) {
1624
+ this.clearSendInterval();
1625
+ }
1626
+ log("warn", "Events send failed, removed from queue and persisted for recovery on next page load", {
1597
1627
  data: { eventCount: eventsToSend.length }
1598
1628
  });
1599
1629
  }
@@ -2559,7 +2589,7 @@ var ScrollHandler = class extends StateManager {
2559
2589
  minDepthChange = MIN_SCROLL_DEPTH_CHANGE;
2560
2590
  minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;
2561
2591
  maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;
2562
- retryTimeoutId = null;
2592
+ containerDiscoveryTimeoutId = null;
2563
2593
  constructor(eventManager) {
2564
2594
  super();
2565
2595
  this.eventManager = eventManager;
@@ -2571,9 +2601,9 @@ var ScrollHandler = class extends StateManager {
2571
2601
  this.tryDetectScrollContainers(0);
2572
2602
  }
2573
2603
  stopTracking() {
2574
- if (this.retryTimeoutId !== null) {
2575
- clearTimeout(this.retryTimeoutId);
2576
- this.retryTimeoutId = null;
2604
+ if (this.containerDiscoveryTimeoutId !== null) {
2605
+ clearTimeout(this.containerDiscoveryTimeoutId);
2606
+ this.containerDiscoveryTimeoutId = null;
2577
2607
  }
2578
2608
  for (const container of this.containers) {
2579
2609
  this.clearContainerTimer(container);
@@ -2601,8 +2631,8 @@ var ScrollHandler = class extends StateManager {
2601
2631
  return;
2602
2632
  }
2603
2633
  if (attempt < 5) {
2604
- this.retryTimeoutId = window.setTimeout(() => {
2605
- this.retryTimeoutId = null;
2634
+ this.containerDiscoveryTimeoutId = window.setTimeout(() => {
2635
+ this.containerDiscoveryTimeoutId = null;
2606
2636
  this.tryDetectScrollContainers(attempt + 1);
2607
2637
  }, 200);
2608
2638
  return;
@@ -2688,15 +2718,18 @@ var ScrollHandler = class extends StateManager {
2688
2718
  lastDepth: initialDepth,
2689
2719
  lastDirection: "down" /* DOWN */,
2690
2720
  lastEventTime: 0,
2721
+ firstScrollEventTime: null,
2691
2722
  maxDepthReached: initialDepth,
2692
2723
  debounceTimer: null,
2693
2724
  listener: null
2694
- // Will be assigned after handleScroll is defined
2695
2725
  };
2696
2726
  const handleScroll = () => {
2697
2727
  if (this.get("suppressNextScroll")) {
2698
2728
  return;
2699
2729
  }
2730
+ if (container.firstScrollEventTime === null) {
2731
+ container.firstScrollEventTime = Date.now();
2732
+ }
2700
2733
  this.clearContainerTimer(container);
2701
2734
  container.debounceTimer = window.setTimeout(() => {
2702
2735
  const scrollData = this.calculateScrollData(container);
@@ -2807,8 +2840,15 @@ var ScrollHandler = class extends StateManager {
2807
2840
  const scrollHeight = this.getScrollHeight(element);
2808
2841
  const direction = this.getScrollDirection(scrollTop, lastScrollPos);
2809
2842
  const depth = this.calculateScrollDepth(scrollTop, scrollHeight, viewportHeight);
2810
- const timeDelta = lastEventTime > 0 ? now - lastEventTime : 0;
2811
- const velocity = timeDelta > 0 ? Math.round(positionDelta / timeDelta * 1e3) : 0;
2843
+ let timeDelta;
2844
+ if (lastEventTime > 0) {
2845
+ timeDelta = now - lastEventTime;
2846
+ } else if (container.firstScrollEventTime !== null) {
2847
+ timeDelta = now - container.firstScrollEventTime;
2848
+ } else {
2849
+ timeDelta = SCROLL_DEBOUNCE_TIME_MS;
2850
+ }
2851
+ const velocity = Math.round(positionDelta / timeDelta * 1e3);
2812
2852
  if (depth > container.maxDepthReached) {
2813
2853
  container.maxDepthReached = depth;
2814
2854
  }