@tracelog/lib 0.5.4 → 0.6.0

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.
Files changed (200) hide show
  1. package/README.md +157 -180
  2. package/dist/browser/tracelog.esm.js +1007 -1357
  3. package/dist/browser/tracelog.js +2 -2
  4. package/dist/cjs/api.d.ts +12 -2
  5. package/dist/cjs/api.js +63 -27
  6. package/dist/cjs/app.d.ts +2 -2
  7. package/dist/cjs/app.js +26 -32
  8. package/dist/cjs/constants/config.constants.d.ts +4 -2
  9. package/dist/cjs/constants/config.constants.js +6 -18
  10. package/dist/cjs/constants/index.d.ts +0 -1
  11. package/dist/cjs/constants/index.js +0 -1
  12. package/dist/cjs/constants/storage.constants.d.ts +3 -2
  13. package/dist/cjs/constants/storage.constants.js +4 -4
  14. package/dist/cjs/handlers/click.handler.js +3 -6
  15. package/dist/cjs/handlers/error.handler.js +1 -11
  16. package/dist/cjs/handlers/page-view.handler.js +0 -4
  17. package/dist/cjs/handlers/performance.handler.js +14 -29
  18. package/dist/cjs/handlers/scroll.handler.js +7 -6
  19. package/dist/cjs/handlers/session.handler.js +7 -6
  20. package/dist/cjs/integrations/google-analytics.integration.js +2 -6
  21. package/dist/cjs/listeners/activity-listener-manager.js +3 -3
  22. package/dist/cjs/listeners/input-listener-managers.js +3 -3
  23. package/dist/cjs/listeners/touch-listener-manager.js +3 -3
  24. package/dist/cjs/listeners/unload-listener-manager.js +3 -3
  25. package/dist/cjs/listeners/visibility-listener-manager.js +3 -3
  26. package/dist/cjs/managers/event.manager.d.ts +2 -1
  27. package/dist/cjs/managers/event.manager.js +60 -38
  28. package/dist/cjs/managers/sender.manager.js +29 -36
  29. package/dist/cjs/managers/session.manager.js +5 -13
  30. package/dist/cjs/managers/state.manager.d.ts +0 -3
  31. package/dist/cjs/managers/state.manager.js +1 -43
  32. package/dist/cjs/managers/storage.manager.d.ts +16 -2
  33. package/dist/cjs/managers/storage.manager.js +73 -19
  34. package/dist/cjs/managers/user.manager.d.ts +1 -1
  35. package/dist/cjs/managers/user.manager.js +2 -2
  36. package/dist/cjs/public-api.d.ts +3 -3
  37. package/dist/cjs/public-api.js +1 -1
  38. package/dist/cjs/test-bridge.d.ts +1 -0
  39. package/dist/cjs/test-bridge.js +37 -2
  40. package/dist/cjs/types/config.types.d.ts +15 -18
  41. package/dist/cjs/types/config.types.js +6 -0
  42. package/dist/cjs/types/event.types.d.ts +1 -13
  43. package/dist/cjs/types/index.d.ts +0 -2
  44. package/dist/cjs/types/index.js +0 -2
  45. package/dist/cjs/types/mode.types.d.ts +1 -2
  46. package/dist/cjs/types/mode.types.js +0 -1
  47. package/dist/cjs/types/queue.types.d.ts +0 -6
  48. package/dist/cjs/types/state.types.d.ts +2 -0
  49. package/dist/cjs/types/test-bridge.types.d.ts +2 -2
  50. package/dist/cjs/types/validation-error.types.d.ts +0 -6
  51. package/dist/cjs/types/validation-error.types.js +1 -10
  52. package/dist/cjs/utils/browser/device-detector.utils.js +2 -24
  53. package/dist/cjs/utils/browser/index.d.ts +1 -0
  54. package/dist/cjs/utils/browser/index.js +1 -0
  55. package/dist/cjs/utils/browser/qa-mode.utils.d.ts +13 -0
  56. package/dist/cjs/utils/browser/qa-mode.utils.js +43 -0
  57. package/dist/cjs/utils/browser/utm-params.utils.js +0 -15
  58. package/dist/cjs/utils/data/uuid.utils.d.ts +13 -0
  59. package/dist/cjs/utils/data/uuid.utils.js +37 -1
  60. package/dist/cjs/utils/index.d.ts +1 -1
  61. package/dist/cjs/utils/index.js +1 -1
  62. package/dist/cjs/utils/logging.utils.d.ts +6 -0
  63. package/dist/cjs/utils/logging.utils.js +25 -0
  64. package/dist/cjs/utils/network/index.d.ts +0 -1
  65. package/dist/cjs/utils/network/index.js +0 -1
  66. package/dist/cjs/utils/network/url.utils.d.ts +2 -8
  67. package/dist/cjs/utils/network/url.utils.js +46 -90
  68. package/dist/cjs/utils/security/sanitize.utils.d.ts +1 -13
  69. package/dist/cjs/utils/security/sanitize.utils.js +15 -178
  70. package/dist/cjs/utils/validations/config-validations.utils.d.ts +3 -9
  71. package/dist/cjs/utils/validations/config-validations.utils.js +48 -94
  72. package/dist/cjs/utils/validations/event-validations.utils.js +11 -5
  73. package/dist/cjs/utils/validations/index.d.ts +0 -1
  74. package/dist/cjs/utils/validations/index.js +0 -1
  75. package/dist/cjs/utils/validations/metadata-validations.utils.js +0 -1
  76. package/dist/cjs/utils/validations/type-guards.utils.d.ts +2 -2
  77. package/dist/cjs/utils/validations/type-guards.utils.js +50 -4
  78. package/dist/esm/api.d.ts +12 -2
  79. package/dist/esm/api.js +62 -27
  80. package/dist/esm/app.d.ts +2 -2
  81. package/dist/esm/app.js +28 -34
  82. package/dist/esm/constants/config.constants.d.ts +4 -2
  83. package/dist/esm/constants/config.constants.js +4 -16
  84. package/dist/esm/constants/index.d.ts +0 -1
  85. package/dist/esm/constants/index.js +0 -1
  86. package/dist/esm/constants/storage.constants.d.ts +3 -2
  87. package/dist/esm/constants/storage.constants.js +3 -2
  88. package/dist/esm/handlers/click.handler.js +3 -6
  89. package/dist/esm/handlers/error.handler.js +1 -11
  90. package/dist/esm/handlers/page-view.handler.js +0 -4
  91. package/dist/esm/handlers/performance.handler.js +14 -29
  92. package/dist/esm/handlers/scroll.handler.js +7 -6
  93. package/dist/esm/handlers/session.handler.js +7 -6
  94. package/dist/esm/integrations/google-analytics.integration.js +3 -7
  95. package/dist/esm/listeners/activity-listener-manager.js +3 -3
  96. package/dist/esm/listeners/input-listener-managers.js +3 -3
  97. package/dist/esm/listeners/touch-listener-manager.js +3 -3
  98. package/dist/esm/listeners/unload-listener-manager.js +3 -3
  99. package/dist/esm/listeners/visibility-listener-manager.js +3 -3
  100. package/dist/esm/managers/event.manager.d.ts +2 -1
  101. package/dist/esm/managers/event.manager.js +62 -40
  102. package/dist/esm/managers/sender.manager.js +31 -38
  103. package/dist/esm/managers/session.manager.js +5 -13
  104. package/dist/esm/managers/state.manager.d.ts +0 -3
  105. package/dist/esm/managers/state.manager.js +1 -43
  106. package/dist/esm/managers/storage.manager.d.ts +16 -2
  107. package/dist/esm/managers/storage.manager.js +73 -19
  108. package/dist/esm/managers/user.manager.d.ts +1 -1
  109. package/dist/esm/managers/user.manager.js +2 -2
  110. package/dist/esm/public-api.d.ts +3 -3
  111. package/dist/esm/public-api.js +1 -1
  112. package/dist/esm/test-bridge.d.ts +1 -0
  113. package/dist/esm/test-bridge.js +37 -2
  114. package/dist/esm/types/config.types.d.ts +15 -18
  115. package/dist/esm/types/config.types.js +5 -1
  116. package/dist/esm/types/event.types.d.ts +1 -13
  117. package/dist/esm/types/index.d.ts +0 -2
  118. package/dist/esm/types/index.js +0 -2
  119. package/dist/esm/types/mode.types.d.ts +1 -2
  120. package/dist/esm/types/mode.types.js +0 -1
  121. package/dist/esm/types/queue.types.d.ts +0 -6
  122. package/dist/esm/types/state.types.d.ts +2 -0
  123. package/dist/esm/types/test-bridge.types.d.ts +2 -2
  124. package/dist/esm/types/validation-error.types.d.ts +0 -6
  125. package/dist/esm/types/validation-error.types.js +0 -8
  126. package/dist/esm/utils/browser/device-detector.utils.js +2 -24
  127. package/dist/esm/utils/browser/index.d.ts +1 -0
  128. package/dist/esm/utils/browser/index.js +1 -0
  129. package/dist/esm/utils/browser/qa-mode.utils.d.ts +13 -0
  130. package/dist/esm/utils/browser/qa-mode.utils.js +39 -0
  131. package/dist/esm/utils/browser/utm-params.utils.js +0 -15
  132. package/dist/esm/utils/data/uuid.utils.d.ts +13 -0
  133. package/dist/esm/utils/data/uuid.utils.js +35 -0
  134. package/dist/esm/utils/index.d.ts +1 -1
  135. package/dist/esm/utils/index.js +1 -1
  136. package/dist/esm/utils/logging.utils.d.ts +6 -0
  137. package/dist/esm/utils/logging.utils.js +20 -0
  138. package/dist/esm/utils/network/index.d.ts +0 -1
  139. package/dist/esm/utils/network/index.js +0 -1
  140. package/dist/esm/utils/network/url.utils.d.ts +2 -8
  141. package/dist/esm/utils/network/url.utils.js +45 -88
  142. package/dist/esm/utils/security/sanitize.utils.d.ts +1 -13
  143. package/dist/esm/utils/security/sanitize.utils.js +15 -176
  144. package/dist/esm/utils/validations/config-validations.utils.d.ts +3 -9
  145. package/dist/esm/utils/validations/config-validations.utils.js +49 -94
  146. package/dist/esm/utils/validations/event-validations.utils.js +11 -5
  147. package/dist/esm/utils/validations/index.d.ts +0 -1
  148. package/dist/esm/utils/validations/index.js +0 -1
  149. package/dist/esm/utils/validations/metadata-validations.utils.js +0 -1
  150. package/dist/esm/utils/validations/type-guards.utils.d.ts +2 -2
  151. package/dist/esm/utils/validations/type-guards.utils.js +50 -4
  152. package/package.json +1 -1
  153. package/dist/cjs/app.types.d.ts +0 -2
  154. package/dist/cjs/app.types.js +0 -12
  155. package/dist/cjs/constants/api.constants.d.ts +0 -6
  156. package/dist/cjs/constants/api.constants.js +0 -14
  157. package/dist/cjs/managers/api.manager.d.ts +0 -13
  158. package/dist/cjs/managers/api.manager.js +0 -44
  159. package/dist/cjs/managers/config.builder.d.ts +0 -33
  160. package/dist/cjs/managers/config.builder.js +0 -116
  161. package/dist/cjs/managers/config.manager.d.ts +0 -56
  162. package/dist/cjs/managers/config.manager.js +0 -157
  163. package/dist/cjs/managers/tags.manager.d.ts +0 -36
  164. package/dist/cjs/managers/tags.manager.js +0 -171
  165. package/dist/cjs/types/api.types.d.ts +0 -52
  166. package/dist/cjs/types/api.types.js +0 -56
  167. package/dist/cjs/types/tag.types.d.ts +0 -43
  168. package/dist/cjs/types/tag.types.js +0 -31
  169. package/dist/cjs/utils/logging/debug-logger.utils.d.ts +0 -14
  170. package/dist/cjs/utils/logging/debug-logger.utils.js +0 -47
  171. package/dist/cjs/utils/logging/index.d.ts +0 -1
  172. package/dist/cjs/utils/logging/index.js +0 -5
  173. package/dist/cjs/utils/network/fetch-with-timeout.utils.d.ts +0 -4
  174. package/dist/cjs/utils/network/fetch-with-timeout.utils.js +0 -25
  175. package/dist/cjs/utils/validations/url-validations.utils.d.ts +0 -15
  176. package/dist/cjs/utils/validations/url-validations.utils.js +0 -47
  177. package/dist/esm/app.types.d.ts +0 -2
  178. package/dist/esm/app.types.js +0 -1
  179. package/dist/esm/constants/api.constants.d.ts +0 -6
  180. package/dist/esm/constants/api.constants.js +0 -11
  181. package/dist/esm/managers/api.manager.d.ts +0 -13
  182. package/dist/esm/managers/api.manager.js +0 -41
  183. package/dist/esm/managers/config.builder.d.ts +0 -33
  184. package/dist/esm/managers/config.builder.js +0 -112
  185. package/dist/esm/managers/config.manager.d.ts +0 -56
  186. package/dist/esm/managers/config.manager.js +0 -153
  187. package/dist/esm/managers/tags.manager.d.ts +0 -36
  188. package/dist/esm/managers/tags.manager.js +0 -167
  189. package/dist/esm/types/api.types.d.ts +0 -52
  190. package/dist/esm/types/api.types.js +0 -53
  191. package/dist/esm/types/tag.types.d.ts +0 -43
  192. package/dist/esm/types/tag.types.js +0 -28
  193. package/dist/esm/utils/logging/debug-logger.utils.d.ts +0 -14
  194. package/dist/esm/utils/logging/debug-logger.utils.js +0 -44
  195. package/dist/esm/utils/logging/index.d.ts +0 -1
  196. package/dist/esm/utils/logging/index.js +0 -1
  197. package/dist/esm/utils/network/fetch-with-timeout.utils.d.ts +0 -4
  198. package/dist/esm/utils/network/fetch-with-timeout.utils.js +0 -22
  199. package/dist/esm/utils/validations/url-validations.utils.d.ts +0 -15
  200. package/dist/esm/utils/validations/url-validations.utils.js +0 -42
