@coralogix/browser 3.10.0 → 3.16.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,60 @@
1
+ ## 3.16.0 (2026-06-24)
2
+
3
+ ### 🚀 Features
4
+
5
+ - Add support for configuring fetch priority on SDK network requests
6
+
7
+ ## 3.15.1 (2026-06-23)
8
+
9
+ ### 🩹 Fixes
10
+
11
+ - Improve user-interaction tracking accuracy
12
+
13
+ ## 3.15.0 (2026-06-22)
14
+
15
+ ### 🚀 Features
16
+
17
+ - Improved user-interaction tracking: smarter element fingerprinting and more accurate screenshot capture on clicks and navigation.
18
+
19
+
20
+ ## 3.14.0 (2026-06-14)
21
+
22
+ ### 🚀 Features
23
+
24
+ - Flush telemetry data on tab close with fetch keepalive support
25
+
26
+ ## 3.13.0 (2026-06-11)
27
+
28
+ ### 🚀 Features
29
+
30
+ - Improve user interaction with click and scroll coordinates, and viewport context
31
+
32
+
33
+ ## 3.12.0 (2026-06-09)
34
+
35
+ ### 🚀 Features
36
+
37
+ - Improve: capture screenshot on each unique view navigation
38
+
39
+ ## 3.11.1 (2026-06-08)
40
+
41
+ ### 🩹 Fixes
42
+
43
+ - SVG element support in session recording
44
+ - session recording after refreshing the page
45
+
46
+ ## 3.11.0 (2026-06-04)
47
+
48
+ ### 🚀 Features
49
+
50
+ - Add view number tracking for product analytics support
51
+
52
+ ## 3.10.1 (2026-06-02)
53
+
54
+ ### 🩹 Fixes
55
+
56
+ - Improve beforeSend to correctly reflect modifications in OpenTelemetry span attributes
57
+
1
58
  ## 3.10.0 (2026-05-25)
2
59
 
3
60
  ### 🚀 Features