@@ -1,8 +1,7 @@
1
1
  import { StateManager } from '../managers/state.manager';
2
2
  import { EventType } from '../types';
3
- import { LONG_TASK_THROTTLE_MS, PRECISION_TWO_DECIMALS } from '../constants';
4
- import { WEB_VITALS_THRESHOLDS } from '../constants/performance.constants';
5
- import { debugLog } from '../utils/logging';
3
+ import { LONG_TASK_THROTTLE_MS, PRECISION_TWO_DECIMALS, WEB_VITALS_THRESHOLDS } from '../constants';
4
+ import { log } from '@/utils';
6
5
  export class PerformanceHandler extends StateManager {
7
6
  constructor(eventManager) {
8
7
  super();
@@ -22,10 +21,7 @@ export class PerformanceHandler extends StateManager {
22
21
  obs.disconnect();
23
22
  }
24
23
  catch (error) {
25
- debugLog.warn('PerformanceHandler', 'Failed to disconnect performance observer', {
26
- error: error instanceof Error ? error.message : 'Unknown error',
27
- observerIndex: index,
28
- });
24
+ log('warn', 'Failed to disconnect performance observer', { error, data: { observerIndex: index } });
29
25
  }
30
26
  });
31
27
  this.observers.length = 0;
@@ -98,9 +94,7 @@ export class PerformanceHandler extends StateManager {
98
94
  onINP(report('INP'));
99
95
  }