package/README.md CHANGED
@@ -22,46 +22,60 @@
22
22
  - [Worker URL](#worker-url)
23
23
  - [Screenshots](#screenshots)
24
24
 
25
- 10. [Network Extra Configuration](#network-extra-configuration)
26
- 11. [Multi Page Application](#multi-page-application)
27
- 12. [Ignore Errors](#ignore-errors)
28
- 13. [Ignore URLs](#ignore-urls)
29
- 14. [Stack Trace Limit](#stack-trace-limit)
30
- 15. [Mask Elements](#mask-elements)
31
- 16. [Label Providers](#label-providers)
32
- 17. [URL Blueprinters](#url-blueprinters)
33
- 18. [Traces](#traces)
25
+ 10. [Unique Users](#unique-users)
26
+ 11. [Network Extra Configuration](#network-extra-configuration)
27
+ 12. [Multi Page Application](#multi-page-application)
28
+ 13. [Ignore Errors](#ignore-errors)
29
+ 14. [Ignore URLs](#ignore-urls)
30
+ 15. [Stack Trace Limit](#stack-trace-limit)
31
+ 16. [Mask Elements](#mask-elements)
32
+ 17. [Custom Action Names](#custom-action-names)
33
+ 18. [Label Providers](#label-providers)
34
+ 19. [URL Blueprinters](#url-blueprinters)
35
+ 20. [Traces](#traces)
34
36
 
35
37
  - [Propagate Trace Header for CORS URLs](#propagatetraceheadercorsurls)
36
38
  - [Allowed Tracing URLs](#allowedtracingurls)
37
39
  - [Extra Propagators (B3 / AWS X-Ray)](#b3--aws-x-ray-propagation)
40
+ - [Custom Propagation](#custom-propagation)
41
+ - [Traces Exporter](#traces-exporter)
38
42
 
39
- 19. [Before Send](#before-send)
40
- 20. [Proxy URL](#proxy-url)
41
- 21. [Collect IP Data](#collect-ip-data)
42
- 22. [Custom Measurement](#custom-measurement)
43
- 23. [Add Timing](#add-timing)
44
- 24. [Custom Time Measurement](#custom-time-measurement)
45
- 25. [Microfrontend Support](#microfrontend-support)
43
+ 21. [Before Send](#before-send)
44
+ 22. [Proxy URL](#proxy-url)
45
+
46
+ - [ignoreProxyUrlParams](#ignoreproxyurlparams)
47
+
48
+ 23. [Collect IP Data](#collect-ip-data)
49
+ 24. [SDK Fetch Priority](#sdk-fetch-priority)
50
+ 25. [Custom Measurement](#custom-measurement)
51
+ 26. [Add Timing](#add-timing)
52
+ 27. [Custom Time Measurement](#custom-time-measurement)
53
+ 28. [Microfrontend Support](#microfrontend-support)
46
54
 
47
55
  - [Pre Requisites](#pre-requisites)
48
56
 
49
- 26. [Custom Spans](#custom-spans)
57
+ 29. [Custom Spans](#custom-spans)
50
58
 
51
59
  - [Ignored Instruments](#ignored-instruments)
52
60
 
53
- 27. [Soft Navigations (Experimental)](#soft-navigations--experimental)
54
- 28. [Memory Usage (Experimental)](#memory-usage---experimental)
55
- 29. [Angular Zone.js Configuration](#angular-zonejs-configuration)
56
- 30. [CDN](#cdn)
61
+ 30. [Soft Navigations (Experimental)](#soft-navigations--experimental)
62
+ 31. [Memory Usage (Experimental)](#memory-usage---experimental)
63
+ 32. [Web Worker Support](#web-worker-support)
64
+
65
+ - [Enabling Web Worker Support](#enabling-web-worker-support)
66
+ - [Examples](#examples)
67
+
68
+ 33. [Angular Zone.js Configuration](#angular-zonejs-configuration)
69
+ 34. [CDN](#cdn)
57
70
 
58
71
  - [Specific Version](#specific-version-recommended)
72
+ - [ES5](#es5)
59
73
  - [Add the CDN Script to Your Application](#add-the-cdn-script-to-your-application)
60
74
  - [Initialization](#initialization)
61
75
  - [Via JS File](#via-js-file)
62
76
  - [Via TS File](#via-ts-file)
63
77
 
64
- 31. [Flutter Web](#flutter-web)
78
+ 35. [Flutter Web](#flutter-web)
65
79
 
66
80
  ---
67
81
 
@@ -559,7 +573,7 @@ Examples of masked elements:
559
573
 
560
574
  ```
561
575
 
562
- ### Action Attributes
576
+ ### Custom Action Names
563
577
 
564
578
  The SDK uses various strategies to name click actions. For more control, define a `data-cx-action-name` attribute on clickable elements (or any of their parents) to set the action name.
565
579
 
@@ -854,6 +868,19 @@ CoralogixRum.init({
854
868
  });
855
869
  ```
856
870
 
871
+ ### SDK Fetch Priority
872
+
873
+ Controls the [`priority`](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#priority) hint applied to the SDK's own network requests — the internal calls it makes to send logs and recordings to Coralogix. This is unrelated to your application's requests. When omitted, the browser uses its default (Chromium treats this as `high`), which can cause SDK traffic to compete with your application's critical requests. Set `sdkFetchPriority: 'low'` to deprioritize SDK traffic.
874
+
875
+ Accepted values: `'low'`, `'high'`, or `'auto'` (default).
876
+
877
+ ```javascript
878
+ CoralogixRum.init({
879
+ // ...
880
+ sdkFetchPriority: 'low',
881
+ });
882
+ ```
883
+
857
884
  ### Custom Measurement
858
885
 
859
886
  Custom measurement allows you to send numeric data to Coralogix for precise monitoring and analysis.
package/index.esm2.js CHANGED
@@ -227,6 +227,7 @@ var SESSION_EXPIRATION_TIME = MILLISECONDS_PER_HOUR;
227
227
  var SESSION_MANAGER_KEY = 'rumSessionManager';
228
228
  var SESSION_RECORDER_KEY = 'rumSessionRecorder';
229
229
  var SESSION_RECORDER_SEGMENTS_MAP = 'rumSessionRecorderSegmentsMap';
230
+ var VIEW_NUMBER_KEY = 'rum_view_number';
230
231
 
231
232
  var SNAPSHOT_MANAGER_KEY = 'rumSnapshotManager';
232
233
  var INITIAL_SNAPSHOT_CONTEXT = {
@@ -264,6 +265,8 @@ function getCxGlobal() {
264
265
  }
265
266
  var CxGlobal = getCxGlobal();
266
267
 
268
+ var CLICK_SCREENSHOT_MANAGER_KEY = 'rumClickScreenshotManager';
269
+
267
270
  function getSnapshotManager() {
268
271
  return CxGlobal[SNAPSHOT_MANAGER_KEY];
269
272
  }
@@ -273,12 +276,28 @@ function getSessionManager() {
273
276
  function getSessionRecorder() {
274
277
  return CxGlobal[SESSION_RECORDER_KEY];
275
278
  }
279
+ function getClickScreenshotManager() {
280
+ return CxGlobal[CLICK_SCREENSHOT_MANAGER_KEY];
281
+ }
276
282
  function getSdkConfig() {
277
283
  return CxGlobal[SDK_CONFIG_KEY];
278
284
  }
279
285
  function getUserAgentData() {
280
286
  return CxGlobal[USER_AGENT_KEY];
281
287
  }
288
+ var TRACER_PROVIDER_KEY = '__cx_tracer_provider__';
289
+ function setTracerProvider(provider) {
290
+ CxGlobal[TRACER_PROVIDER_KEY] = provider;
291
+ }
292
+ function getTracerProvider() {
293
+ return CxGlobal[TRACER_PROVIDER_KEY];
294
+ }
295
+ function flush() {
296
+ var tracerProvider = getTracerProvider();
297
+ if (!tracerProvider)
298
+ return;
299
+ tracerProvider.forceFlush();
300
+ }
282
301
 
283
302
  var GLOBAL_SPAN_KEY = '__globalSpan__';
284
303
  var GLOBAL_SPAN_MAP_KEY = '__globalSpanMap__';
@@ -2122,8 +2141,13 @@ function addEventListeners(eventTarget, eventNames, listener, _a) {
2122
2141
  };
2123
2142
  }
2124
2143
 
2144
+ var CX_ACTION_NAME_ATTRIBUTE = 'data-cx-action-name';
2145
+ var DATA_TEST_ATTRIBUTE = 'data-test';
2146
+ var DATA_TESTID_ATTRIBUTE = 'data-testid';
2147
+ var DATA_TEST_ID_ATTRIBUTE = 'data-test-id';
2148
+
2125
2149
  var PARENT_SEARCH_DEPTH = 5;
2126
- var CLICKABLE_ELEMENTS = ['BUTTON', 'LABEL', 'A', 'INPUT', 'OPTION'];
2150
+ var CLICKABLE_ELEMENTS = ['BUTTON', 'LABEL', 'A', 'INPUT', 'OPTION', 'LI'];
2127
2151
  function getAttributeFromAncestors(element, attr, depth) {
2128
2152
  if (depth === void 0) { depth = PARENT_SEARCH_DEPTH; }
2129
2153
  if (!element || depth <= 0)
@@ -2159,7 +2183,12 @@ function getPlaceholder(element) {
2159
2183
  return '';
2160
2184
  }
2161
2185
  function getInnerText(element) {
2162
- return element instanceof HTMLElement ? element.innerText || '' : '';
2186
+ var clickableElement = findClickableElement(element, PARENT_SEARCH_DEPTH);
2187
+ if (!clickableElement)
2188
+ return '';
2189
+ return clickableElement instanceof HTMLElement
2190
+ ? clickableElement.innerText || ''
2191
+ : '';
2163
2192
  }
2164
2193
  function extractMaskedOrTextContent(element, config) {
2165
2194
  if (!element)
@@ -2238,6 +2267,177 @@ function findClickableElement(element, maxDepth) {
2238
2267
  return findClickableElement(element.parentElement, maxDepth - 1);
2239
2268
  }
2240
2269
 
2270
+ var SHADOW_DOM_MARKER = '::shadow ';
2271
+ var STABLE_ATTRIBUTES = [
2272
+ CX_ACTION_NAME_ATTRIBUTE,
2273
+ DATA_TEST_ATTRIBUTE,
2274
+ DATA_TESTID_ATTRIBUTE,
2275
+ DATA_TEST_ID_ATTRIBUTE,
2276
+ ];
2277
+ var ESCAPE_FREE_CLASS_NAME = /^[a-zA-Z_-][a-zA-Z0-9_-]*$/;
2278
+ var GENERATED_VALUE_PATTERNS = [
2279
+ /^\d/,
2280
+ /\d{3,}/,
2281
+ /__[a-zA-Z0-9]/,
2282
+ /(?:[a-z]\d|\d[a-z]){3,}/i,
2283
+ ];
2284
+ function getElementFingerprint(target) {
2285
+ try {
2286
+ if (!target.isConnected) {
2287
+ return undefined;
2288
+ }
2289
+ var selectors = [];
2290
+ var element = target;
2291
+ while (element) {
2292
+ var root = element.getRootNode();
2293
+ var selector = getSubtreeSelector(element, root);
2294
+ if (!selector) {
2295
+ return undefined;
2296
+ }
2297
+ selectors.unshift(selector);
2298
+ element = isShadowRoot(root) ? root.host : null;
2299
+ }
2300
+ return selectors.join(SHADOW_DOM_MARKER);
2301
+ }
2302
+ catch (_a) {
2303
+ return undefined;
2304
+ }
2305
+ }
2306
+ function isShadowRoot(node) {
2307
+ return (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !!node.host);
2308
+ }
2309
+ function getSubtreeSelector(target, root) {
2310
+ var selector = '';
2311
+ for (var element = target; element && element.nodeName !== 'HTML'; element = element.parentElement) {
2312
+ var unique = getUniqueSegment(element, root, selector);
2313
+ if (unique) {
2314
+ return joinWithChild(unique, selector);
2315
+ }
2316
+ selector = joinWithChild(getLevelSegment(element, selector), selector);
2317
+ }
2318
+ return selector;
2319
+ }
2320
+ function getUniqueSegment(element, root, childSelector) {
2321
+ var e_1, _a;
2322
+ try {
2323
+ for (var _b = __values$1([getAttributeSegment(element), getIdSegment(element)]), _c = _b.next(); !_c.done; _c = _b.next()) {
2324
+ var segment = _c.value;
2325
+ if (segment && isUnique(root, joinWithChild(segment, childSelector))) {
2326
+ return segment;
2327
+ }
2328
+ }
2329
+ }
2330
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2331
+ finally {
2332
+ try {
2333
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2334
+ }
2335
+ finally { if (e_1) throw e_1.error; }
2336
+ }
2337
+ return undefined;
2338
+ }
2339
+ function getLevelSegment(element, childSelector) {
2340
+ var e_2, _a;
2341
+ var candidates = [
2342
+ getAttributeSegment(element),
2343
+ getStableClassSegment(element),
2344
+ element.tagName,
2345
+ ];
2346
+ try {
2347
+ for (var candidates_1 = __values$1(candidates), candidates_1_1 = candidates_1.next(); !candidates_1_1.done; candidates_1_1 = candidates_1.next()) {
2348
+ var segment = candidates_1_1.value;
2349
+ if (segment && isUniqueAmongSiblings(element, segment, childSelector)) {
2350
+ return segment;
2351
+ }
2352
+ }
2353
+ }
2354
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2355
+ finally {
2356
+ try {
2357
+ if (candidates_1_1 && !candidates_1_1.done && (_a = candidates_1.return)) _a.call(candidates_1);
2358
+ }
2359
+ finally { if (e_2) throw e_2.error; }
2360
+ }
2361
+ return "".concat(element.tagName, ":nth-of-type(").concat(nthOfTypeIndex(element), ")");
2362
+ }
2363
+ function getAttributeSegment(element) {
2364
+ var e_3, _a;
2365
+ try {
2366
+ for (var STABLE_ATTRIBUTES_1 = __values$1(STABLE_ATTRIBUTES), STABLE_ATTRIBUTES_1_1 = STABLE_ATTRIBUTES_1.next(); !STABLE_ATTRIBUTES_1_1.done; STABLE_ATTRIBUTES_1_1 = STABLE_ATTRIBUTES_1.next()) {
2367
+ var attribute = STABLE_ATTRIBUTES_1_1.value;
2368
+ var value = element.getAttribute(attribute);
2369
+ if (value) {
2370
+ return "".concat(element.tagName, "[").concat(attribute, "=\"").concat(CSS.escape(value), "\"]");
2371
+ }
2372
+ }
2373
+ }
2374
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
2375
+ finally {
2376
+ try {
2377
+ if (STABLE_ATTRIBUTES_1_1 && !STABLE_ATTRIBUTES_1_1.done && (_a = STABLE_ATTRIBUTES_1.return)) _a.call(STABLE_ATTRIBUTES_1);
2378
+ }
2379
+ finally { if (e_3) throw e_3.error; }
2380
+ }
2381
+ return undefined;
2382
+ }
2383
+ function getIdSegment(element) {
2384
+ return element.id && !isUnstableValue(element.id)
2385
+ ? "#".concat(CSS.escape(element.id))
2386
+ : undefined;
2387
+ }
2388
+ function getStableClassSegment(element) {
2389
+ var _a, _b;
2390
+ if (element.tagName === 'BODY') {
2391
+ return undefined;
2392
+ }
2393
+ var classNames = (_b = (_a = element.getAttribute('class')) === null || _a === void 0 ? void 0 : _a.split(/\s+/)) !== null && _b !== void 0 ? _b : [];
2394
+ var stable = classNames.find(function (name) { return name && !isUnstableValue(name) && ESCAPE_FREE_CLASS_NAME.test(name); });
2395
+ return stable ? "".concat(element.tagName, ".").concat(stable) : undefined;
2396
+ }
2397
+ function isUnstableValue(value) {
2398
+ return GENERATED_VALUE_PATTERNS.some(function (pattern) { return pattern.test(value); });
2399
+ }
2400
+ function isUnique(root, selector) {
2401
+ return root.querySelectorAll(selector).length === 1;
2402
+ }
2403
+ function isUniqueAmongSiblings(element, segment, childSelector) {
2404
+ var e_4, _a;
2405
+ var _b, _c;
2406
+ var siblings = (_c = (_b = element.parentElement) === null || _b === void 0 ? void 0 : _b.children) !== null && _c !== void 0 ? _c : [];
2407
+ try {
2408
+ for (var siblings_1 = __values$1(siblings), siblings_1_1 = siblings_1.next(); !siblings_1_1.done; siblings_1_1 = siblings_1.next()) {
2409
+ var sibling = siblings_1_1.value;
2410
+ if (sibling === element) {
2411
+ continue;
2412
+ }
2413
+ if (sibling.matches(segment) &&
2414
+ (!childSelector || sibling.querySelector(childSelector) !== null)) {
2415
+ return false;
2416
+ }
2417
+ }
2418
+ }
2419
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
2420
+ finally {
2421
+ try {
2422
+ if (siblings_1_1 && !siblings_1_1.done && (_a = siblings_1.return)) _a.call(siblings_1);
2423
+ }
2424
+ finally { if (e_4) throw e_4.error; }
2425
+ }
2426
+ return true;
2427
+ }
2428
+ function nthOfTypeIndex(element) {
2429
+ var index = 1;
2430
+ for (var s = element.previousElementSibling; s; s = s.previousElementSibling) {
2431
+ if (s.tagName === element.tagName) {
2432
+ index += 1;
2433
+ }
2434
+ }
2435
+ return index;
2436
+ }
2437
+ function joinWithChild(parent, child) {
2438
+ return child ? "".concat(parent, ">").concat(child) : parent;
2439
+ }
2440
+
2241
2441
  var _a$3;
2242
2442
  var USER_INTERACTION_INSTRUMENTATION_NAME = 'interactions';
2243
2443
  var USER_INTERACTION_INSTRUMENTATION_VERSION = '1';
@@ -2256,6 +2456,7 @@ var CoralogixUserInteractionInstrumentation = (function (_super) {
2256
2456
  var _this = this;
2257
2457
  var _a;
2258
2458
  this.handler = function (e) {
2459
+ var _a;
2259
2460
  var span;
2260
2461
  if (shouldAttachSpanToGlobalSpan(CoralogixEventType.USER_INTERACTION)) {
2261
2462
  span = attachChildSpanToGlobalSpan(CoralogixEventType.USER_INTERACTION);
@@ -2266,8 +2467,16 @@ var CoralogixUserInteractionInstrumentation = (function (_super) {
2266
2467
  var eventTarget = e.target;
2267
2468
  var config = getSdkConfig();
2268
2469
  var id = eventTarget.id, type = eventTarget.type, className = eventTarget.className, nodeName = eventTarget.nodeName;
2470
+ var clickKey = generateUUID();
2269
2471
  span.setAttribute(CoralogixAttributes.EVENT_TYPE, CoralogixEventType.USER_INTERACTION);
2270
2472
  span.setAttribute(CoralogixAttributes.INTERACTION_EVENT_NAME, e.type);
2473
+ span.setAttribute(CoralogixAttributes.CX_ID, clickKey);
2474
+ if (e instanceof MouseEvent) {
2475
+ span.setAttribute(CoralogixAttributes.CLICK_X, e.clientX);
2476
+ span.setAttribute(CoralogixAttributes.CLICK_Y, e.clientY);
2477
+ span.setAttribute(CoralogixAttributes.ELEMENT_RELATIVE_X, e.offsetX);
2478
+ span.setAttribute(CoralogixAttributes.ELEMENT_RELATIVE_Y, e.offsetY);
2479
+ }
2271
2480
  if (eventTarget && eventTarget instanceof HTMLElement) {
2272
2481
  var elementText = extractMaskedOrTextContent(eventTarget, config);
2273
2482
  var cxActionName = extractActionName(eventTarget);
@@ -2279,6 +2488,13 @@ var CoralogixUserInteractionInstrumentation = (function (_super) {
2279
2488
  actionName: cxActionName,
2280
2489
  ariaLabel: ariaLabel,
2281
2490
  });
2491
+ var _b = eventTarget.getBoundingClientRect(), width = _b.width, height = _b.height;
2492
+ span.setAttribute(CoralogixAttributes.ELEMENT_WIDTH, width);
2493
+ span.setAttribute(CoralogixAttributes.ELEMENT_HEIGHT, height);
2494
+ var fingerprint = getElementFingerprint(eventTarget);
2495
+ if (fingerprint) {
2496
+ span.setAttribute(CoralogixAttributes.ELEMENT_FINGERPRINT, fingerprint);
2497
+ }
2282
2498
  [
2283
2499
  [CoralogixAttributes.ELEMENT_ID, id],
2284
2500
  [CoralogixAttributes.ELEMENT_CLASSES, className],
@@ -2301,6 +2517,7 @@ var CoralogixUserInteractionInstrumentation = (function (_super) {
2301
2517
  });
2302
2518
  }
2303
2519
  span.end();
2520
+ (_a = getClickScreenshotManager()) === null || _a === void 0 ? void 0 : _a.handleClick();
2304
2521
  };
2305
2522
  var eventsMap = __assign(__assign({}, DEFAULT_INSTRUMENTED_EVENTS), (_a = this._config) === null || _a === void 0 ? void 0 : _a['events']);
2306
2523
  var eventNames = Object.entries(eventsMap)
@@ -2598,13 +2815,20 @@ var CoralogixDOMInstrumentation = (function (_super) {
2598
2815
  var _this = _super.call(this, DOM_INSTRUMENTATION_NAME, DOM_INSTRUMENTATION_VERSION, config) || this;
2599
2816
  _this.visibilityChangeHandler = function () {
2600
2817
  if (document.hidden) {
2601
- var domSpan = _this.tracer.startSpan(DOM_INSTRUMENTATION_NAME);
2602
- domSpan.setAttribute(CoralogixAttributes.EVENT_TYPE, CoralogixEventType.DOM);
2603
- domSpan.end();
2818
+ _this.createDOMSpan();
2819
+ flush();
2604
2820
  }
2605
2821
  };
2606
2822
  return _this;
2607
2823
  }
2824
+ CoralogixDOMInstrumentation.prototype.createDOMSpan = function () {
2825
+ var domSpan = this.tracer.startSpan(DOM_INSTRUMENTATION_NAME);
2826
+ domSpan.setAttribute(CoralogixAttributes.EVENT_TYPE, CoralogixEventType.DOM);
2827
+ domSpan[CoralogixAttributes.DOM_CONTEXT] = {
2828
+ visibility_state: document.visibilityState,
2829
+ };
2830
+ domSpan.end();
2831
+ };
2608
2832
  CoralogixDOMInstrumentation.prototype.registerToDOMEvents = function () {
2609
2833
  var originalAddEventListener = getZoneJsOriginalDom(document, 'addEventListener');
2610
2834
  originalAddEventListener.call(document, 'visibilitychange', this.visibilityChangeHandler);
@@ -2713,9 +2937,8 @@ var NETWORK_URL_LABEL_PROVIDERS_KEY = 'NETWORK_URL_LABEL_PROVIDERS';
2713
2937
  var RUM_INTERNAL_DATA_KEY = 'rumInternalData';
2714
2938
  var MASKED_TEXT = '***';
2715
2939
  var MASK_CLASS_DEFAULT = 'cx-mask';
2716
- var CX_ACTION_NAME_ATTRIBUTE = 'data-cx-action-name';
2940
+ var CX_PREFIX = 'cx';
2717
2941
  var ARIA_LABEL_ATTRIBUTE = 'aria-label';
2718
- var DATA_TEST_ATTRIBUTE = 'data-test';
2719
2942
  var MASK_INPUT_TYPES_DEFAULT = [
2720
2943
  'password',
2721
2944
  'email',
@@ -2857,14 +3080,23 @@ var CoralogixAttributes = {
2857
3080
  TARGET_ELEMENT: 'target_element',
2858
3081
  TARGET_ELEMENT_TYPE: 'target_element_type',
2859
3082
  CX_ACTION_NAME: 'cx_action_name',
3083
+ CX_ID: 'cx_id',
2860
3084
  ARIA_LABEL: 'element_aria_label',
2861
3085
  TEST_ID: 'element_test_id',
2862
3086
  RESOLVED_NAME: 'element_resolved_name',
3087
+ CLICK_X: 'click_x',
3088
+ CLICK_Y: 'click_y',
3089
+ ELEMENT_RELATIVE_X: 'element_relative_x',
3090
+ ELEMENT_RELATIVE_Y: 'element_relative_y',
3091
+ ELEMENT_WIDTH: 'element_width',
3092
+ ELEMENT_HEIGHT: 'element_height',
3093
+ ELEMENT_FINGERPRINT: 'element_fingerprint',
2863
3094
  TIMESTAMP: 'timestamp',
2864
3095
  INTERNAL: 'internal',
2865
3096
  PAGE_CONTEXT: 'page_context',
2866
3097
  IS_NAVIGATION_EVENT: 'is_navigation_event',
2867
3098
  SCREENSHOT_CONTEXT: 'screenshot_context',
3099
+ DOM_CONTEXT: 'dom_context',
2868
3100
  };
2869
3101
  var CoralogixDomainsApiUrlMap = {
2870
3102
  EU1: 'https://ingress.eu1.rum-ingress-coralogix.com',
@@ -3520,11 +3752,14 @@ var DEFAULT_MS_RECORD_TIME = 10000;
3520
3752
  _a$1),
3521
3753
  });
3522
3754
 
3755
+ var KEEPALIVE_MAX_BYTES = 65536;
3756
+ var encoder = new TextEncoder();
3523
3757
  var Request = (function () {
3524
3758
  function Request(requestConfig) {
3525
3759
  this.requestConfig = requestConfig;
3526
3760
  this.resolvedUrl = '';
3527
3761
  this.resolvedHeaders = {};
3762
+ this.fetchPriority = 'auto';
3528
3763
  this.init();
3529
3764
  }
3530
3765
  Request.prototype.getResolvedUrl = function (config) {
@@ -3537,7 +3772,7 @@ var Request = (function () {
3537
3772
  return "".concat(proxyUrl, "?").concat(PROXY_CX_FORWARD_PARAMETER, "=").concat(encodeURIComponent(cxEndpoint));
3538
3773
  };
3539
3774
  Request.prototype.init = function () {
3540
- var _a = getSdkConfig(), proxyUrl = _a.proxyUrl, ignoreProxyUrlParams = _a.ignoreProxyUrlParams, coralogixDomain = _a.coralogixDomain, public_key = _a.public_key;
3775
+ var _a = getSdkConfig(), proxyUrl = _a.proxyUrl, ignoreProxyUrlParams = _a.ignoreProxyUrlParams, coralogixDomain = _a.coralogixDomain, public_key = _a.public_key, sdkFetchPriority = _a.sdkFetchPriority;
3541
3776
  var headers = this.requestConfig.headers;
3542
3777
  this.resolvedUrl = this.getResolvedUrl({
3543
3778
  proxyUrl: proxyUrl,
@@ -3548,16 +3783,25 @@ var Request = (function () {
3548
3783
  headers['Authorization'] = "Bearer ".concat(public_key);
3549
3784
  }
3550
3785
  this.resolvedHeaders = headers;
3786
+ if (sdkFetchPriority) {
3787
+ this.fetchPriority = sdkFetchPriority;
3788
+ }
3551
3789
  };
3552
3790
  Request.prototype.send = function (body) {
3791
+ var useKeepalive = document.hidden && this.isWithinKeepaliveQuota(body);
3553
3792
  return fetch(this.resolvedUrl, {
3554
3793
  method: 'POST',
3555
3794
  headers: this.resolvedHeaders,
3556
3795
  body: body,
3796
+ keepalive: useKeepalive,
3797
+ priority: this.fetchPriority,
3557
3798
  }).catch(function (e) {
3558
3799
  return e;
3559
3800
  });
3560
3801
  };
3802
+ Request.prototype.isWithinKeepaliveQuota = function (body) {
3803
+ return typeof body === 'string' && encoder.encode(body).length <= KEEPALIVE_MAX_BYTES;
3804
+ };
3561
3805
  return Request;
3562
3806
  }());
3563
3807
 
@@ -4033,7 +4277,7 @@ function isInstrumentationCompatible(confKey) {
4033
4277
  var SessionManager = (function (_super) {
4034
4278
  __extends(SessionManager, _super);
4035
4279
  function SessionManager(recordConfig) {
4036
- var _a;
4280
+ var _a, _b;
4037
4281
  var _this = _super.call(this, {
4038
4282
  timeoutDelay: SESSION_IDLE_TIME,
4039
4283
  onIdle: function () { return _this.clearSessionWhenIdle(); },
@@ -4043,6 +4287,7 @@ var SessionManager = (function (_super) {
4043
4287
  _this._sessionHasError = false;
4044
4288
  _this._cachedLogsSent = false;
4045
4289
  _this._currentPageTimestamp = getNowTime();
4290
+ _this._viewNumber = 0;
4046
4291
  _this.debugMode = !!((_a = getSdkConfig()) === null || _a === void 0 ? void 0 : _a.debug);
4047
4292
  _this.getPrevSession = function () {
4048
4293
  var _a;
@@ -4086,6 +4331,9 @@ var SessionManager = (function (_super) {
4086
4331
  return _this.activeSession;
4087
4332
  };
4088
4333
  _this.initializeSession(recordConfig);
4334
+ if ((_b = _this._sessionConfig) === null || _b === void 0 ? void 0 : _b.keepSessionAfterReload) {
4335
+ _this.loadViewNumber();
4336
+ }
4089
4337
  return _this;
4090
4338
  }
4091
4339
  Object.defineProperty(SessionManager.prototype, "currentPageTimestamp", {
@@ -4164,6 +4412,13 @@ var SessionManager = (function (_super) {
4164
4412
  enumerable: false,
4165
4413
  configurable: true
4166
4414
  });
4415
+ Object.defineProperty(SessionManager.prototype, "viewNumber", {
4416
+ get: function () {
4417
+ return this._viewNumber;
4418
+ },
4419
+ enumerable: false,
4420
+ configurable: true
4421
+ });
4167
4422
  SessionManager.prototype.updateCurrentPage = function (fragment) {
4168
4423
  if (this.isIdleActive) {
4169
4424
  this._currentPageFragment = undefined;
@@ -4172,6 +4427,26 @@ var SessionManager = (function (_super) {
4172
4427
  this._currentPageFragment = fragment;
4173
4428
  this._currentPageTimestamp = getNowTime();
4174
4429
  };
4430
+ SessionManager.prototype.incrementViewNumber = function () {
4431
+ this._viewNumber++;
4432
+ this.persistViewNumber();
4433
+ };
4434
+ SessionManager.prototype.persistViewNumber = function () {
4435
+ var _a, _b;
4436
+ if ((_a = this._sessionConfig) === null || _a === void 0 ? void 0 : _a.keepSessionAfterReload) {
4437
+ (_b = CxGlobal.sessionStorage) === null || _b === void 0 ? void 0 : _b.setItem(VIEW_NUMBER_KEY, String(this._viewNumber));
4438
+ }
4439
+ };
4440
+ SessionManager.prototype.loadViewNumber = function () {
4441
+ var _a;
4442
+ var storedViewNumber = (_a = CxGlobal.sessionStorage) === null || _a === void 0 ? void 0 : _a.getItem(VIEW_NUMBER_KEY);
4443
+ this._viewNumber = Number(storedViewNumber) || 0;
4444
+ };
4445
+ SessionManager.prototype.resetViewNumber = function () {
4446
+ var _a;
4447
+ this._viewNumber = 0;
4448
+ (_a = CxGlobal.sessionStorage) === null || _a === void 0 ? void 0 : _a.removeItem(VIEW_NUMBER_KEY);
4449
+ };
4175
4450
  SessionManager.prototype.getSessionKey = function () {
4176
4451
  return SESSION_KEY;
4177
4452
  };
@@ -4226,7 +4501,7 @@ var SessionManager = (function (_super) {
4226
4501
  (_a = CxGlobal.sessionStorage) === null || _a === void 0 ? void 0 : _a.removeItem(PREV_SESSION_KEY);
4227
4502
  };
4228
4503
  SessionManager.prototype.clearSession = function () {
4229
- var _a, _b, _c, _d, _e, _f;
4504
+ var _a, _b, _c, _d, _e, _f, _g;
4230
4505
  if (this.debugMode) {
4231
4506
  console.debug('Coralogix Browser SDK - Session expired, clearing session');
4232
4507
  }
@@ -4234,9 +4509,11 @@ var SessionManager = (function (_super) {
4234
4509
  this.clearGlobalSpans();
4235
4510
  this.clearSessionWithErrorMode();
4236
4511
  (_d = getSnapshotManager()) === null || _d === void 0 ? void 0 : _d.resetSnapshot();
4512
+ (_e = getClickScreenshotManager()) === null || _e === void 0 ? void 0 : _e.reset();
4237
4513
  this._currentPageFragment = undefined;
4238
- (_e = this.sessionRecorder) === null || _e === void 0 ? void 0 : _e.stopRecording();
4239
- (_f = CxGlobal.sessionStorage) === null || _f === void 0 ? void 0 : _f.removeItem(SESSION_KEY);
4514
+ this.resetViewNumber();
4515
+ (_f = this.sessionRecorder) === null || _f === void 0 ? void 0 : _f.stopRecording();
4516
+ (_g = CxGlobal.sessionStorage) === null || _g === void 0 ? void 0 : _g.removeItem(SESSION_KEY);
4240
4517
  };
4241
4518
  SessionManager.prototype.clearGlobalSpans = function () {
4242
4519
  var _a;
@@ -4249,13 +4526,8 @@ var SessionManager = (function (_super) {
4249
4526
  this.cachedLogsSent = false;
4250
4527
  };
4251
4528
  SessionManager.prototype.handleRefreshedSessions = function () {
4252
- var _a, _b;
4253
4529
  this.activeSession = this.getSession();
4254
- var recordingSegmentMapFromStorage = JSON.parse(((_a = CxGlobal.sessionStorage) === null || _a === void 0 ? void 0 : _a.getItem(SESSION_RECORDER_SEGMENTS_MAP)) || '{}');
4255
- if (this.activeSession) {
4256
- (_b = getSessionRecorder()) === null || _b === void 0 ? void 0 : _b.updateSegmentIndexCounter(recordingSegmentMapFromStorage);
4257
- }
4258
- else {
4530
+ if (!this.activeSession) {
4259
4531
  this.createNewSession();
4260
4532
  }
4261
4533
  };
@@ -4440,7 +4712,7 @@ function resolveUrlBlueprinters(urlBlueprinters) {
4440
4712
  return resolvedUrlBlueprinters;
4441
4713
  }
4442
4714
 
4443
- var SDK_VERSION = '3.10.0';
4715
+ var SDK_VERSION = '3.16.0';
4444
4716
 
4445
4717
  function shouldDropEvent(cxRumEvent, options) {
4446
4718
  if (isDocumentErrorWithoutMessage(cxRumEvent)) {
@@ -4578,6 +4850,9 @@ var CoralogixSpanMapProcessor = (function () {
4578
4850
  getSessionManager().sessionHasError = true;
4579
4851
  resolvedCxSpan.text.cx_rum.session_context.hasError = true;
4580
4852
  }
4853
+ if (shouldAddOtelAttr(span)) {
4854
+ this.addOtelInstrumentationData(span, resolvedCxSpan);
4855
+ }
4581
4856
  span[CX_MAPPED_SPAN] = resolvedCxSpan;
4582
4857
  }
4583
4858
  }
@@ -4591,21 +4866,19 @@ var CoralogixSpanMapProcessor = (function () {
4591
4866
  return Promise.resolve(undefined);
4592
4867
  };
4593
4868
  CoralogixSpanMapProcessor.prototype._mapToCxSpan = function (span, session, prevSession, sessionHasRecording, sessionHasScreenshot, onlySessionWithErrorMode) {
4594
- var _a, _b;
4595
- var _c = session || {}, sessionId = _c.sessionId, sessionCreationDate = _c.sessionCreationDate;
4596
- var _d = prevSession || {}, prevSessionId = _d.sessionId, prevSessionCreationDate = _d.sessionCreationDate, prevSessionHasRecording = _d.hasRecording, prevSessionHasScreenshot = _d.hasScreenshot;
4597
- var attributes = span.attributes, startTime = span.startTime, parentSpanId = span.parentSpanId, name = span.name, endTime = span.endTime, status = span.status, duration = span.duration, kind = span.kind;
4869
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
4870
+ var _l = session || {}, sessionId = _l.sessionId, sessionCreationDate = _l.sessionCreationDate;
4871
+ var _m = prevSession || {}, prevSessionId = _m.sessionId, prevSessionCreationDate = _m.sessionCreationDate, prevSessionHasRecording = _m.hasRecording, prevSessionHasScreenshot = _m.hasScreenshot;
4872
+ var attributes = span.attributes;
4598
4873
  var user_context = JSON.parse(attributes[CoralogixAttributes.USER_CONTEXT]);
4599
4874
  var application_context = JSON.parse(attributes[CoralogixAttributes.APPLICATION_CONTEXT]);
4600
4875
  var application = application_context.application, version = application_context.version;
4601
4876
  var eventType = attributes[CoralogixAttributes.EVENT_TYPE] ||
4602
4877
  span[CoralogixAttributes.EVENT_TYPE];
4603
4878
  var eventTypeContext = this._getEventTypeContext(attributes, eventType, span);
4604
- var _e = span.spanContext(), spanId = _e.spanId, traceId = _e.traceId;
4605
- var resourceAttributes = __assign(__assign({}, (_a = span.resource) === null || _a === void 0 ? void 0 : _a.attributes), { 'service.name': application });
4606
4879
  var fingerPrint = getSessionManager().fingerPrint;
4607
4880
  var labels = JSON.parse(attributes[CoralogixAttributes.CUSTOM_LABELS]);
4608
- var isErrorWithStacktrace = !!((_b = eventTypeContext === null || eventTypeContext === void 0 ? void 0 : eventTypeContext.error_context) === null || _b === void 0 ? void 0 : _b.original_stacktrace);
4881
+ var isErrorWithStacktrace = !!((_a = eventTypeContext === null || eventTypeContext === void 0 ? void 0 : eventTypeContext.error_context) === null || _a === void 0 ? void 0 : _a.original_stacktrace);
4609
4882
  var version_metadata = {
4610
4883
  app_name: application,
4611
4884
  app_version: version,
@@ -4637,34 +4910,18 @@ var CoralogixSpanMapProcessor = (function () {
4637
4910
  type: eventType,
4638
4911
  source: attributes[CoralogixAttributes.SOURCE],
4639
4912
  severity: severity,
4640
- }, labels: labels, environment: attributes[CoralogixAttributes.ENVIRONMENT] || '' }),
4913
+ }, labels: labels, environment: attributes[CoralogixAttributes.ENVIRONMENT] || '', view_number: getSessionManager().viewNumber, layout_context: {
4914
+ viewport_width: (_b = window === null || window === void 0 ? void 0 : window.innerWidth) !== null && _b !== void 0 ? _b : 0,
4915
+ viewport_height: (_c = window === null || window === void 0 ? void 0 : window.innerHeight) !== null && _c !== void 0 ? _c : 0,
4916
+ view_width: (_e = (_d = document === null || document === void 0 ? void 0 : document.documentElement) === null || _d === void 0 ? void 0 : _d.scrollWidth) !== null && _e !== void 0 ? _e : 0,
4917
+ view_height: (_g = (_f = document === null || document === void 0 ? void 0 : document.documentElement) === null || _f === void 0 ? void 0 : _f.scrollHeight) !== null && _g !== void 0 ? _g : 0,
4918
+ device_pixel_ratio: (_h = window === null || window === void 0 ? void 0 : window.devicePixelRatio) !== null && _h !== void 0 ? _h : 1,
4919
+ scroll_x: (_j = window === null || window === void 0 ? void 0 : window.scrollX) !== null && _j !== void 0 ? _j : 0,
4920
+ scroll_y: (_k = window === null || window === void 0 ? void 0 : window.scrollY) !== null && _k !== void 0 ? _k : 0,
4921
+ } }),
4641
4922
  },
4642
4923
  };
4643
4924
  var resolvedLabels = this.resolveLabels(cxSpan.text.cx_rum);
4644
- if (shouldAddOtelAttr(span)) {
4645
- cxSpan.text.cx_rum.spanId = spanId;
4646
- cxSpan.text.cx_rum.traceId = traceId;
4647
- cxSpan.text.cx_rum.parentSpanId = parentSpanId;
4648
- cxSpan.instrumentation_data = {
4649
- otelSpan: {
4650
- spanId: spanId,
4651
- traceId: traceId,
4652
- parentSpanId: parentSpanId,
4653
- startTime: startTime,
4654
- endTime: endTime,
4655
- status: severity === CoralogixLogSeverity.Error
4656
- ? __assign(__assign({}, status), { code: SpanStatusCode.ERROR }) : status,
4657
- kind: kind,
4658
- duration: duration,
4659
- sessionId: sessionId,
4660
- name: name,
4661
- attributes: buildRumContextAttributes(cxSpan.text.cx_rum, resolvedLabels),
4662
- },
4663
- otelResource: {
4664
- attributes: resourceAttributes,
4665
- },
4666
- };
4667
- }
4668
4925
  this.resolveContextFromSpan(cxSpan, span, eventType);
4669
4926
  cxSpan.text.cx_rum.labels = resolvedLabels;
4670
4927
  return cxSpan;
@@ -4686,8 +4943,42 @@ var CoralogixSpanMapProcessor = (function () {
4686
4943
  span[CoralogixAttributes.SCREENSHOT_CONTEXT];
4687
4944
  break;
4688
4945
  }
4946
+ case CoralogixEventType.DOM: {
4947
+ cxSpan.text.cx_rum.dom_context = span[CoralogixAttributes.DOM_CONTEXT];
4948
+ break;
4949
+ }
4689
4950
  }
4690
4951
  };
4952
+ CoralogixSpanMapProcessor.prototype.addOtelInstrumentationData = function (span, cxSpan) {
4953
+ var _a;
4954
+ var _b = span.spanContext(), spanId = _b.spanId, traceId = _b.traceId;
4955
+ var parentSpanId = span.parentSpanId, startTime = span.startTime, endTime = span.endTime, status = span.status, kind = span.kind, duration = span.duration, name = span.name;
4956
+ var cxRum = cxSpan.text.cx_rum;
4957
+ var sessionId = cxRum.session_context.session_id;
4958
+ cxRum.spanId = spanId;
4959
+ cxRum.traceId = traceId;
4960
+ cxRum.parentSpanId = parentSpanId;
4961
+ var resourceAttributes = __assign(__assign({}, (_a = span.resource) === null || _a === void 0 ? void 0 : _a.attributes), { 'service.name': cxSpan.applicationName });
4962
+ cxSpan.instrumentation_data = {
4963
+ otelSpan: {
4964
+ spanId: spanId,
4965
+ traceId: traceId,
4966
+ parentSpanId: parentSpanId,
4967
+ startTime: startTime,
4968
+ endTime: endTime,
4969
+ status: cxSpan.severity === CoralogixLogSeverity.Error
4970
+ ? __assign(__assign({}, status), { code: SpanStatusCode.ERROR }) : status,
4971
+ kind: kind,
4972
+ duration: duration,
4973
+ sessionId: sessionId,
4974
+ name: name,
4975
+ attributes: buildRumContextAttributes(cxRum, cxRum.labels),
4976
+ },
4977
+ otelResource: {
4978
+ attributes: resourceAttributes,
4979
+ },
4980
+ };
4981
+ };
4691
4982
  CoralogixSpanMapProcessor.prototype._getEventTypeContext = function (spanAttributes, eventType, span) {
4692
4983
  var _a;
4693
4984
  switch (eventType) {
@@ -4761,6 +5052,7 @@ var CoralogixSpanMapProcessor = (function () {
4761
5052
  interaction_context: {
4762
5053
  target_element: spanAttributes[CoralogixAttributes.TARGET_ELEMENT],
4763
5054
  event_name: spanAttributes[CoralogixAttributes.INTERACTION_EVENT_NAME],
5055
+ cx_id: spanAttributes[CoralogixAttributes.CX_ID],
4764
5056
  target_element_inner_text: spanAttributes[CoralogixAttributes.ELEMENT_INNER_TEXT],
4765
5057
  element_id: spanAttributes[CoralogixAttributes.ELEMENT_ID],
4766
5058
  element_classes: spanAttributes[CoralogixAttributes.ELEMENT_CLASSES],
@@ -4769,6 +5061,13 @@ var CoralogixSpanMapProcessor = (function () {
4769
5061
  cx_action_name: spanAttributes[CoralogixAttributes.CX_ACTION_NAME],
4770
5062
  element_aria_label: spanAttributes[CoralogixAttributes.ARIA_LABEL],
4771
5063
  element_test_id: spanAttributes[CoralogixAttributes.TEST_ID],
5064
+ click_x: spanAttributes[CoralogixAttributes.CLICK_X],
5065
+ click_y: spanAttributes[CoralogixAttributes.CLICK_Y],
5066
+ element_relative_x: spanAttributes[CoralogixAttributes.ELEMENT_RELATIVE_X],
5067
+ element_relative_y: spanAttributes[CoralogixAttributes.ELEMENT_RELATIVE_Y],
5068
+ element_width: spanAttributes[CoralogixAttributes.ELEMENT_WIDTH],
5069
+ element_height: spanAttributes[CoralogixAttributes.ELEMENT_HEIGHT],
5070
+ element_fingerprint: spanAttributes[CoralogixAttributes.ELEMENT_FINGERPRINT],
4772
5071
  },
4773
5072
  };
4774
5073
  }
@@ -4976,6 +5275,7 @@ var CoralogixNavigationProcessor = (function () {
4976
5275
  };
4977
5276
  CoralogixNavigationProcessor.prototype.onEnd = function (span) { };
4978
5277
  CoralogixNavigationProcessor.prototype.onStart = function (span) {
5278
+ var _a;
4979
5279
  if (this.isResolving) {
4980
5280
  return;
4981
5281
  }
@@ -4989,6 +5289,8 @@ var CoralogixNavigationProcessor = (function () {
4989
5289
  if (currentPageFragment !== page_fragments) {
4990
5290
  getSessionManager().updateCurrentPage(page_fragments);
4991
5291
  span[CoralogixAttributes.IS_NAVIGATION_EVENT] = true;
5292
+ this.handlePageNavigation(currentPageFragment);
5293
+ (_a = getClickScreenshotManager()) === null || _a === void 0 ? void 0 : _a.onNavigation();
4992
5294
  }
4993
5295
  }
4994
5296
  }
@@ -4996,6 +5298,11 @@ var CoralogixNavigationProcessor = (function () {
4996
5298
  this.isResolving = false;
4997
5299
  }
4998
5300
  };
5301
+ CoralogixNavigationProcessor.prototype.handlePageNavigation = function (currentPageFragment) {
5302
+ if (currentPageFragment) {
5303
+ getSessionManager().incrementViewNumber();
5304
+ }
5305
+ };
4999
5306
  CoralogixNavigationProcessor.prototype.shutdown = function () {
5000
5307
  return Promise.resolve();
5001
5308
  };
@@ -5009,6 +5316,42 @@ function getTiming(duration) {
5009
5316
  return getNowTime() - getSessionManager().currentPageTimestamp;
5010
5317
  }
5011
5318
 
5319
+ var FIRST_CAPTURE_CLICK = 1;
5320
+ var MIN_SECOND_CAPTURE_CLICK = 2;
5321
+ var TOTAL_CAPTURE_OPTIONS = 9;
5322
+ function sampleSecondCaptureClick() {
5323
+ return (MIN_SECOND_CAPTURE_CLICK + Math.floor(Math.random() * TOTAL_CAPTURE_OPTIONS));
5324
+ }
5325
+ var ClickScreenshotManager = (function () {
5326
+ function ClickScreenshotManager() {
5327
+ var _this = this;
5328
+ this.secondCaptureClick = sampleSecondCaptureClick();
5329
+ this.clickCount = 0;
5330
+ this.reset = function () {
5331
+ _this.secondCaptureClick = sampleSecondCaptureClick();
5332
+ _this.clickCount = 0;
5333
+ };
5334
+ this.onNavigation = function () {
5335
+ _this.clickCount = 0;
5336
+ };
5337
+ this.handleClick = function () {
5338
+ if (!getSessionRecorder()) {
5339
+ return;
5340
+ }
5341
+ _this.clickCount += 1;
5342
+ if (_this.clickCount === FIRST_CAPTURE_CLICK ||
5343
+ _this.clickCount === _this.secondCaptureClick) {
5344
+ CoralogixRum.screenshot(CX_PREFIX);
5345
+ }
5346
+ };
5347
+ CxGlobal[CLICK_SCREENSHOT_MANAGER_KEY] = this;
5348
+ }
5349
+ ClickScreenshotManager.unregister = function () {
5350
+ CxGlobal[CLICK_SCREENSHOT_MANAGER_KEY] = undefined;
5351
+ };
5352
+ return ClickScreenshotManager;
5353
+ }());
5354
+
5012
5355
  if (supportedPerformanceTypes === null || supportedPerformanceTypes === void 0 ? void 0 : supportedPerformanceTypes.has(PerformanceTypes.LongTask)) {
5013
5356
  var ttiHandler_1 = (CxGlobal.__tti = {
5014
5357
  e: [],
@@ -5039,6 +5382,7 @@ var CoralogixRum = {
5039
5382
  init: function (options) {
5040
5383
  var _a, _b;
5041
5384
  var _this = this;
5385
+ var _c;
5042
5386
  try {
5043
5387
  if (isInited) {
5044
5388
  if (options === null || options === void 0 ? void 0 : options.debug) {
@@ -5070,6 +5414,7 @@ var CoralogixRum = {
5070
5414
  tracerProvider = new CoralogixWebTracerProvider({
5071
5415
  sampler: sampler,
5072
5416
  });
5417
+ setTracerProvider(tracerProvider);
5073
5418
  var pluginDefaults_1 = {};
5074
5419
  var instrumentations = INSTRUMENTATIONS.map(function (_a) {
5075
5420
  var _b, _c;
@@ -5155,6 +5500,9 @@ var CoralogixRum = {
5155
5500
  spanMapProcessor = new CoralogixSpanMapProcessor();
5156
5501
  tracerProvider.addSpanProcessor(spanMapProcessor);
5157
5502
  new SnapshotManager();
5503
+ if ((_c = resolvedOptions_1.sessionRecordingConfig) === null || _c === void 0 ? void 0 : _c.enable) {
5504
+ new ClickScreenshotManager();
5505
+ }
5158
5506
  snapshotProcessor = new CoralogixSnapshotSpanProcessor();
5159
5507
  tracerProvider.addSpanProcessor(snapshotProcessor);
5160
5508
  tracerProvider.addSpanProcessor(new BatchSpanProcessor((exporter = new CoralogixExporter()), {
@@ -5166,10 +5514,10 @@ var CoralogixRum = {
5166
5514
  tracerProvider: tracerProvider,
5167
5515
  instrumentations: instrumentations,
5168
5516
  });
5169
- var _c = __read$1(partition(resolvedOptions_1.labelProviders || [], function (_a) {
5517
+ var _d = __read$1(partition(resolvedOptions_1.labelProviders || [], function (_a) {
5170
5518
  var urlType = _a.urlType;
5171
5519
  return urlType === UrlType.PAGE || !urlType;
5172
- }), 2), pageUrlLabelProviders = _c[0], networkUrlLabelProviders = _c[1];
5520
+ }), 2), pageUrlLabelProviders = _d[0], networkUrlLabelProviders = _d[1];
5173
5521
  saveInternalRumData(PAGE_URL_LABEL_PROVIDERS_KEY, pageUrlLabelProviders);
5174
5522
  saveInternalRumData(NETWORK_URL_LABEL_PROVIDERS_KEY, networkUrlLabelProviders);
5175
5523
  isInited = true;
@@ -5255,6 +5603,7 @@ var CoralogixRum = {
5255
5603
  _deregisterInstrumentations = undefined;
5256
5604
  this.stopSessionRecording();
5257
5605
  (_a = getSessionManager()) === null || _a === void 0 ? void 0 : _a.stop();
5606
+ ClickScreenshotManager.unregister();
5258
5607
  attributesProcessor === null || attributesProcessor === void 0 ? void 0 : attributesProcessor.shutdown();
5259
5608
  navigationProcessor === null || navigationProcessor === void 0 ? void 0 : navigationProcessor.shutdown();
5260
5609
  spanMapProcessor === null || spanMapProcessor === void 0 ? void 0 : spanMapProcessor.shutdown();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coralogix/browser",
3
- "version": "3.10.0",
3
+ "version": "3.16.0",
4
4
  "description": "Official Coralogix SDK for browsers",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Coralogix",
@@ -1,5 +1,5 @@
1
1
  import { __values, __spreadArray, __read, __assign, __awaiter, __generator, __rest } from 'tslib';
2
- import { c as cxSetTimeout, a as cxClearTimeout, g as getZoneJsOriginalDom, b as createCxMutationObserver, d as cxRequestAnimationFrame, e as cxCancelAnimationFrame, C as CxGlobal, f as getSdkConfig, h as cxClearInterval, S as SESSION_RECORDER_SEGMENTS_MAP, i as getNowTime, j as SESSION_RECORDING_NETWORK_ERR0R_MESSAGE, k as cxSetInterval, R as Request, l as SESSION_RECORDING_DEFAULT_HEADERS, m as SESSION_RECORDING_POSTFIX_URL, B as BATCH_TIME_DELAY, n as SESSION_RECORDER_KEY, o as SESSION_RECORDING_DEFAULT_ERROR_MESSAGE, M as MAX_BATCH_TIME_MS } from './index.esm2.js';
2
+ import { c as cxSetTimeout, a as cxClearTimeout, g as getZoneJsOriginalDom, b as createCxMutationObserver, d as cxRequestAnimationFrame, e as cxCancelAnimationFrame, C as CxGlobal, S as SESSION_RECORDER_SEGMENTS_MAP, f as getSdkConfig, h as cxClearInterval, i as getNowTime, j as SESSION_RECORDING_NETWORK_ERR0R_MESSAGE, k as cxSetInterval, R as Request, l as SESSION_RECORDING_DEFAULT_HEADERS, m as SESSION_RECORDING_POSTFIX_URL, B as BATCH_TIME_DELAY, n as SESSION_RECORDER_KEY, o as SESSION_RECORDING_DEFAULT_ERROR_MESSAGE, M as MAX_BATCH_TIME_MS } from './index.esm2.js';
3
3
  import '@opentelemetry/sdk-trace-base';
4
4
  import '@opentelemetry/sdk-trace-web';
5
5
  import '@opentelemetry/instrumentation';
@@ -492,6 +492,9 @@ function absolutifyURLs(cssText, href) {
492
492
  if (!filePath) {
493
493
  return origin;
494
494
  }
495
+ if (filePath[0] === '#') {
496
+ return "url(".concat(maybeQuote).concat(filePath).concat(maybeQuote, ")");
497
+ }
495
498
  if (URL_PROTOCOL_MATCH.test(filePath) || URL_WWW_MATCH.test(filePath)) {
496
499
  return "url(".concat(maybeQuote).concat(filePath).concat(maybeQuote, ")");
497
500
  }
@@ -712,8 +715,11 @@ function absoluteToDoc(doc, attributeValue) {
712
715
  }
713
716
  return getHref(doc, attributeValue);
714
717
  }
718
+ var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
715
719
  function isSVGElement(el) {
716
- return Boolean(el.tagName === 'svg' || el.ownerSVGElement);
720
+ return Boolean(el.namespaceURI === SVG_NAMESPACE ||
721
+ el.tagName === 'svg' ||
722
+ el.ownerSVGElement);
717
723
  }
718
724
  function getHref(doc, customHref) {
719
725
  var a = cachedDocument.get(doc);
@@ -1166,12 +1172,13 @@ function serializeElementNode(n, options) {
1166
1172
  }
1167
1173
  catch (e) {
1168
1174
  }
1175
+ var isSVG = isSVGElement(n);
1169
1176
  return {
1170
1177
  type: NodeType.Element,
1171
- tagName: tagName,
1178
+ tagName: isSVG ? n.tagName : tagName,
1172
1179
  attributes: attributes,
1173
1180
  childNodes: [],
1174
- isSVG: isSVGElement(n) || undefined,
1181
+ isSVG: isSVG || undefined,
1175
1182
  needBlock: needBlock,
1176
1183
  rootId: rootId,
1177
1184
  isCustom: isCustomElement,
@@ -5710,7 +5717,7 @@ var WorkerManager = (function () {
5710
5717
  var SessionRecorder = (function () {
5711
5718
  function SessionRecorder(sessionManager, recordConfig) {
5712
5719
  var _this = this;
5713
- var _a;
5720
+ var _a, _b;
5714
5721
  this.isAutoStartRecording = false;
5715
5722
  this.onlySessionWithErrorMode = false;
5716
5723
  this.recordEvents = [];
@@ -5788,6 +5795,9 @@ var SessionRecorder = (function () {
5788
5795
  };
5789
5796
  CxGlobal[SESSION_RECORDER_KEY] = this;
5790
5797
  this.sessionManager = sessionManager;
5798
+ if ((_b = getSdkConfig().sessionConfig) === null || _b === void 0 ? void 0 : _b.keepSessionAfterReload) {
5799
+ this.restoreSegmentIndexCounter();
5800
+ }
5791
5801
  var onlySessionWithErrorMode = sessionManager.onlySessionWithErrorMode, maxRecordTimeForSessionWithError = sessionManager.maxRecordTimeForSessionWithError;
5792
5802
  var autoStartSessionRecording = recordConfig.autoStartSessionRecording, workerUrl = recordConfig.workerUrl;
5793
5803
  this.onlySessionWithErrorMode = onlySessionWithErrorMode;
@@ -5812,15 +5822,22 @@ var SessionRecorder = (function () {
5812
5822
  return (this.hasRecording &&
5813
5823
  !!this.segmentIndexCounter[(_a = this.sessionManager.getActiveSession()) === null || _a === void 0 ? void 0 : _a.sessionId]);
5814
5824
  };
5815
- SessionRecorder.prototype.updateSegmentIndexCounter = function (segmentIndexCounter) {
5816
- this.segmentIndexCounter = segmentIndexCounter;
5825
+ SessionRecorder.prototype.getSegmentIndexCounter = function () {
5826
+ return this.segmentIndexCounter;
5827
+ };
5828
+ SessionRecorder.prototype.restoreSegmentIndexCounter = function () {
5829
+ var stored = CxGlobal.sessionStorage.getItem(SESSION_RECORDER_SEGMENTS_MAP);
5830
+ if (stored) {
5831
+ this.segmentIndexCounter = JSON.parse(stored);
5832
+ }
5817
5833
  };
5818
5834
  SessionRecorder.prototype.getIsAutoStartRecording = function () {
5819
5835
  return this.isAutoStartRecording;
5820
5836
  };
5821
5837
  SessionRecorder.prototype.isConsoleRecordingActive = function () {
5822
5838
  var _a;
5823
- return !!this.recordRef && ((_a = getSdkConfig().sessionRecordingConfig) === null || _a === void 0 ? void 0 : _a.recordConsoleEvents) === true;
5839
+ return (!!this.recordRef &&
5840
+ ((_a = getSdkConfig().sessionRecordingConfig) === null || _a === void 0 ? void 0 : _a.recordConsoleEvents) === true);
5824
5841
  };
5825
5842
  Object.defineProperty(SessionRecorder.prototype, "recordingStopDueToTimeout", {
5826
5843
  get: function () {
package/src/Request.d.ts CHANGED
@@ -6,9 +6,11 @@ export declare class Request {
6
6
  private requestConfig;
7
7
  private resolvedUrl;
8
8
  private resolvedHeaders;
9
+ private fetchPriority;
9
10
  constructor(requestConfig: RequestConfig);
10
11
  private getResolvedUrl;
11
12
  private init;
12
13
  send(body: BodyInit): Promise<Response>;
14
+ private isWithinKeepaliveQuota;
13
15
  }
14
16
  export {};
@@ -16,9 +16,8 @@ export declare const NETWORK_URL_LABEL_PROVIDERS_KEY = "NETWORK_URL_LABEL_PROVID
16
16
  export declare const RUM_INTERNAL_DATA_KEY = "rumInternalData";
17
17
  export declare const MASKED_TEXT = "***";
18
18
  export declare const MASK_CLASS_DEFAULT = "cx-mask";
19
- export declare const CX_ACTION_NAME_ATTRIBUTE = "data-cx-action-name";
19
+ export declare const CX_PREFIX = "cx";
20
20
  export declare const ARIA_LABEL_ATTRIBUTE = "aria-label";
21
- export declare const DATA_TEST_ATTRIBUTE = "data-test";
22
21
  export declare const MASK_INPUT_TYPES_DEFAULT: InputType[];
23
22
  export declare const FINGER_PRINT_KEY = "cx-fingerprint";
24
23
  export declare const OPTIONS_DEFAULTS: Partial<CoralogixBrowserSdkConfig>;
@@ -47,14 +46,23 @@ export declare const CoralogixAttributes: {
47
46
  TARGET_ELEMENT: string;
48
47
  TARGET_ELEMENT_TYPE: string;
49
48
  CX_ACTION_NAME: string;
49
+ CX_ID: string;
50
50
  ARIA_LABEL: string;
51
51
  TEST_ID: string;
52
52
  RESOLVED_NAME: string;
53
+ CLICK_X: string;
54
+ CLICK_Y: string;
55
+ ELEMENT_RELATIVE_X: string;
56
+ ELEMENT_RELATIVE_Y: string;
57
+ ELEMENT_WIDTH: string;
58
+ ELEMENT_HEIGHT: string;
59
+ ELEMENT_FINGERPRINT: string;
53
60
  TIMESTAMP: string;
54
61
  INTERNAL: string;
55
62
  PAGE_CONTEXT: string;
56
63
  IS_NAVIGATION_EVENT: string;
57
64
  SCREENSHOT_CONTEXT: string;
65
+ DOM_CONTEXT: string;
58
66
  };
59
67
  export declare const CoralogixDomainsApiUrlMap: {
60
68
  EU1: string;
@@ -0,0 +1,4 @@
1
+ export declare const CX_ACTION_NAME_ATTRIBUTE = "data-cx-action-name";
2
+ export declare const DATA_TEST_ATTRIBUTE = "data-test";
3
+ export declare const DATA_TESTID_ATTRIBUTE = "data-testid";
4
+ export declare const DATA_TEST_ID_ATTRIBUTE = "data-test-id";
package/src/helpers.d.ts CHANGED
@@ -2,9 +2,15 @@ import { SessionManager } from './session/sessionManager';
2
2
  import { SessionRecorder } from './session/sessionRecorder';
3
3
  import { CoralogixBrowserSdkConfig, UserAgentData } from './types';
4
4
  import { SnapshotManager } from './snapshot/snapshotManager';
5
+ import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
6
+ import type { ClickScreenshotManager } from './instrumentations/screenshot/click-screenshot-manager';
5
7
  export declare function getSnapshotManager(): SnapshotManager;
6
8
  export declare function getSessionManager(): SessionManager;
7
9
  export declare function getSessionRecorder(): SessionRecorder | undefined;
10
+ export declare function getClickScreenshotManager(): ClickScreenshotManager | undefined;
8
11
  export declare function getSdkConfig(): CoralogixBrowserSdkConfig;
9
12
  export declare function getUserAgentData(): UserAgentData;
10
13
  export declare function clearMemoryFrom(keys: string[]): void;
14
+ export declare function setTracerProvider(provider: WebTracerProvider): void;
15
+ export declare function getTracerProvider(): WebTracerProvider | undefined;
16
+ export declare function flush(): void;
@@ -1,6 +1,7 @@
1
1
  import { InstrumentationBase, InstrumentationConfig } from '@opentelemetry/instrumentation';
2
2
  export declare class CoralogixDOMInstrumentation extends InstrumentationBase {
3
3
  constructor(config: InstrumentationConfig);
4
+ private createDOMSpan;
4
5
  private visibilityChangeHandler;
5
6
  private registerToDOMEvents;
6
7
  private unregisterFromDOMEvents;
@@ -0,0 +1,9 @@
1
+ export declare class ClickScreenshotManager {
2
+ private secondCaptureClick;
3
+ private clickCount;
4
+ static unregister(): void;
5
+ constructor();
6
+ reset: () => void;
7
+ onNavigation: () => void;
8
+ handleClick: () => void;
9
+ }
@@ -0,0 +1 @@
1
+ export declare const CLICK_SCREENSHOT_MANAGER_KEY = "rumClickScreenshotManager";
@@ -0,0 +1,2 @@
1
+ export declare const SHADOW_DOM_MARKER = "::shadow ";
2
+ export declare function getElementFingerprint(target: Element): string | undefined;
@@ -4,5 +4,6 @@ export declare class CoralogixNavigationProcessor implements SpanProcessor {
4
4
  forceFlush(): Promise<void>;
5
5
  onEnd(span: ReadableSpan): void;
6
6
  onStart(span: Span): void;
7
+ private handlePageNavigation;
7
8
  shutdown(): Promise<void>;
8
9
  }
@@ -9,6 +9,7 @@ export declare class CoralogixSpanMapProcessor implements SpanProcessor, Process
9
9
  forceFlush(): Promise<void>;
10
10
  private _mapToCxSpan;
11
11
  private resolveContextFromSpan;
12
+ private addOtelInstrumentationData;
12
13
  private _getEventTypeContext;
13
14
  private resolveLabels;
14
15
  private getLabelsByLabelProviders;
@@ -16,3 +16,4 @@ export declare const SESSION_EXPIRATION_TIME: number;
16
16
  export declare const SESSION_MANAGER_KEY = "rumSessionManager";
17
17
  export declare const SESSION_RECORDER_KEY = "rumSessionRecorder";
18
18
  export declare const SESSION_RECORDER_SEGMENTS_MAP = "rumSessionRecorderSegmentsMap";
19
+ export declare const VIEW_NUMBER_KEY = "rum_view_number";
@@ -11,6 +11,7 @@ export declare class SessionManager extends SessionIdle {
11
11
  private _currentPageFragment;
12
12
  private _currentPageTimestamp;
13
13
  private _fingerPrint;
14
+ private _viewNumber;
14
15
  private debugMode;
15
16
  constructor(recordConfig?: SessionRecordingConfig);
16
17
  get currentPageTimestamp(): number;
@@ -23,9 +24,14 @@ export declare class SessionManager extends SessionIdle {
23
24
  get cachedLogsSent(): boolean;
24
25
  get sessionHasError(): boolean;
25
26
  get fingerPrint(): string | undefined;
27
+ get viewNumber(): number;
26
28
  set sessionHasError(value: boolean);
27
29
  set cachedLogsSent(val: boolean);
28
30
  updateCurrentPage(fragment: string): void;
31
+ incrementViewNumber(): void;
32
+ private persistViewNumber;
33
+ private loadViewNumber;
34
+ private resetViewNumber;
29
35
  getSessionKey(): string;
30
36
  getActiveSession(): Session;
31
37
  start(): void;
@@ -26,7 +26,8 @@ export declare class SessionRecorder {
26
26
  constructor(sessionManager: SessionManager, recordConfig: SessionRecordingConfig);
27
27
  getSessionHasScreenshot(): boolean;
28
28
  getSessionHasRecording(): boolean;
29
- updateSegmentIndexCounter(segmentIndexCounter: Record<string, number>): void;
29
+ getSegmentIndexCounter(): Record<string, number>;
30
+ private restoreSegmentIndexCounter;
30
31
  getIsAutoStartRecording(): boolean;
31
32
  isConsoleRecordingActive(): boolean;
32
33
  set recordingStopDueToTimeout(value: boolean);
package/src/types.d.ts CHANGED
@@ -75,6 +75,9 @@ export interface ScreenshotContext {
75
75
  id: string;
76
76
  description?: string;
77
77
  }
78
+ export interface DomContext {
79
+ visibility_state: DocumentVisibilityState;
80
+ }
78
81
  export interface ApplicationContextConfig {
79
82
  application: string;
80
83
  version: string;
@@ -161,6 +164,7 @@ export interface CoralogixBrowserSdkConfig {
161
164
  workerSupport?: boolean;
162
165
  tracesExporter?: (data: TraceExporterData) => void;
163
166
  runOutsideAngularZone?: boolean;
167
+ sdkFetchPriority?: RequestPriority;
164
168
  }
165
169
  export interface CoralogixOtelWebType extends SendLog {
166
170
  init: (options: CoralogixBrowserSdkConfig) => void;
@@ -221,12 +225,29 @@ export interface InteractionContext {
221
225
  target_element_inner_text: string;
222
226
  target_element_type: string;
223
227
  event_name: string;
228
+ cx_id: string;
224
229
  element_id: string;
225
230
  element_classes: string;
226
231
  cx_action_name?: string;
227
232
  element_aria_label?: string;
228
233
  element_test_id?: string;
229
234
  resolved_name: string;
235
+ click_x?: number;
236
+ click_y?: number;
237
+ element_relative_x?: number;
238
+ element_relative_y?: number;
239
+ element_width?: number;
240
+ element_height?: number;
241
+ element_fingerprint?: string;
242
+ }
243
+ export interface LayoutContext {
244
+ viewport_width: number;
245
+ viewport_height: number;
246
+ view_width: number;
247
+ view_height: number;
248
+ device_pixel_ratio: number;
249
+ scroll_x: number;
250
+ scroll_y: number;
230
251
  }
231
252
  export interface LongTaskContext extends Omit<PerformanceEntry, 'toJSON'> {
232
253
  id: string;
@@ -258,6 +279,7 @@ export interface EventTypeContext {
258
279
  custom_measurement_context?: CustomMeasurementContext;
259
280
  screenshot_context?: ScreenshotContext;
260
281
  memory_usage_context?: MemoryUsageContext;
282
+ dom_context?: DomContext;
261
283
  }
262
284
  export interface UserMetadata {
263
285
  user_id: string;
@@ -335,6 +357,8 @@ export interface CxRumEvent extends EventTypeContext {
335
357
  screenshot_context?: ScreenshotContext;
336
358
  screenshotId?: string;
337
359
  fingerPrint: string;
360
+ view_number: number;
361
+ layout_context: LayoutContext;
338
362
  }
339
363
  export interface CxSpan {
340
364
  version_metadata: VersionMetaData;
package/src/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "3.10.0";
1
+ export declare const SDK_VERSION = "3.16.0";