100
96
  catch (error) {
101
- debugLog.warn('PerformanceHandler', 'Failed to load web-vitals library, using fallback', {
102
- error: error instanceof Error ? error.message : 'Unknown error',
103
- });
97
+ log('warn', 'Failed to load web-vitals library, using fallback', { error });
104
98
  this.observeWebVitalsFallback();
105
99
  }
106
100
  }
@@ -121,9 +115,7 @@ export class PerformanceHandler extends StateManager {
121
115
  }
122
116
  }
123
117
  catch (error) {
124
- debugLog.warn('PerformanceHandler', 'Failed to report TTFB', {
125
- error: error instanceof Error ? error.message : 'Unknown error',
126
- });
118
+ log('warn', 'Failed to report TTFB', { error });
127
119
  }
128
120
  }
129
121
  observeLongTasks() {
@@ -165,7 +157,7 @@ export class PerformanceHandler extends StateManager {
165
157
  }
166
158
  trackWebVital(type, value) {
167
159
  if (!Number.isFinite(value)) {
168
- debugLog.warn('PerformanceHandler', 'Invalid web vital value', { type, value });
160
+ log('warn', 'Invalid web vital value', { data: { type, value } });
169
161
  return;
170
162
  }
171
163
  this.eventManager.track({
@@ -188,9 +180,7 @@ export class PerformanceHandler extends StateManager {
188
180
  return `${timestamp.toFixed(2)}_${window.location.pathname}_${random}`;
189
181
  }
190
182
  catch (error) {
191
- debugLog.warn('PerformanceHandler', 'Failed to get navigation ID', {
192
- error: error instanceof Error ? error.message : 'Unknown error',
193
- });
183
+ log('warn', 'Failed to get navigation ID', { error });
194
184
  return null;
195
185
  }
196
186
  }
@@ -210,9 +200,9 @@ export class PerformanceHandler extends StateManager {
210
200
  cb(list, observer);
211
201
  }
212
202
  catch (callbackError) {
213
- debugLog.warn('PerformanceHandler', 'Observer callback failed', {
214
- type,
215
- error: callbackError instanceof Error ? callbackError.message : 'Unknown error',
203
+ log('warn', 'Observer callback failed', {
204
+ error: callbackError,
205
+ data: { type },
216
206
  });
217
207
  }
218
208
  if (once) {
@@ -231,25 +221,20 @@ export class PerformanceHandler extends StateManager {
231
221
  return true;
232
222
  }
233
223
  catch (error) {
234
- debugLog.warn('PerformanceHandler', 'Failed to create performance observer', {
235
- type,
236
- error: error instanceof Error ? error.message : 'Unknown error',
224
+ log('warn', 'Failed to create performance observer', {
225
+ error,
226
+ data: { type },
237
227
  });
238
228
  return false;
239
229
  }
240
230
  }
241
231
  shouldSendVital(type, value) {
242
232
  if (typeof value !== 'number' || !Number.isFinite(value)) {
243
- debugLog.warn('PerformanceHandler', 'Invalid web vital value', { type, value });
233
+ log('warn', 'Invalid web vital value', { data: { type, value } });
244
234
  return false;
245
235
  }
246
236
  const threshold = this.vitalThresholds[type];
247
237
  if (typeof threshold === 'number' && value <= threshold) {
248
- debugLog.debug('PerformanceHandler', 'Web vital below threshold, skipping', {
249
- type,
250
- value,
251
- threshold,
252
- });
253
238
  return false;
254
239
  }
255
240
  return true;
@@ -1,7 +1,7 @@
1
1
  import { MAX_SCROLL_EVENTS_PER_SESSION, MIN_SCROLL_DEPTH_CHANGE, SCROLL_DEBOUNCE_TIME_MS, SCROLL_MIN_EVENT_INTERVAL_MS, SIGNIFICANT_SCROLL_DELTA, } from '../constants';
2
2
  import { EventType, ScrollDirection } from '../types';
3
3
  import { StateManager } from '../managers/state.manager';
4
- import { debugLog } from '../utils/logging';
4
+ import { log } from '../utils';
5
5
  export class ScrollHandler extends StateManager {
6
6
  constructor(eventManager) {
7
7
  super();
@@ -141,8 +141,8 @@ export class ScrollHandler extends StateManager {
141
141
  return;
142
142
  }
143
143
  this.limitWarningLogged = true;
144
- debugLog.warn('ScrollHandler', 'Max scroll events per session reached', {
145
- limit: this.maxEventsPerSession,
144
+ log('warn', 'Max scroll events per session reached', {
145
+ data: { limit: this.maxEventsPerSession },
146
146
  });
147
147
  }
148
148
  applyConfigOverrides() {
@@ -211,9 +211,10 @@ export class ScrollHandler extends StateManager {
211
211
  return document.querySelector(selector);
212
212
  }
213
213
  catch (error) {
214
- debugLog.clientWarn('ScrollHandler', 'Invalid CSS selector', {
215
- selector,
216
- error: error instanceof Error ? error.message : 'Unknown error',
214
+ log('warn', 'Invalid CSS selector', {
215
+ error,
216
+ data: { selector },
217
+ showToClient: true,
217
218
  });
218
219
  return null;
219
220
  }
@@ -1,6 +1,6 @@
1
1
  import { SessionManager } from '../managers/session.manager';
2
2
  import { StateManager } from '../managers/state.manager';
3
- import { debugLog } from '../utils/logging';
3
+ import { log } from '../utils';
4
4
  export class SessionHandler extends StateManager {
5
5
  constructor(storageManager, eventManager) {
6
6
  super();
@@ -14,16 +14,19 @@ export class SessionHandler extends StateManager {
14
14
  return;
15
15
  }
16
16
  if (this.destroyed) {
17
- debugLog.warn('SessionHandler', 'Cannot start tracking on destroyed handler');
17
+ log('warn', 'Cannot start tracking on destroyed handler');
18
18
  return;
19
19
  }
20
- const projectId = this.get('config')?.id;
20
+ const config = this.get('config');
21
+ const projectId = config?.integrations?.tracelog?.projectId ?? config?.integrations?.custom?.apiUrl ?? 'default';
21
22
  if (!projectId) {
22
23
  throw new Error('Cannot start session tracking: config not available');
23
24
  }
24
25
  try {
25
26
  this.sessionManager = new SessionManager(this.storageManager, this.eventManager, projectId);
26
27
  await this.sessionManager.startTracking();
28
+ // Flush any events that were buffered during initialization
29
+ this.eventManager.flushPendingEvents();
27
30
  }
28
31
  catch (error) {
29
32
  if (this.sessionManager) {
@@ -35,9 +38,7 @@ export class SessionHandler extends StateManager {
35
38
  }
36
39
  this.sessionManager = null;
37
40
  }
38
- debugLog.error('SessionHandler', 'Failed to start session tracking', {
39
- error: error instanceof Error ? error.message : 'Unknown error',
40
- });
41
+ log('error', 'Failed to start session tracking', { error });
41
42
  throw error;
42
43
  }
43
44
  }
@@ -1,4 +1,4 @@
1
- import { debugLog } from '../utils';
1
+ import { log } from '../utils';
2
2
  import { StateManager } from '../managers/state.manager';
3
3
  export class GoogleAnalyticsIntegration extends StateManager {
4
4
  constructor() {
@@ -24,9 +24,7 @@ export class GoogleAnalyticsIntegration extends StateManager {
24
24
  this.isInitialized = true;
25
25
  }
26
26
  catch (error) {
27
- debugLog.error('GoogleAnalyticsIntegration', 'Initialization failed', {
28
- error: error instanceof Error ? error.message : 'Unknown error',
29
- });
27
+ log('error', 'Google Analytics initialization failed', { error });
30
28
  }
31
29
  }
32
30
  trackEvent(eventName, metadata) {
@@ -38,9 +36,7 @@ export class GoogleAnalyticsIntegration extends StateManager {
38
36
  window.gtag('event', eventName, normalizedMetadata);
39
37
  }
40
38
  catch (error) {
41
- debugLog.error('GoogleAnalyticsIntegration', 'Event tracking failed', {
42
- error: error instanceof Error ? error.message : 'Unknown error',
43
- });
39
+ log('error', 'Google Analytics event tracking failed', { error });
44
40
  }
45
41
  }
46
42
  cleanup() {
@@ -1,4 +1,4 @@
1
- import { debugLog } from '../utils/logging';
1
+ import { log } from '../utils';
2
2
  export class ActivityListenerManager {
3
3
  constructor(onActivity) {
4
4
  this.options = { passive: true };
@@ -11,7 +11,7 @@ export class ActivityListenerManager {
11
11
  window.addEventListener('focus', this.onActivity, this.options);
12
12
  }
13
13
  catch (error) {
14
- debugLog.error('ActivityListenerManager', 'Failed to setup activity listeners', { error });
14
+ log('error', 'Failed to setup activity listeners', { error });
15
15
  throw error;
16
16
  }
17
17
  }
@@ -22,7 +22,7 @@ export class ActivityListenerManager {
22
22
  window.removeEventListener('focus', this.onActivity);
23
23
  }
24
24
  catch (error) {
25
- debugLog.warn('ActivityListenerManager', 'Error during activity listeners cleanup', { error });
25
+ log('warn', 'Error during activity listeners cleanup', { error });
26
26
  }
27
27
  }
28
28
  }
@@ -1,4 +1,4 @@
1
- import { debugLog } from '../utils/logging';
1
+ import { log } from '../utils';
2
2
  /**
3
3
  * Base class for input listener managers to reduce code duplication
4
4
  */
@@ -14,7 +14,7 @@ class BaseInputListenerManager {
14
14
  });
15
15
  }
16
16
  catch (error) {
17
- debugLog.error(this.logPrefix, `Failed to setup ${this.logPrefix.toLowerCase()} listeners`, { error });
17
+ log('error', `Failed to setup ${this.logPrefix.toLowerCase()} listeners`, { error });
18
18
  }
19
19
  }
20
20
  cleanup() {
@@ -24,7 +24,7 @@ class BaseInputListenerManager {
24
24
  });
25
25
  }
26
26
  catch (error) {
27
- debugLog.warn(this.logPrefix, `Error during ${this.logPrefix.toLowerCase()} listeners cleanup`, { error });
27
+ log('warn', `Error during ${this.logPrefix.toLowerCase()} listeners cleanup`, { error });
28
28
  }
29
29
  }
30
30
  }
@@ -1,4 +1,4 @@
1
- import { debugLog } from '../utils/logging';
1
+ import { log } from '../utils';
2
2
  export class TouchListenerManager {
3
3
  constructor(onActivity) {
4
4
  this.options = { passive: true };
@@ -12,7 +12,7 @@ export class TouchListenerManager {
12
12
  window.addEventListener('orientationchange', this.onActivity, this.options);
13
13
  }
14
14
  catch (error) {
15
- debugLog.error('TouchListenerManager', 'Failed to setup touch listeners', { error });
15
+ log('error', 'Failed to setup touch listeners', { error });
16
16
  throw error;
17
17
  }
18
18
  }
@@ -24,7 +24,7 @@ export class TouchListenerManager {
24
24
  window.removeEventListener('orientationchange', this.onActivity);
25
25
  }
26
26
  catch (error) {
27
- debugLog.warn('TouchListenerManager', 'Error during touch listeners cleanup', { error });
27
+ log('warn', 'Error during touch listeners cleanup', { error });
28
28
  }
29
29
  }
30
30
  }
@@ -1,4 +1,4 @@
1
- import { debugLog } from '../utils/logging';
1
+ import { log } from '../utils';
2
2
  export class UnloadListenerManager {
3
3
  constructor(onInactivity) {
4
4
  this.options = { passive: true };
@@ -10,7 +10,7 @@ export class UnloadListenerManager {
10
10
  window.addEventListener('pagehide', this.onInactivity, this.options);
11
11
  }
12
12
  catch (error) {
13
- debugLog.error('UnloadListenerManager', 'Failed to setup unload listeners', { error });
13
+ log('error', 'Failed to setup unload listeners', { error });
14
14
  throw error;
15
15
  }
16
16
  }
@@ -20,7 +20,7 @@ export class UnloadListenerManager {
20
20
  window.removeEventListener('pagehide', this.onInactivity);
21
21
  }
22
22
  catch (error) {
23
- debugLog.warn('UnloadListenerManager', 'Error during unload listeners cleanup', { error });
23
+ log('warn', 'Error during unload listeners cleanup', { error });
24
24
  }
25
25
  }
26
26
  }
@@ -1,4 +1,4 @@
1
- import { debugLog } from '../utils/logging';
1
+ import { log } from '../utils';
2
2
  export class VisibilityListenerManager {
3
3
  constructor(onActivity, onVisibilityChange) {
4
4
  this.options = { passive: true };
@@ -21,7 +21,7 @@ export class VisibilityListenerManager {
21
21
  }
22
22
  }
23
23
  catch (error) {
24
- debugLog.error('VisibilityListenerManager', 'Failed to setup visibility listeners', { error });
24
+ log('error', 'Failed to setup visibility listeners', { error });
25
25
  }
26
26
  }
27
27
  cleanup() {
@@ -37,7 +37,7 @@ export class VisibilityListenerManager {
37
37
  }
38
38
  }
39
39
  catch (error) {
40
- debugLog.warn('VisibilityListenerManager', 'Error during visibility listeners cleanup', { error });
40
+ log('warn', 'Error during visibility listeners cleanup', { error });
41
41
  }
42
42
  }
43
43
  }
@@ -8,6 +8,7 @@ export declare class EventManager extends StateManager {
8
8
  private readonly dataSender;
9
9
  private readonly emitter;
10
10
  private eventsQueue;
11
+ private pendingEventsBuffer;
11
12
  private lastEventFingerprint;
12
13
  private lastEventTime;
13
14
  private sendIntervalId;
@@ -18,12 +19,12 @@ export declare class EventManager extends StateManager {
18
19
  flushImmediately(): Promise<boolean>;
19
20
  flushImmediatelySync(): boolean;
20
21
  getQueueLength(): number;
22
+ flushPendingEvents(): void;
21
23
  private clearSendInterval;
22
24
  private flushEvents;
23
25
  private sendEventsQueue;
24
26
  private buildEventsPayload;
25
27
  private buildEventPayload;
26
- private isEventExcluded;
27
28
  private isDuplicateEvent;
28
29
  private createEventFingerprint;
29
30
  private createEventSignature;
@@ -1,12 +1,13 @@
1
1
  import { EVENT_SENT_INTERVAL_MS, MAX_EVENTS_QUEUE_LENGTH, DUPLICATE_EVENT_THRESHOLD_MS, } from '../constants/config.constants';
2
- import { EmitterEvent, EventType } from '../types';
3
- import { getUTMParameters, isUrlPathExcluded, debugLog } from '../utils';
2
+ import { EmitterEvent, EventType, Mode } from '../types';
3
+ import { getUTMParameters, log, generateEventId } from '../utils';
4
4
  import { SenderManager } from './sender.manager';
5
5
  import { StateManager } from './state.manager';
6
6
  export class EventManager extends StateManager {
7
7
  constructor(storeManager, googleAnalytics = null, emitter = null) {
8
8
  super();
9
9
  this.eventsQueue = [];
10
+ this.pendingEventsBuffer = [];
10
11
  this.lastEventFingerprint = null;
11
12
  this.lastEventTime = 0;
12
13
  this.sendIntervalId = null;
@@ -18,7 +19,7 @@ export class EventManager extends StateManager {
18
19
  await this.dataSender.recoverPersistedEvents({
19
20
  onSuccess: (_eventCount, recoveredEvents, body) => {
20
21
  if (recoveredEvents && recoveredEvents.length > 0) {
21
- const eventIds = recoveredEvents.map((e) => e.timestamp + '_' + e.type);
22
+ const eventIds = recoveredEvents.map((e) => e.id);
22
23
  this.removeProcessedEvents(eventIds);
23
24
  if (body) {
24
25
  this.emitEventsQueue(body);
@@ -26,13 +27,27 @@ export class EventManager extends StateManager {
26
27
  }
27
28
  },
28
29
  onFailure: async () => {
29
- debugLog.warn('EventManager', 'Failed to recover persisted events');
30
+ log('warn', 'Failed to recover persisted events');
30
31
  },
31
32
  });
32
33
  }
33
34
  track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, }) {
34
35
  if (!type) {
35
- debugLog.warn('EventManager', 'Event type is required');
36
+ log('warn', 'Event type is required');
37
+ return;
38
+ }
39
+ if (!this.get('sessionId')) {
40
+ this.pendingEventsBuffer.push({
41
+ type,
42
+ page_url,
43
+ from_page_url,
44
+ scroll_data,
45
+ click_data,
46
+ custom_event,
47
+ web_vitals,
48
+ error_data,
49
+ session_end_reason,
50
+ });
36
51
  return;
37
52
  }
38
53
  const eventType = type;
@@ -51,21 +66,18 @@ export class EventManager extends StateManager {
51
66
  error_data,
52
67
  session_end_reason,
53
68
  });
54
- if (this.isEventExcluded(payload)) {
55
- return;
56
- }
57
69
  if (!isCriticalEvent && !this.shouldSample()) {
58
70
  return;
59
71
  }
60
72
  if (isSessionStart) {
61
73
  const currentSessionId = this.get('sessionId');
62
74
  if (!currentSessionId) {
63
- debugLog.warn('EventManager', 'Session start event ignored: missing sessionId');
75
+ log('warn', 'Session start event ignored: missing sessionId');
64
76
  return;
65
77
  }
66
78
  if (this.get('hasStartSession')) {
67
- debugLog.warn('EventManager', 'Duplicate session_start detected', {
68
- sessionId: currentSessionId,
79
+ log('warn', 'Duplicate session_start detected', {
80
+ data: { sessionId: currentSessionId },
69
81
  });
70
82
  return;
71
83
  }
@@ -74,6 +86,14 @@ export class EventManager extends StateManager {
74
86
  if (this.isDuplicateEvent(payload)) {
75
87
  return;
76
88
  }
89
+ if (this.get('mode') === Mode.QA && eventType === EventType.CUSTOM && custom_event) {
90
+ console.log('[TraceLog] Event', {
91
+ name: custom_event.name,
92
+ ...(custom_event.metadata && { metadata: custom_event.metadata }),
93
+ });
94
+ this.emitEvent(payload);
95
+ return;
96
+ }
77
97
  this.addToQueue(payload);
78
98
  }
79
99
  stop() {
@@ -82,6 +102,7 @@ export class EventManager extends StateManager {
82
102
  this.sendIntervalId = null;
83
103
  }
84
104
  this.eventsQueue = [];
105
+ this.pendingEventsBuffer = [];
85
106
  this.lastEventFingerprint = null;
86
107
  this.lastEventTime = 0;
87
108
  this.dataSender.stop();
@@ -95,6 +116,20 @@ export class EventManager extends StateManager {
95
116
  getQueueLength() {
96
117
  return this.eventsQueue.length;
97
118
  }
119
+ flushPendingEvents() {
120
+ if (this.pendingEventsBuffer.length === 0) {
121
+ return;
122
+ }
123
+ if (!this.get('sessionId')) {
124
+ log('warn', 'Cannot flush pending events: session not initialized');
125
+ return;
126
+ }
127
+ const bufferedEvents = [...this.pendingEventsBuffer];
128
+ this.pendingEventsBuffer = [];
129
+ bufferedEvents.forEach((event) => {
130
+ this.track(event);
131
+ });
132
+ }
98
133
  clearSendInterval() {
99
134
  if (this.sendIntervalId) {
100
135
  clearInterval(this.sendIntervalId);
@@ -107,7 +142,7 @@ export class EventManager extends StateManager {
107
142
  }
108
143
  const body = this.buildEventsPayload();
109
144
  const eventsToSend = [...this.eventsQueue];
110
- const eventIds = eventsToSend.map((e) => `${e.timestamp}_${e.type}`);
145
+ const eventIds = eventsToSend.map((e) => e.id);
111
146
  if (isSync) {
112
147
  const success = this.dataSender.sendEventsQueueSync(body);
113
148
  if (success) {
@@ -125,8 +160,8 @@ export class EventManager extends StateManager {
125
160
  this.emitEventsQueue(body);
126
161
  },
127
162
  onFailure: () => {
128
- debugLog.warn('EventManager', 'Async flush failed', {
129
- eventCount: eventsToSend.length,
163
+ log('warn', 'Async flush failed', {
164
+ data: { eventCount: eventsToSend.length },
130
165
  });
131
166
  },
132
167
  });
@@ -138,15 +173,15 @@ export class EventManager extends StateManager {
138
173
  }
139
174
  const body = this.buildEventsPayload();
140
175
  const eventsToSend = [...this.eventsQueue];
141
- const eventIds = eventsToSend.map((e) => `${e.timestamp}_${e.type}`);
176
+ const eventIds = eventsToSend.map((e) => e.id);
142
177
  await this.dataSender.sendEventsQueue(body, {
143
178
  onSuccess: () => {
144
179
  this.removeProcessedEvents(eventIds);
145
180
  this.emitEventsQueue(body);
146
181
  },
147
182
  onFailure: async () => {
148
- debugLog.warn('EventManager', 'Events send failed, keeping in queue', {
149
- eventCount: eventsToSend.length,
183
+ log('warn', 'Events send failed, keeping in queue', {
184
+ data: { eventCount: eventsToSend.length },
150
185
  });
151
186
  },
152
187
  });
@@ -177,6 +212,7 @@ export class EventManager extends StateManager {
177
212
  const isSessionStart = data.type === EventType.SESSION_START;
178
213
  const currentPageUrl = data.page_url ?? this.get('pageUrl');
179
214
  const payload = {
215
+ id: generateEventId(),
180
216
  type: data.type,
181
217
  page_url: currentPageUrl,
182
218
  timestamp: Date.now(),
@@ -190,23 +226,8 @@ export class EventManager extends StateManager {
190
226
  ...(data.session_end_reason && { session_end_reason: data.session_end_reason }),
191
227
  ...(isSessionStart && getUTMParameters() && { utm: getUTMParameters() }),
192
228
  };
193
- const projectTags = this.get('config')?.tags;
194
- if (projectTags?.length) {
195
- payload.tags = projectTags;
196
- }
197
229
  return payload;
198
230
  }
199
- isEventExcluded(event) {
200
- const config = this.get('config');
201
- const isRouteExcluded = isUrlPathExcluded(event.page_url, config?.excludedUrlPaths ?? []);
202
- const hasStartSession = this.get('hasStartSession');
203
- const isSessionEndEvent = event.type === EventType.SESSION_END;
204
- const isSessionStartEvent = event.type === EventType.SESSION_START;
205
- if (isRouteExcluded && !isSessionStartEvent && !(isSessionEndEvent && hasStartSession)) {
206
- return true;
207
- }
208
- return config?.ipExcluded === true;
209
- }
210
231
  isDuplicateEvent(event) {
211
232
  const now = Date.now();
212
233
  const fingerprint = this.createEventFingerprint(event);
@@ -247,11 +268,13 @@ export class EventManager extends StateManager {
247
268
  if (this.eventsQueue.length > MAX_EVENTS_QUEUE_LENGTH) {
248
269
  const nonCriticalIndex = this.eventsQueue.findIndex((e) => e.type !== EventType.SESSION_START && e.type !== EventType.SESSION_END);
249
270
  const removedEvent = nonCriticalIndex >= 0 ? this.eventsQueue.splice(nonCriticalIndex, 1)[0] : this.eventsQueue.shift();
250
- debugLog.warn('EventManager', 'Event queue overflow, oldest non-critical event removed', {
251
- maxLength: MAX_EVENTS_QUEUE_LENGTH,
252
- currentLength: this.eventsQueue.length,
253
- removedEventType: removedEvent?.type,
254
- wasCritical: removedEvent?.type === EventType.SESSION_START || removedEvent?.type === EventType.SESSION_END,
271
+ log('warn', 'Event queue overflow, oldest non-critical event removed', {
272
+ data: {
273
+ maxLength: MAX_EVENTS_QUEUE_LENGTH,
274
+ currentLength: this.eventsQueue.length,
275
+ removedEventType: removedEvent?.type,
276
+ wasCritical: removedEvent?.type === EventType.SESSION_START || removedEvent?.type === EventType.SESSION_END,
277
+ },
255
278
  });
256
279
  }
257
280
  if (!this.sendIntervalId) {
@@ -268,7 +291,7 @@ export class EventManager extends StateManager {
268
291
  }
269
292
  handleGoogleAnalyticsIntegration(event) {
270
293
  if (this.googleAnalytics && event.type === EventType.CUSTOM && event.custom_event) {
271
- if (this.get('config')?.mode === 'qa' || this.get('config')?.mode === 'debug') {
294
+ if (this.get('mode') === Mode.QA) {
272
295
  return;
273
296
  }
274
297
  this.googleAnalytics.trackEvent(event.custom_event.name, event.custom_event.metadata ?? {});
@@ -281,8 +304,7 @@ export class EventManager extends StateManager {
281
304
  removeProcessedEvents(eventIds) {
282
305
  const eventIdSet = new Set(eventIds);
283
306
  this.eventsQueue = this.eventsQueue.filter((event) => {
284
- const eventId = `${event.timestamp}_${event.type}`;
285
- return !eventIdSet.has(eventId);
307
+ return !eventIdSet.has(event.id);
286
308
  });
287
309
  }
288
310
  emitEvent(eventData) {