@kubesense/kubesense-browser-rum 1.0.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 (540) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +34 -0
  3. package/bundle/chunks/profiler-b64730a2109c3ddbc539-kubesense-rum.js +1 -0
  4. package/bundle/chunks/recorder-9ae532a18bac5f4280da-kubesense-rum.js +1 -0
  5. package/bundle/kubesense-rum.js +1 -0
  6. package/cjs/boot/isBrowserSupported.d.ts +4 -0
  7. package/cjs/boot/isBrowserSupported.js +17 -0
  8. package/cjs/boot/isBrowserSupported.js.map +1 -0
  9. package/cjs/boot/lazyLoadProfiler.d.ts +4 -0
  10. package/cjs/boot/lazyLoadProfiler.js +54 -0
  11. package/cjs/boot/lazyLoadProfiler.js.map +1 -0
  12. package/cjs/boot/lazyLoadRecorder.d.ts +4 -0
  13. package/cjs/boot/lazyLoadRecorder.js +54 -0
  14. package/cjs/boot/lazyLoadRecorder.js.map +1 -0
  15. package/cjs/boot/postStartStrategy.d.ts +33 -0
  16. package/cjs/boot/postStartStrategy.js +98 -0
  17. package/cjs/boot/postStartStrategy.js.map +1 -0
  18. package/cjs/boot/preStartStrategy.d.ts +6 -0
  19. package/cjs/boot/preStartStrategy.js +24 -0
  20. package/cjs/boot/preStartStrategy.js.map +1 -0
  21. package/cjs/boot/profilerApi.d.ts +2 -0
  22. package/cjs/boot/profilerApi.js +53 -0
  23. package/cjs/boot/profilerApi.js.map +1 -0
  24. package/cjs/boot/recorderApi.d.ts +4 -0
  25. package/cjs/boot/recorderApi.js +73 -0
  26. package/cjs/boot/recorderApi.js.map +1 -0
  27. package/cjs/boot/startRecording.d.ts +6 -0
  28. package/cjs/boot/startRecording.js +45 -0
  29. package/cjs/boot/startRecording.js.map +1 -0
  30. package/cjs/domain/deflate/deflateEncoder.d.ts +3 -0
  31. package/cjs/domain/deflate/deflateEncoder.js +110 -0
  32. package/cjs/domain/deflate/deflateEncoder.js.map +1 -0
  33. package/cjs/domain/deflate/deflateWorker.d.ts +30 -0
  34. package/cjs/domain/deflate/deflateWorker.js +104 -0
  35. package/cjs/domain/deflate/deflateWorker.js.map +1 -0
  36. package/cjs/domain/deflate/index.d.ts +3 -0
  37. package/cjs/domain/deflate/index.js +10 -0
  38. package/cjs/domain/deflate/index.js.map +1 -0
  39. package/cjs/domain/getSessionReplayLink.d.ts +2 -0
  40. package/cjs/domain/getSessionReplayLink.js +35 -0
  41. package/cjs/domain/getSessionReplayLink.js.map +1 -0
  42. package/cjs/domain/profiling/profiler.d.ts +7 -0
  43. package/cjs/domain/profiling/profiler.js +244 -0
  44. package/cjs/domain/profiling/profiler.js.map +1 -0
  45. package/cjs/domain/profiling/profilingContext.d.ts +6 -0
  46. package/cjs/domain/profiling/profilingContext.js +28 -0
  47. package/cjs/domain/profiling/profilingContext.js.map +1 -0
  48. package/cjs/domain/profiling/profilingSupported.d.ts +1 -0
  49. package/cjs/domain/profiling/profilingSupported.js +11 -0
  50. package/cjs/domain/profiling/profilingSupported.js.map +1 -0
  51. package/cjs/domain/profiling/test-utils/mockedTrace.d.ts +3 -0
  52. package/cjs/domain/profiling/test-utils/mockedTrace.js +57 -0
  53. package/cjs/domain/profiling/test-utils/mockedTrace.js.map +1 -0
  54. package/cjs/domain/profiling/transport/assembly.d.ts +21 -0
  55. package/cjs/domain/profiling/transport/assembly.js +45 -0
  56. package/cjs/domain/profiling/transport/assembly.js.map +1 -0
  57. package/cjs/domain/profiling/transport/buildProfileEventAttributes.d.ts +25 -0
  58. package/cjs/domain/profiling/transport/buildProfileEventAttributes.js +50 -0
  59. package/cjs/domain/profiling/transport/buildProfileEventAttributes.js.map +1 -0
  60. package/cjs/domain/profiling/types/index.d.ts +2 -0
  61. package/cjs/domain/profiling/types/index.js +3 -0
  62. package/cjs/domain/profiling/types/index.js.map +1 -0
  63. package/cjs/domain/profiling/types/profilerApi.types.d.ts +58 -0
  64. package/cjs/domain/profiling/types/profilerApi.types.js +5 -0
  65. package/cjs/domain/profiling/types/profilerApi.types.js.map +1 -0
  66. package/cjs/domain/profiling/types/rumProfiler.types.d.ts +72 -0
  67. package/cjs/domain/profiling/types/rumProfiler.types.js +3 -0
  68. package/cjs/domain/profiling/types/rumProfiler.types.js.map +1 -0
  69. package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.d.ts +1 -0
  70. package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.js +7 -0
  71. package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.js.map +1 -0
  72. package/cjs/domain/profiling/utils/getDefaultViewName.d.ts +1 -0
  73. package/cjs/domain/profiling/utils/getDefaultViewName.js +14 -0
  74. package/cjs/domain/profiling/utils/getDefaultViewName.js.map +1 -0
  75. package/cjs/domain/profiling/utils/getNumberOfSamples.d.ts +7 -0
  76. package/cjs/domain/profiling/utils/getNumberOfSamples.js +18 -0
  77. package/cjs/domain/profiling/utils/getNumberOfSamples.js.map +1 -0
  78. package/cjs/domain/record/assembly.d.ts +2 -0
  79. package/cjs/domain/record/assembly.js +16 -0
  80. package/cjs/domain/record/assembly.js.map +1 -0
  81. package/cjs/domain/record/elementsScrollPositions.d.ts +10 -0
  82. package/cjs/domain/record/elementsScrollPositions.js +23 -0
  83. package/cjs/domain/record/elementsScrollPositions.js.map +1 -0
  84. package/cjs/domain/record/eventIds.d.ts +4 -0
  85. package/cjs/domain/record/eventIds.js +16 -0
  86. package/cjs/domain/record/eventIds.js.map +1 -0
  87. package/cjs/domain/record/eventsUtils.d.ts +2 -0
  88. package/cjs/domain/record/eventsUtils.js +15 -0
  89. package/cjs/domain/record/eventsUtils.js.map +1 -0
  90. package/cjs/domain/record/index.d.ts +7 -0
  91. package/cjs/domain/record/index.js +17 -0
  92. package/cjs/domain/record/index.js.map +1 -0
  93. package/cjs/domain/record/internalApi.d.ts +22 -0
  94. package/cjs/domain/record/internalApi.js +57 -0
  95. package/cjs/domain/record/internalApi.js.map +1 -0
  96. package/cjs/domain/record/mutationBatch.d.ts +12 -0
  97. package/cjs/domain/record/mutationBatch.js +44 -0
  98. package/cjs/domain/record/mutationBatch.js.map +1 -0
  99. package/cjs/domain/record/nodeIds.d.ts +15 -0
  100. package/cjs/domain/record/nodeIds.js +32 -0
  101. package/cjs/domain/record/nodeIds.js.map +1 -0
  102. package/cjs/domain/record/record.d.ts +16 -0
  103. package/cjs/domain/record/record.js +90 -0
  104. package/cjs/domain/record/record.js.map +1 -0
  105. package/cjs/domain/record/record.types.d.ts +4 -0
  106. package/cjs/domain/record/record.types.js +3 -0
  107. package/cjs/domain/record/record.types.js.map +1 -0
  108. package/cjs/domain/record/recordingScope.d.ts +19 -0
  109. package/cjs/domain/record/recordingScope.js +13 -0
  110. package/cjs/domain/record/recordingScope.js.map +1 -0
  111. package/cjs/domain/record/serialization/index.d.ts +8 -0
  112. package/cjs/domain/record/serialization/index.js +18 -0
  113. package/cjs/domain/record/serialization/index.js.map +1 -0
  114. package/cjs/domain/record/serialization/serialization.types.d.ts +28 -0
  115. package/cjs/domain/record/serialization/serialization.types.js +3 -0
  116. package/cjs/domain/record/serialization/serialization.types.js.map +1 -0
  117. package/cjs/domain/record/serialization/serializationStats.d.ts +12 -0
  118. package/cjs/domain/record/serialization/serializationStats.js +32 -0
  119. package/cjs/domain/record/serialization/serializationStats.js.map +1 -0
  120. package/cjs/domain/record/serialization/serializationTransaction.d.ts +45 -0
  121. package/cjs/domain/record/serialization/serializationTransaction.js +38 -0
  122. package/cjs/domain/record/serialization/serializationTransaction.js.map +1 -0
  123. package/cjs/domain/record/serialization/serializationUtils.d.ts +18 -0
  124. package/cjs/domain/record/serialization/serializationUtils.js +88 -0
  125. package/cjs/domain/record/serialization/serializationUtils.js.map +1 -0
  126. package/cjs/domain/record/serialization/serializeAttribute.d.ts +4 -0
  127. package/cjs/domain/record/serialization/serializeAttribute.js +42 -0
  128. package/cjs/domain/record/serialization/serializeAttribute.js.map +1 -0
  129. package/cjs/domain/record/serialization/serializeAttributes.d.ts +7 -0
  130. package/cjs/domain/record/serialization/serializeAttributes.js +167 -0
  131. package/cjs/domain/record/serialization/serializeAttributes.js.map +1 -0
  132. package/cjs/domain/record/serialization/serializeDocument.d.ts +3 -0
  133. package/cjs/domain/record/serialization/serializeDocument.js +11 -0
  134. package/cjs/domain/record/serialization/serializeDocument.js.map +1 -0
  135. package/cjs/domain/record/serialization/serializeNode.d.ts +7 -0
  136. package/cjs/domain/record/serialization/serializeNode.js +154 -0
  137. package/cjs/domain/record/serialization/serializeNode.js.map +1 -0
  138. package/cjs/domain/record/serialization/serializeStyleSheets.d.ts +2 -0
  139. package/cjs/domain/record/serialization/serializeStyleSheets.js +19 -0
  140. package/cjs/domain/record/serialization/serializeStyleSheets.js.map +1 -0
  141. package/cjs/domain/record/shadowRootsController.d.ts +11 -0
  142. package/cjs/domain/record/shadowRootsController.js +45 -0
  143. package/cjs/domain/record/shadowRootsController.js.map +1 -0
  144. package/cjs/domain/record/startFullSnapshots.d.ts +9 -0
  145. package/cjs/domain/record/startFullSnapshots.js +59 -0
  146. package/cjs/domain/record/startFullSnapshots.js.map +1 -0
  147. package/cjs/domain/record/trackers/index.d.ts +12 -0
  148. package/cjs/domain/record/trackers/index.js +27 -0
  149. package/cjs/domain/record/trackers/index.js.map +1 -0
  150. package/cjs/domain/record/trackers/trackFocus.d.ts +5 -0
  151. package/cjs/domain/record/trackers/trackFocus.js +15 -0
  152. package/cjs/domain/record/trackers/trackFocus.js.map +1 -0
  153. package/cjs/domain/record/trackers/trackFrustration.d.ts +7 -0
  154. package/cjs/domain/record/trackers/trackFrustration.js +31 -0
  155. package/cjs/domain/record/trackers/trackFrustration.js.map +1 -0
  156. package/cjs/domain/record/trackers/trackInput.d.ts +4 -0
  157. package/cjs/domain/record/trackers/trackInput.js +104 -0
  158. package/cjs/domain/record/trackers/trackInput.js.map +1 -0
  159. package/cjs/domain/record/trackers/trackMediaInteraction.d.ts +5 -0
  160. package/cjs/domain/record/trackers/trackMediaInteraction.js +29 -0
  161. package/cjs/domain/record/trackers/trackMediaInteraction.js.map +1 -0
  162. package/cjs/domain/record/trackers/trackMouseInteraction.d.ts +5 -0
  163. package/cjs/domain/record/trackers/trackMouseInteraction.js +59 -0
  164. package/cjs/domain/record/trackers/trackMouseInteraction.js.map +1 -0
  165. package/cjs/domain/record/trackers/trackMove.d.ts +9 -0
  166. package/cjs/domain/record/trackers/trackMove.js +55 -0
  167. package/cjs/domain/record/trackers/trackMove.js.map +1 -0
  168. package/cjs/domain/record/trackers/trackMutation.d.ts +11 -0
  169. package/cjs/domain/record/trackers/trackMutation.js +270 -0
  170. package/cjs/domain/record/trackers/trackMutation.js.map +1 -0
  171. package/cjs/domain/record/trackers/trackScroll.d.ts +5 -0
  172. package/cjs/domain/record/trackers/trackScroll.js +48 -0
  173. package/cjs/domain/record/trackers/trackScroll.js.map +1 -0
  174. package/cjs/domain/record/trackers/trackStyleSheet.d.ts +6 -0
  175. package/cjs/domain/record/trackers/trackStyleSheet.js +89 -0
  176. package/cjs/domain/record/trackers/trackStyleSheet.js.map +1 -0
  177. package/cjs/domain/record/trackers/trackViewEnd.d.ts +5 -0
  178. package/cjs/domain/record/trackers/trackViewEnd.js +20 -0
  179. package/cjs/domain/record/trackers/trackViewEnd.js.map +1 -0
  180. package/cjs/domain/record/trackers/trackViewportResize.d.ts +6 -0
  181. package/cjs/domain/record/trackers/trackViewportResize.js +46 -0
  182. package/cjs/domain/record/trackers/trackViewportResize.js.map +1 -0
  183. package/cjs/domain/record/trackers/tracker.types.d.ts +3 -0
  184. package/cjs/domain/record/trackers/tracker.types.js +3 -0
  185. package/cjs/domain/record/trackers/tracker.types.js.map +1 -0
  186. package/cjs/domain/record/viewports.d.ts +20 -0
  187. package/cjs/domain/record/viewports.js +60 -0
  188. package/cjs/domain/record/viewports.js.map +1 -0
  189. package/cjs/domain/replayStats.d.ts +8 -0
  190. package/cjs/domain/replayStats.js +60 -0
  191. package/cjs/domain/replayStats.js.map +1 -0
  192. package/cjs/domain/scriptLoadingError.d.ts +6 -0
  193. package/cjs/domain/scriptLoadingError.js +26 -0
  194. package/cjs/domain/scriptLoadingError.js.map +1 -0
  195. package/cjs/domain/segmentCollection/buildReplayPayload.d.ts +15 -0
  196. package/cjs/domain/segmentCollection/buildReplayPayload.js +26 -0
  197. package/cjs/domain/segmentCollection/buildReplayPayload.js.map +1 -0
  198. package/cjs/domain/segmentCollection/index.d.ts +4 -0
  199. package/cjs/domain/segmentCollection/index.js +11 -0
  200. package/cjs/domain/segmentCollection/index.js.map +1 -0
  201. package/cjs/domain/segmentCollection/segment.d.ts +16 -0
  202. package/cjs/domain/segmentCollection/segment.js +82 -0
  203. package/cjs/domain/segmentCollection/segment.js.map +1 -0
  204. package/cjs/domain/segmentCollection/segmentCollection.d.ts +31 -0
  205. package/cjs/domain/segmentCollection/segmentCollection.js +113 -0
  206. package/cjs/domain/segmentCollection/segmentCollection.js.map +1 -0
  207. package/cjs/domain/segmentCollection/startSegmentTelemetry.d.ts +6 -0
  208. package/cjs/domain/segmentCollection/startSegmentTelemetry.js +47 -0
  209. package/cjs/domain/segmentCollection/startSegmentTelemetry.js.map +1 -0
  210. package/cjs/domain/startRecordBridge.d.ts +5 -0
  211. package/cjs/domain/startRecordBridge.js +17 -0
  212. package/cjs/domain/startRecordBridge.js.map +1 -0
  213. package/cjs/domain/startRecorderInitTelemetry.d.ts +15 -0
  214. package/cjs/domain/startRecorderInitTelemetry.js +55 -0
  215. package/cjs/domain/startRecorderInitTelemetry.js.map +1 -0
  216. package/cjs/entries/internal.d.ts +11 -0
  217. package/cjs/entries/internal.js +28 -0
  218. package/cjs/entries/internal.js.map +1 -0
  219. package/cjs/entries/internalSynthetics.d.ts +2 -0
  220. package/cjs/entries/internalSynthetics.js +27 -0
  221. package/cjs/entries/internalSynthetics.js.map +1 -0
  222. package/cjs/entries/main.d.ts +23 -0
  223. package/cjs/entries/main.js +35 -0
  224. package/cjs/entries/main.js.map +1 -0
  225. package/cjs/types/index.d.ts +2 -0
  226. package/cjs/types/index.js +18 -0
  227. package/cjs/types/index.js.map +1 -0
  228. package/cjs/types/sessionReplay.d.ts +703 -0
  229. package/cjs/types/sessionReplay.js +7 -0
  230. package/cjs/types/sessionReplay.js.map +1 -0
  231. package/cjs/types/sessionReplayConstants.d.ts +49 -0
  232. package/cjs/types/sessionReplayConstants.js +49 -0
  233. package/cjs/types/sessionReplayConstants.js.map +1 -0
  234. package/esm/boot/isBrowserSupported.d.ts +4 -0
  235. package/esm/boot/isBrowserSupported.js +14 -0
  236. package/esm/boot/isBrowserSupported.js.map +1 -0
  237. package/esm/boot/lazyLoadProfiler.d.ts +4 -0
  238. package/esm/boot/lazyLoadProfiler.js +18 -0
  239. package/esm/boot/lazyLoadProfiler.js.map +1 -0
  240. package/esm/boot/lazyLoadRecorder.d.ts +4 -0
  241. package/esm/boot/lazyLoadRecorder.js +18 -0
  242. package/esm/boot/lazyLoadRecorder.js.map +1 -0
  243. package/esm/boot/postStartStrategy.d.ts +33 -0
  244. package/esm/boot/postStartStrategy.js +95 -0
  245. package/esm/boot/postStartStrategy.js.map +1 -0
  246. package/esm/boot/preStartStrategy.d.ts +6 -0
  247. package/esm/boot/preStartStrategy.js +21 -0
  248. package/esm/boot/preStartStrategy.js.map +1 -0
  249. package/esm/boot/profilerApi.d.ts +2 -0
  250. package/esm/boot/profilerApi.js +50 -0
  251. package/esm/boot/profilerApi.js.map +1 -0
  252. package/esm/boot/recorderApi.d.ts +4 -0
  253. package/esm/boot/recorderApi.js +70 -0
  254. package/esm/boot/recorderApi.js.map +1 -0
  255. package/esm/boot/startRecording.d.ts +6 -0
  256. package/esm/boot/startRecording.js +42 -0
  257. package/esm/boot/startRecording.js.map +1 -0
  258. package/esm/domain/deflate/deflateEncoder.d.ts +3 -0
  259. package/esm/domain/deflate/deflateEncoder.js +107 -0
  260. package/esm/domain/deflate/deflateEncoder.js.map +1 -0
  261. package/esm/domain/deflate/deflateWorker.d.ts +30 -0
  262. package/esm/domain/deflate/deflateWorker.js +97 -0
  263. package/esm/domain/deflate/deflateWorker.js.map +1 -0
  264. package/esm/domain/deflate/index.d.ts +3 -0
  265. package/esm/domain/deflate/index.js +3 -0
  266. package/esm/domain/deflate/index.js.map +1 -0
  267. package/esm/domain/getSessionReplayLink.d.ts +2 -0
  268. package/esm/domain/getSessionReplayLink.js +32 -0
  269. package/esm/domain/getSessionReplayLink.js.map +1 -0
  270. package/esm/domain/profiling/profiler.d.ts +7 -0
  271. package/esm/domain/profiling/profiler.js +240 -0
  272. package/esm/domain/profiling/profiler.js.map +1 -0
  273. package/esm/domain/profiling/profilingContext.d.ts +6 -0
  274. package/esm/domain/profiling/profilingContext.js +25 -0
  275. package/esm/domain/profiling/profilingContext.js.map +1 -0
  276. package/esm/domain/profiling/profilingSupported.d.ts +1 -0
  277. package/esm/domain/profiling/profilingSupported.js +8 -0
  278. package/esm/domain/profiling/profilingSupported.js.map +1 -0
  279. package/esm/domain/profiling/test-utils/mockedTrace.d.ts +3 -0
  280. package/esm/domain/profiling/test-utils/mockedTrace.js +54 -0
  281. package/esm/domain/profiling/test-utils/mockedTrace.js.map +1 -0
  282. package/esm/domain/profiling/transport/assembly.d.ts +21 -0
  283. package/esm/domain/profiling/transport/assembly.js +42 -0
  284. package/esm/domain/profiling/transport/assembly.js.map +1 -0
  285. package/esm/domain/profiling/transport/buildProfileEventAttributes.d.ts +25 -0
  286. package/esm/domain/profiling/transport/buildProfileEventAttributes.js +47 -0
  287. package/esm/domain/profiling/transport/buildProfileEventAttributes.js.map +1 -0
  288. package/esm/domain/profiling/types/index.d.ts +2 -0
  289. package/esm/domain/profiling/types/index.js +2 -0
  290. package/esm/domain/profiling/types/index.js.map +1 -0
  291. package/esm/domain/profiling/types/profilerApi.types.d.ts +58 -0
  292. package/esm/domain/profiling/types/profilerApi.types.js +4 -0
  293. package/esm/domain/profiling/types/profilerApi.types.js.map +1 -0
  294. package/esm/domain/profiling/types/rumProfiler.types.d.ts +72 -0
  295. package/esm/domain/profiling/types/rumProfiler.types.js +2 -0
  296. package/esm/domain/profiling/types/rumProfiler.types.js.map +1 -0
  297. package/esm/domain/profiling/utils/getCustomOrDefaultViewName.d.ts +1 -0
  298. package/esm/domain/profiling/utils/getCustomOrDefaultViewName.js +3 -0
  299. package/esm/domain/profiling/utils/getCustomOrDefaultViewName.js.map +1 -0
  300. package/esm/domain/profiling/utils/getDefaultViewName.d.ts +1 -0
  301. package/esm/domain/profiling/utils/getDefaultViewName.js +11 -0
  302. package/esm/domain/profiling/utils/getDefaultViewName.js.map +1 -0
  303. package/esm/domain/profiling/utils/getNumberOfSamples.d.ts +7 -0
  304. package/esm/domain/profiling/utils/getNumberOfSamples.js +15 -0
  305. package/esm/domain/profiling/utils/getNumberOfSamples.js.map +1 -0
  306. package/esm/domain/record/assembly.d.ts +2 -0
  307. package/esm/domain/record/assembly.js +13 -0
  308. package/esm/domain/record/assembly.js.map +1 -0
  309. package/esm/domain/record/elementsScrollPositions.d.ts +10 -0
  310. package/esm/domain/record/elementsScrollPositions.js +20 -0
  311. package/esm/domain/record/elementsScrollPositions.js.map +1 -0
  312. package/esm/domain/record/eventIds.d.ts +4 -0
  313. package/esm/domain/record/eventIds.js +13 -0
  314. package/esm/domain/record/eventIds.js.map +1 -0
  315. package/esm/domain/record/eventsUtils.d.ts +2 -0
  316. package/esm/domain/record/eventsUtils.js +11 -0
  317. package/esm/domain/record/eventsUtils.js.map +1 -0
  318. package/esm/domain/record/index.d.ts +7 -0
  319. package/esm/domain/record/index.js +6 -0
  320. package/esm/domain/record/index.js.map +1 -0
  321. package/esm/domain/record/internalApi.d.ts +22 -0
  322. package/esm/domain/record/internalApi.js +53 -0
  323. package/esm/domain/record/internalApi.js.map +1 -0
  324. package/esm/domain/record/mutationBatch.d.ts +12 -0
  325. package/esm/domain/record/mutationBatch.js +40 -0
  326. package/esm/domain/record/mutationBatch.js.map +1 -0
  327. package/esm/domain/record/nodeIds.d.ts +15 -0
  328. package/esm/domain/record/nodeIds.js +29 -0
  329. package/esm/domain/record/nodeIds.js.map +1 -0
  330. package/esm/domain/record/record.d.ts +16 -0
  331. package/esm/domain/record/record.js +54 -0
  332. package/esm/domain/record/record.js.map +1 -0
  333. package/esm/domain/record/record.types.d.ts +4 -0
  334. package/esm/domain/record/record.types.js +2 -0
  335. package/esm/domain/record/record.types.js.map +1 -0
  336. package/esm/domain/record/recordingScope.d.ts +19 -0
  337. package/esm/domain/record/recordingScope.js +10 -0
  338. package/esm/domain/record/recordingScope.js.map +1 -0
  339. package/esm/domain/record/serialization/index.d.ts +8 -0
  340. package/esm/domain/record/serialization/index.js +7 -0
  341. package/esm/domain/record/serialization/index.js.map +1 -0
  342. package/esm/domain/record/serialization/serialization.types.d.ts +28 -0
  343. package/esm/domain/record/serialization/serialization.types.js +2 -0
  344. package/esm/domain/record/serialization/serialization.types.js.map +1 -0
  345. package/esm/domain/record/serialization/serializationStats.d.ts +12 -0
  346. package/esm/domain/record/serialization/serializationStats.js +27 -0
  347. package/esm/domain/record/serialization/serializationStats.js.map +1 -0
  348. package/esm/domain/record/serialization/serializationTransaction.d.ts +45 -0
  349. package/esm/domain/record/serialization/serializationTransaction.js +35 -0
  350. package/esm/domain/record/serialization/serializationTransaction.js.map +1 -0
  351. package/esm/domain/record/serialization/serializationUtils.d.ts +18 -0
  352. package/esm/domain/record/serialization/serializationUtils.js +80 -0
  353. package/esm/domain/record/serialization/serializationUtils.js.map +1 -0
  354. package/esm/domain/record/serialization/serializeAttribute.d.ts +4 -0
  355. package/esm/domain/record/serialization/serializeAttribute.js +38 -0
  356. package/esm/domain/record/serialization/serializeAttribute.js.map +1 -0
  357. package/esm/domain/record/serialization/serializeAttributes.d.ts +7 -0
  358. package/esm/domain/record/serialization/serializeAttributes.js +161 -0
  359. package/esm/domain/record/serialization/serializeAttributes.js.map +1 -0
  360. package/esm/domain/record/serialization/serializeDocument.d.ts +3 -0
  361. package/esm/domain/record/serialization/serializeDocument.js +8 -0
  362. package/esm/domain/record/serialization/serializeDocument.js.map +1 -0
  363. package/esm/domain/record/serialization/serializeNode.d.ts +7 -0
  364. package/esm/domain/record/serialization/serializeNode.js +149 -0
  365. package/esm/domain/record/serialization/serializeNode.js.map +1 -0
  366. package/esm/domain/record/serialization/serializeStyleSheets.d.ts +2 -0
  367. package/esm/domain/record/serialization/serializeStyleSheets.js +16 -0
  368. package/esm/domain/record/serialization/serializeStyleSheets.js.map +1 -0
  369. package/esm/domain/record/shadowRootsController.d.ts +11 -0
  370. package/esm/domain/record/shadowRootsController.js +41 -0
  371. package/esm/domain/record/shadowRootsController.js.map +1 -0
  372. package/esm/domain/record/startFullSnapshots.d.ts +9 -0
  373. package/esm/domain/record/startFullSnapshots.js +55 -0
  374. package/esm/domain/record/startFullSnapshots.js.map +1 -0
  375. package/esm/domain/record/trackers/index.d.ts +12 -0
  376. package/esm/domain/record/trackers/index.js +12 -0
  377. package/esm/domain/record/trackers/index.js.map +1 -0
  378. package/esm/domain/record/trackers/trackFocus.d.ts +5 -0
  379. package/esm/domain/record/trackers/trackFocus.js +12 -0
  380. package/esm/domain/record/trackers/trackFocus.js.map +1 -0
  381. package/esm/domain/record/trackers/trackFrustration.d.ts +7 -0
  382. package/esm/domain/record/trackers/trackFrustration.js +28 -0
  383. package/esm/domain/record/trackers/trackFrustration.js.map +1 -0
  384. package/esm/domain/record/trackers/trackInput.d.ts +4 -0
  385. package/esm/domain/record/trackers/trackInput.js +101 -0
  386. package/esm/domain/record/trackers/trackInput.js.map +1 -0
  387. package/esm/domain/record/trackers/trackMediaInteraction.d.ts +5 -0
  388. package/esm/domain/record/trackers/trackMediaInteraction.js +26 -0
  389. package/esm/domain/record/trackers/trackMediaInteraction.js.map +1 -0
  390. package/esm/domain/record/trackers/trackMouseInteraction.d.ts +5 -0
  391. package/esm/domain/record/trackers/trackMouseInteraction.js +56 -0
  392. package/esm/domain/record/trackers/trackMouseInteraction.js.map +1 -0
  393. package/esm/domain/record/trackers/trackMove.d.ts +9 -0
  394. package/esm/domain/record/trackers/trackMove.js +51 -0
  395. package/esm/domain/record/trackers/trackMove.js.map +1 -0
  396. package/esm/domain/record/trackers/trackMutation.d.ts +11 -0
  397. package/esm/domain/record/trackers/trackMutation.js +266 -0
  398. package/esm/domain/record/trackers/trackMutation.js.map +1 -0
  399. package/esm/domain/record/trackers/trackScroll.d.ts +5 -0
  400. package/esm/domain/record/trackers/trackScroll.js +45 -0
  401. package/esm/domain/record/trackers/trackScroll.js.map +1 -0
  402. package/esm/domain/record/trackers/trackStyleSheet.d.ts +6 -0
  403. package/esm/domain/record/trackers/trackStyleSheet.js +85 -0
  404. package/esm/domain/record/trackers/trackStyleSheet.js.map +1 -0
  405. package/esm/domain/record/trackers/trackViewEnd.d.ts +5 -0
  406. package/esm/domain/record/trackers/trackViewEnd.js +17 -0
  407. package/esm/domain/record/trackers/trackViewEnd.js.map +1 -0
  408. package/esm/domain/record/trackers/trackViewportResize.d.ts +6 -0
  409. package/esm/domain/record/trackers/trackViewportResize.js +42 -0
  410. package/esm/domain/record/trackers/trackViewportResize.js.map +1 -0
  411. package/esm/domain/record/trackers/tracker.types.d.ts +3 -0
  412. package/esm/domain/record/trackers/tracker.types.js +2 -0
  413. package/esm/domain/record/trackers/tracker.types.js.map +1 -0
  414. package/esm/domain/record/viewports.d.ts +20 -0
  415. package/esm/domain/record/viewports.js +55 -0
  416. package/esm/domain/record/viewports.js.map +1 -0
  417. package/esm/domain/replayStats.d.ts +8 -0
  418. package/esm/domain/replayStats.js +51 -0
  419. package/esm/domain/replayStats.js.map +1 -0
  420. package/esm/domain/scriptLoadingError.d.ts +6 -0
  421. package/esm/domain/scriptLoadingError.js +23 -0
  422. package/esm/domain/scriptLoadingError.js.map +1 -0
  423. package/esm/domain/segmentCollection/buildReplayPayload.d.ts +15 -0
  424. package/esm/domain/segmentCollection/buildReplayPayload.js +23 -0
  425. package/esm/domain/segmentCollection/buildReplayPayload.js.map +1 -0
  426. package/esm/domain/segmentCollection/index.d.ts +4 -0
  427. package/esm/domain/segmentCollection/index.js +4 -0
  428. package/esm/domain/segmentCollection/index.js.map +1 -0
  429. package/esm/domain/segmentCollection/segment.d.ts +16 -0
  430. package/esm/domain/segmentCollection/segment.js +46 -0
  431. package/esm/domain/segmentCollection/segment.js.map +1 -0
  432. package/esm/domain/segmentCollection/segmentCollection.d.ts +31 -0
  433. package/esm/domain/segmentCollection/segmentCollection.js +106 -0
  434. package/esm/domain/segmentCollection/segmentCollection.js.map +1 -0
  435. package/esm/domain/segmentCollection/startSegmentTelemetry.d.ts +6 -0
  436. package/esm/domain/segmentCollection/startSegmentTelemetry.js +44 -0
  437. package/esm/domain/segmentCollection/startSegmentTelemetry.js.map +1 -0
  438. package/esm/domain/startRecordBridge.d.ts +5 -0
  439. package/esm/domain/startRecordBridge.js +14 -0
  440. package/esm/domain/startRecordBridge.js.map +1 -0
  441. package/esm/domain/startRecorderInitTelemetry.d.ts +15 -0
  442. package/esm/domain/startRecorderInitTelemetry.js +52 -0
  443. package/esm/domain/startRecorderInitTelemetry.js.map +1 -0
  444. package/esm/entries/internal.d.ts +11 -0
  445. package/esm/entries/internal.js +4 -0
  446. package/esm/entries/internal.js.map +1 -0
  447. package/esm/entries/internalSynthetics.d.ts +2 -0
  448. package/esm/entries/internalSynthetics.js +23 -0
  449. package/esm/entries/internalSynthetics.js.map +1 -0
  450. package/esm/entries/main.d.ts +23 -0
  451. package/esm/entries/main.js +31 -0
  452. package/esm/entries/main.js.map +1 -0
  453. package/esm/types/index.d.ts +2 -0
  454. package/esm/types/index.js +2 -0
  455. package/esm/types/index.js.map +1 -0
  456. package/esm/types/sessionReplay.d.ts +703 -0
  457. package/esm/types/sessionReplay.js +6 -0
  458. package/esm/types/sessionReplay.js.map +1 -0
  459. package/esm/types/sessionReplayConstants.d.ts +49 -0
  460. package/esm/types/sessionReplayConstants.js +46 -0
  461. package/esm/types/sessionReplayConstants.js.map +1 -0
  462. package/internal/package.json +6 -0
  463. package/internal-synthetics/package.json +6 -0
  464. package/package.json +40 -0
  465. package/src/boot/isBrowserSupported.ts +14 -0
  466. package/src/boot/lazyLoadProfiler.ts +21 -0
  467. package/src/boot/lazyLoadRecorder.ts +21 -0
  468. package/src/boot/postStartStrategy.ts +176 -0
  469. package/src/boot/preStartStrategy.ts +34 -0
  470. package/src/boot/profilerApi.ts +86 -0
  471. package/src/boot/recorderApi.ts +124 -0
  472. package/src/boot/startRecording.ts +70 -0
  473. package/src/domain/deflate/deflateEncoder.ts +144 -0
  474. package/src/domain/deflate/deflateWorker.ts +157 -0
  475. package/src/domain/deflate/index.ts +8 -0
  476. package/src/domain/getSessionReplayLink.ts +40 -0
  477. package/src/domain/profiling/profiler.ts +338 -0
  478. package/src/domain/profiling/profilingContext.ts +34 -0
  479. package/src/domain/profiling/profilingSupported.ts +10 -0
  480. package/src/domain/profiling/test-utils/mockedTrace.ts +58 -0
  481. package/src/domain/profiling/transport/assembly.ts +78 -0
  482. package/src/domain/profiling/transport/buildProfileEventAttributes.ts +66 -0
  483. package/src/domain/profiling/types/index.ts +2 -0
  484. package/src/domain/profiling/types/profilerApi.types.ts +87 -0
  485. package/src/domain/profiling/types/rumProfiler.types.ts +81 -0
  486. package/src/domain/profiling/utils/getCustomOrDefaultViewName.ts +4 -0
  487. package/src/domain/profiling/utils/getDefaultViewName.ts +12 -0
  488. package/src/domain/profiling/utils/getNumberOfSamples.ts +16 -0
  489. package/src/domain/record/assembly.ts +17 -0
  490. package/src/domain/record/elementsScrollPositions.ts +28 -0
  491. package/src/domain/record/eventIds.ts +17 -0
  492. package/src/domain/record/eventsUtils.ts +12 -0
  493. package/src/domain/record/index.ts +7 -0
  494. package/src/domain/record/internalApi.ts +88 -0
  495. package/src/domain/record/mutationBatch.ts +47 -0
  496. package/src/domain/record/nodeIds.ts +46 -0
  497. package/src/domain/record/record.ts +98 -0
  498. package/src/domain/record/record.types.ts +5 -0
  499. package/src/domain/record/recordingScope.ts +36 -0
  500. package/src/domain/record/serialization/index.ts +8 -0
  501. package/src/domain/record/serialization/serialization.types.ts +43 -0
  502. package/src/domain/record/serialization/serializationStats.ts +43 -0
  503. package/src/domain/record/serialization/serializationTransaction.ts +94 -0
  504. package/src/domain/record/serialization/serializationUtils.ts +103 -0
  505. package/src/domain/record/serialization/serializeAttribute.ts +55 -0
  506. package/src/domain/record/serialization/serializeAttributes.ts +194 -0
  507. package/src/domain/record/serialization/serializeDocument.ts +13 -0
  508. package/src/domain/record/serialization/serializeNode.ts +229 -0
  509. package/src/domain/record/serialization/serializeStyleSheets.ts +18 -0
  510. package/src/domain/record/shadowRootsController.ts +62 -0
  511. package/src/domain/record/startFullSnapshots.ts +84 -0
  512. package/src/domain/record/trackers/index.ts +12 -0
  513. package/src/domain/record/trackers/trackFocus.ts +16 -0
  514. package/src/domain/record/trackers/trackFrustration.ts +41 -0
  515. package/src/domain/record/trackers/trackInput.ts +128 -0
  516. package/src/domain/record/trackers/trackMediaInteraction.ts +43 -0
  517. package/src/domain/record/trackers/trackMouseInteraction.ts +74 -0
  518. package/src/domain/record/trackers/trackMove.ts +78 -0
  519. package/src/domain/record/trackers/trackMutation.ts +399 -0
  520. package/src/domain/record/trackers/trackScroll.ts +61 -0
  521. package/src/domain/record/trackers/trackStyleSheet.ts +117 -0
  522. package/src/domain/record/trackers/trackViewEnd.ts +27 -0
  523. package/src/domain/record/trackers/trackViewportResize.ts +69 -0
  524. package/src/domain/record/trackers/tracker.types.ts +3 -0
  525. package/src/domain/record/viewports.ts +68 -0
  526. package/src/domain/replayStats.ts +61 -0
  527. package/src/domain/scriptLoadingError.ts +36 -0
  528. package/src/domain/segmentCollection/buildReplayPayload.ts +52 -0
  529. package/src/domain/segmentCollection/index.ts +4 -0
  530. package/src/domain/segmentCollection/segment.ts +78 -0
  531. package/src/domain/segmentCollection/segmentCollection.ts +200 -0
  532. package/src/domain/segmentCollection/startSegmentTelemetry.ts +82 -0
  533. package/src/domain/startRecordBridge.ts +17 -0
  534. package/src/domain/startRecorderInitTelemetry.ts +90 -0
  535. package/src/entries/internal.ts +18 -0
  536. package/src/entries/internalSynthetics.ts +24 -0
  537. package/src/entries/main.ts +95 -0
  538. package/src/types/index.ts +2 -0
  539. package/src/types/sessionReplay.ts +734 -0
  540. package/src/types/sessionReplayConstants.ts +86 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Browsers have not standardized various dimension properties. Mobile devices typically report
3
+ * dimensions in reference to the visual viewport, while desktop uses the layout viewport. For example,
4
+ * Mobile Chrome will change innerWidth when a pinch zoom takes place, while Chrome Desktop (mac) will not.
5
+ *
6
+ * With the new Viewport API, we now calculate and normalize dimension properties to the layout viewport.
7
+ * If the VisualViewport API is not supported by a browser, it isn't reasonably possible to detect or normalize
8
+ * which viewport is being measured. Therefore these exported functions will fallback to assuming that the layout
9
+ * viewport is being measured by the browser
10
+ */
11
+
12
+ import type { VisualViewportRecord } from '../../types'
13
+
14
+ // Scrollbar widths vary across properties on different devices and browsers
15
+ const TOLERANCE = 25
16
+
17
+ /**
18
+ * Use the Visual Viewport API's properties to measure scrollX/Y in reference to the layout viewport
19
+ * in order to determine if window.scrollX/Y is measuring the layout or visual viewport.
20
+ * This finding corresponds to which viewport mouseEvent.clientX/Y and window.innerWidth/Height measures.
21
+ */
22
+ function isVisualViewportFactoredIn(visualViewport: VisualViewport) {
23
+ return (
24
+ Math.abs(visualViewport.pageTop - visualViewport.offsetTop - window.scrollY) > TOLERANCE ||
25
+ Math.abs(visualViewport.pageLeft - visualViewport.offsetLeft - window.scrollX) > TOLERANCE
26
+ )
27
+ }
28
+
29
+ interface LayoutCoordinates {
30
+ layoutViewportX: number
31
+ layoutViewportY: number
32
+ visualViewportX: number
33
+ visualViewportY: number
34
+ }
35
+
36
+ export const convertMouseEventToLayoutCoordinates = (clientX: number, clientY: number): LayoutCoordinates => {
37
+ const visualViewport = window.visualViewport
38
+ const normalized: LayoutCoordinates = {
39
+ layoutViewportX: clientX,
40
+ layoutViewportY: clientY,
41
+ visualViewportX: clientX,
42
+ visualViewportY: clientY,
43
+ }
44
+
45
+ if (!visualViewport) {
46
+ // On old browsers, we cannot normalize, so fallback to clientX/Y
47
+ return normalized
48
+ } else if (isVisualViewportFactoredIn(visualViewport)) {
49
+ // Typically Mobile Devices
50
+ normalized.layoutViewportX = Math.round(clientX + visualViewport.offsetLeft)
51
+ normalized.layoutViewportY = Math.round(clientY + visualViewport.offsetTop)
52
+ } else {
53
+ // Typically Desktop Devices
54
+ normalized.visualViewportX = Math.round(clientX - visualViewport.offsetLeft)
55
+ normalized.visualViewportY = Math.round(clientY - visualViewport.offsetTop)
56
+ }
57
+ return normalized
58
+ }
59
+
60
+ export const getVisualViewport = (visualViewport: VisualViewport): VisualViewportRecord['data'] => ({
61
+ scale: visualViewport.scale,
62
+ offsetLeft: visualViewport.offsetLeft,
63
+ offsetTop: visualViewport.offsetTop,
64
+ pageLeft: visualViewport.pageLeft,
65
+ pageTop: visualViewport.pageTop,
66
+ height: visualViewport.height,
67
+ width: visualViewport.width,
68
+ })
@@ -0,0 +1,61 @@
1
+ import type { ReplayStats } from '@kubesense/kubesense-browser-rum-core'
2
+
3
+ export const MAX_STATS_HISTORY = 1000
4
+ let statsPerView: Map<string, ReplayStats> | undefined
5
+
6
+ export function getSegmentsCount(viewId: string) {
7
+ return getOrCreateReplayStats(viewId).segments_count
8
+ }
9
+
10
+ export function addSegment(viewId: string) {
11
+ getOrCreateReplayStats(viewId).segments_count += 1
12
+ }
13
+
14
+ export function addRecord(viewId: string) {
15
+ getOrCreateReplayStats(viewId).records_count += 1
16
+ }
17
+
18
+ export function addWroteData(viewId: string, additionalBytesCount: number) {
19
+ getOrCreateReplayStats(viewId).segments_total_raw_size += additionalBytesCount
20
+ }
21
+
22
+ export function getReplayStats(viewId: string) {
23
+ return statsPerView?.get(viewId)
24
+ }
25
+
26
+ export function resetReplayStats() {
27
+ statsPerView = undefined
28
+ }
29
+
30
+ function getOrCreateReplayStats(viewId: string) {
31
+ if (!statsPerView) {
32
+ statsPerView = new Map()
33
+ }
34
+
35
+ let replayStats: ReplayStats
36
+ if (statsPerView.has(viewId)) {
37
+ replayStats = statsPerView.get(viewId)!
38
+ } else {
39
+ replayStats = {
40
+ records_count: 0,
41
+ segments_count: 0,
42
+ segments_total_raw_size: 0,
43
+ }
44
+ statsPerView.set(viewId, replayStats)
45
+ if (statsPerView.size > MAX_STATS_HISTORY) {
46
+ deleteOldestStats()
47
+ }
48
+ }
49
+
50
+ return replayStats
51
+ }
52
+
53
+ function deleteOldestStats() {
54
+ if (!statsPerView) {
55
+ return
56
+ }
57
+ const toDelete = statsPerView.keys().next().value
58
+ if (toDelete) {
59
+ statsPerView.delete(toDelete)
60
+ }
61
+ }
@@ -0,0 +1,36 @@
1
+ import { addTelemetryError, display, DOCS_ORIGIN } from '@kubesense/kubesense-browser-core'
2
+
3
+ export function reportScriptLoadingError({
4
+ configuredUrl,
5
+ error,
6
+ source,
7
+ scriptType,
8
+ }: {
9
+ configuredUrl?: string | undefined
10
+ error: unknown
11
+ source: string
12
+ scriptType: 'module' | 'worker'
13
+ }) {
14
+ display.error(`${source} failed to start: an error occurred while initializing the ${scriptType}:`, error)
15
+ if (error instanceof Event || (error instanceof Error && isMessageCspRelated(error.message))) {
16
+ let baseMessage
17
+ if (configuredUrl) {
18
+ baseMessage = `Please make sure the ${scriptType} URL ${configuredUrl} is correct and CSP is correctly configured.`
19
+ } else {
20
+ baseMessage = 'Please make sure CSP is correctly configured.'
21
+ }
22
+ display.error(
23
+ `${baseMessage} See documentation at ${DOCS_ORIGIN}/integrations/content_security_policy_logs/#use-csp-with-real-user-monitoring-and-session-replay`
24
+ )
25
+ } else if (scriptType === 'worker') {
26
+ addTelemetryError(error)
27
+ }
28
+ }
29
+
30
+ function isMessageCspRelated(message: string) {
31
+ return (
32
+ message.includes('Content Security Policy') ||
33
+ // Related to `require-trusted-types-for` CSP: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/require-trusted-types-for
34
+ message.includes("requires 'TrustedScriptURL'")
35
+ )
36
+ }
@@ -0,0 +1,52 @@
1
+ import type { Payload, Uint8ArrayBuffer } from '@kubesense/kubesense-browser-core'
2
+ import type { BrowserSegmentMetadata } from '../../types'
3
+ import type { SerializationMetric, SerializationStats } from '../record'
4
+
5
+ export type BrowserSegmentMetadataAndSegmentSizes = BrowserSegmentMetadata & {
6
+ raw_segment_size: number
7
+ compressed_segment_size: number
8
+ }
9
+
10
+ export type ReplayPayload = Payload & {
11
+ cssText: SerializationMetric
12
+ isFullSnapshot: boolean
13
+ rawSize: number
14
+ recordCount: number
15
+ serializationDuration: SerializationMetric
16
+ }
17
+
18
+ export function buildReplayPayload(
19
+ data: Uint8ArrayBuffer,
20
+ metadata: BrowserSegmentMetadata,
21
+ stats: SerializationStats,
22
+ rawSegmentBytesCount: number
23
+ ): ReplayPayload {
24
+ const formData = new FormData()
25
+
26
+ formData.append(
27
+ 'segment',
28
+ new Blob([data], {
29
+ type: 'application/octet-stream',
30
+ }),
31
+ `${metadata.session.id}-${metadata.start}`
32
+ )
33
+
34
+ const metadataAndSegmentSizes: BrowserSegmentMetadataAndSegmentSizes = {
35
+ raw_segment_size: rawSegmentBytesCount,
36
+ compressed_segment_size: data.byteLength,
37
+ ...metadata,
38
+ }
39
+
40
+ const serializedMetadataAndSegmentSizes = JSON.stringify(metadataAndSegmentSizes)
41
+ formData.append('event', new Blob([serializedMetadataAndSegmentSizes], { type: 'application/json' }))
42
+
43
+ return {
44
+ data: formData,
45
+ bytesCount: data.byteLength,
46
+ cssText: stats.cssText,
47
+ isFullSnapshot: metadata.index_in_view === 0,
48
+ rawSize: rawSegmentBytesCount,
49
+ recordCount: metadata.records_count,
50
+ serializationDuration: stats.serializationDuration,
51
+ }
52
+ }
@@ -0,0 +1,4 @@
1
+ export { startSegmentCollection, setSegmentBytesLimit } from './segmentCollection'
2
+ export { SEGMENT_BYTES_LIMIT } from './segmentCollection'
3
+ export type { BrowserSegmentMetadataAndSegmentSizes, ReplayPayload } from './buildReplayPayload'
4
+ export { startSegmentTelemetry } from './startSegmentTelemetry'
@@ -0,0 +1,78 @@
1
+ import type { Encoder, EncoderResult, Uint8ArrayBuffer } from '@kubesense/kubesense-browser-core'
2
+ import type { BrowserRecord, BrowserSegmentMetadata, CreationReason, SegmentContext } from '../../types'
3
+ import { RecordType } from '../../types'
4
+ import * as replayStats from '../replayStats'
5
+ import type { SerializationStats } from '../record'
6
+ import { aggregateSerializationStats, createSerializationStats } from '../record'
7
+
8
+ export type FlushReason = Exclude<CreationReason, 'init'> | 'stop'
9
+ export type FlushCallback = (
10
+ metadata: BrowserSegmentMetadata,
11
+ stats: SerializationStats,
12
+ encoderResult: EncoderResult<Uint8ArrayBuffer>
13
+ ) => void
14
+ export type AddRecordCallback = (encodedBytesCount: number) => void
15
+
16
+ export interface Segment {
17
+ addRecord: (record: BrowserRecord, callback: AddRecordCallback) => void
18
+ addStats: (stats: SerializationStats) => void
19
+ flush: (callback: FlushCallback) => void
20
+ }
21
+
22
+ export function createSegment({
23
+ context,
24
+ creationReason,
25
+ encoder,
26
+ }: {
27
+ context: SegmentContext
28
+ creationReason: CreationReason
29
+ encoder: Encoder<Uint8ArrayBuffer>
30
+ }): Segment {
31
+ let encodedBytesCount = 0
32
+ const viewId = context.view.id
33
+ const indexInView = replayStats.getSegmentsCount(viewId)
34
+ const metadata: BrowserSegmentMetadata = {
35
+ start: Infinity,
36
+ end: -Infinity,
37
+ creation_reason: creationReason,
38
+ records_count: 0,
39
+ has_full_snapshot: false,
40
+ index_in_view: indexInView,
41
+ source: 'browser' as const,
42
+ ...context,
43
+ }
44
+
45
+ const serializationStats = createSerializationStats()
46
+ replayStats.addSegment(viewId)
47
+
48
+ function addRecord(record: BrowserRecord, callback: AddRecordCallback): void {
49
+ metadata.start = Math.min(metadata.start, record.timestamp)
50
+ metadata.end = Math.max(metadata.end, record.timestamp)
51
+ metadata.records_count += 1
52
+ metadata.has_full_snapshot ||= record.type === RecordType.FullSnapshot
53
+
54
+ const prefix = encoder.isEmpty ? '{"records":[' : ','
55
+ encoder.write(prefix + JSON.stringify(record), (additionalEncodedBytesCount) => {
56
+ encodedBytesCount += additionalEncodedBytesCount
57
+ callback(encodedBytesCount)
58
+ })
59
+ }
60
+
61
+ function addStats(stats: SerializationStats): void {
62
+ aggregateSerializationStats(serializationStats, stats)
63
+ }
64
+
65
+ function flush(callback: FlushCallback) {
66
+ if (encoder.isEmpty) {
67
+ throw new Error('Empty segment flushed')
68
+ }
69
+
70
+ encoder.write(`],${JSON.stringify(metadata).slice(1)}\n`)
71
+ encoder.finish((encoderResult) => {
72
+ replayStats.addWroteData(metadata.view.id, encoderResult.rawBytesCount)
73
+ callback(metadata, serializationStats, encoderResult)
74
+ })
75
+ }
76
+
77
+ return { addRecord, addStats, flush }
78
+ }
@@ -0,0 +1,200 @@
1
+ import type { DeflateEncoder, HttpRequest, TimeoutId } from '@kubesense/kubesense-browser-core'
2
+ import { isPageExitReason, ONE_SECOND, clearTimeout, setTimeout } from '@kubesense/kubesense-browser-core'
3
+ import type { LifeCycle, ViewHistory, RumSessionManager, RumConfiguration } from '@kubesense/kubesense-browser-rum-core'
4
+ import { LifeCycleEventType } from '@kubesense/kubesense-browser-rum-core'
5
+ import type { BrowserRecord, CreationReason, SegmentContext } from '../../types'
6
+ import type { SerializationStats } from '../record'
7
+ import type { ReplayPayload } from './buildReplayPayload'
8
+ import { buildReplayPayload } from './buildReplayPayload'
9
+ import type { FlushReason, Segment } from './segment'
10
+ import { createSegment } from './segment'
11
+
12
+ export const SEGMENT_DURATION_LIMIT = 5 * ONE_SECOND
13
+ /**
14
+ * beacon payload max queue size implementation is 64kb
15
+ * ensure that we leave room for logs, rum and potential other users
16
+ */
17
+ export let SEGMENT_BYTES_LIMIT = 60_000
18
+
19
+ // Segments are the main data structure for session replays. They contain context information used
20
+ // for indexing or UI needs, and a list of records (RRWeb 'events', renamed to avoid confusing
21
+ // namings). They are stored without any processing from the intake, and fetched one after the
22
+ // other while a session is being replayed. Their encoding (deflate) are carefully crafted to allow
23
+ // concatenating multiple segments together. Segments have a size overhead (metadata), so our goal is to
24
+ // build segments containing as many records as possible while complying with the various flush
25
+ // strategies to guarantee a good replay quality.
26
+ //
27
+ // When the recording starts, a segment is initially created. The segment is flushed (finalized and
28
+ // sent) based on various events (non-exhaustive list):
29
+ //
30
+ // * the page visibility change or becomes to unload
31
+ // * the segment duration reaches a limit
32
+ // * the encoded segment bytes count reaches a limit
33
+ // * ...
34
+ //
35
+ // A segment cannot be created without its context. If the RUM session ends and no session id is
36
+ // available when creating a new segment, records will be ignored, until the session is renewed and
37
+ // a new session id is available.
38
+ //
39
+ // Empty segments (segments with no record) aren't useful and should be ignored.
40
+ //
41
+ // To help investigate session replays issues, each segment is created with a "creation reason",
42
+ // indicating why the session has been created.
43
+
44
+ interface SegmentCollector {
45
+ addRecord(this: void, record: BrowserRecord): void
46
+ addStats(this: void, stats: SerializationStats): void
47
+ stop(this: void): void
48
+ }
49
+
50
+ export function startSegmentCollection(
51
+ lifeCycle: LifeCycle,
52
+ configuration: RumConfiguration,
53
+ sessionManager: RumSessionManager,
54
+ viewHistory: ViewHistory,
55
+ httpRequest: HttpRequest<ReplayPayload>,
56
+ encoder: DeflateEncoder
57
+ ): SegmentCollector {
58
+ return doStartSegmentCollection(
59
+ lifeCycle,
60
+ () => computeSegmentContext(configuration.applicationId, sessionManager, viewHistory),
61
+ httpRequest,
62
+ encoder
63
+ )
64
+ }
65
+
66
+ const enum SegmentCollectionStatus {
67
+ WaitingForInitialRecord,
68
+ SegmentPending,
69
+ Stopped,
70
+ }
71
+ type SegmentCollectionState =
72
+ | {
73
+ status: SegmentCollectionStatus.WaitingForInitialRecord
74
+ nextSegmentCreationReason: CreationReason
75
+ }
76
+ | {
77
+ status: SegmentCollectionStatus.SegmentPending
78
+ segment: Segment
79
+ expirationTimeoutId: TimeoutId
80
+ }
81
+ | {
82
+ status: SegmentCollectionStatus.Stopped
83
+ }
84
+
85
+ export function doStartSegmentCollection(
86
+ lifeCycle: LifeCycle,
87
+ getSegmentContext: () => SegmentContext | undefined,
88
+ httpRequest: HttpRequest<ReplayPayload>,
89
+ encoder: DeflateEncoder
90
+ ): SegmentCollector {
91
+ let state: SegmentCollectionState = {
92
+ status: SegmentCollectionStatus.WaitingForInitialRecord,
93
+ nextSegmentCreationReason: 'init',
94
+ }
95
+
96
+ const { unsubscribe: unsubscribeViewCreated } = lifeCycle.subscribe(LifeCycleEventType.VIEW_CREATED, () => {
97
+ flushSegment('view_change')
98
+ })
99
+
100
+ const { unsubscribe: unsubscribePageMayExit } = lifeCycle.subscribe(
101
+ LifeCycleEventType.PAGE_MAY_EXIT,
102
+ (pageMayExitEvent) => {
103
+ flushSegment(pageMayExitEvent.reason as FlushReason)
104
+ }
105
+ )
106
+
107
+ function flushSegment(flushReason: FlushReason) {
108
+ if (state.status === SegmentCollectionStatus.SegmentPending) {
109
+ state.segment.flush((metadata, stats, encoderResult) => {
110
+ const payload = buildReplayPayload(encoderResult.output, metadata, stats, encoderResult.rawBytesCount)
111
+
112
+ if (isPageExitReason(flushReason)) {
113
+ httpRequest.sendOnExit(payload)
114
+ } else {
115
+ httpRequest.send(payload)
116
+ }
117
+ })
118
+ clearTimeout(state.expirationTimeoutId)
119
+ }
120
+
121
+ if (flushReason !== 'stop') {
122
+ state = {
123
+ status: SegmentCollectionStatus.WaitingForInitialRecord,
124
+ nextSegmentCreationReason: flushReason,
125
+ }
126
+ } else {
127
+ state = {
128
+ status: SegmentCollectionStatus.Stopped,
129
+ }
130
+ }
131
+ }
132
+
133
+ return {
134
+ addRecord: (record: BrowserRecord) => {
135
+ if (state.status === SegmentCollectionStatus.Stopped) {
136
+ return
137
+ }
138
+
139
+ if (state.status === SegmentCollectionStatus.WaitingForInitialRecord) {
140
+ const context = getSegmentContext()
141
+ if (!context) {
142
+ return
143
+ }
144
+
145
+ state = {
146
+ status: SegmentCollectionStatus.SegmentPending,
147
+ segment: createSegment({ encoder, context, creationReason: state.nextSegmentCreationReason }),
148
+ expirationTimeoutId: setTimeout(() => {
149
+ flushSegment('segment_duration_limit')
150
+ }, SEGMENT_DURATION_LIMIT),
151
+ }
152
+ }
153
+
154
+ state.segment.addRecord(record, (encodedBytesCount) => {
155
+ if (encodedBytesCount > SEGMENT_BYTES_LIMIT) {
156
+ flushSegment('segment_bytes_limit')
157
+ }
158
+ })
159
+ },
160
+
161
+ addStats: (stats: SerializationStats) => {
162
+ if (state.status === SegmentCollectionStatus.SegmentPending) {
163
+ state.segment.addStats(stats)
164
+ }
165
+ },
166
+
167
+ stop: () => {
168
+ flushSegment('stop')
169
+ unsubscribeViewCreated()
170
+ unsubscribePageMayExit()
171
+ },
172
+ }
173
+ }
174
+
175
+ export function computeSegmentContext(
176
+ applicationId: string,
177
+ sessionManager: RumSessionManager,
178
+ viewHistory: ViewHistory
179
+ ) {
180
+ const session = sessionManager.findTrackedSession()
181
+ const viewContext = viewHistory.findView()
182
+ if (!session || !viewContext) {
183
+ return undefined
184
+ }
185
+ return {
186
+ application: {
187
+ id: applicationId,
188
+ },
189
+ session: {
190
+ id: session.id,
191
+ },
192
+ view: {
193
+ id: viewContext.id,
194
+ },
195
+ }
196
+ }
197
+
198
+ export function setSegmentBytesLimit(newSegmentBytesLimit = 60_000) {
199
+ SEGMENT_BYTES_LIMIT = newSegmentBytesLimit
200
+ }
@@ -0,0 +1,82 @@
1
+ import type { BandwidthStats, Context, HttpRequestEvent, Observable, Telemetry } from '@kubesense/kubesense-browser-core'
2
+ import { TelemetryMetrics, addTelemetryMetrics, noop } from '@kubesense/kubesense-browser-core'
3
+ import type { ReplayPayload } from './buildReplayPayload'
4
+
5
+ interface SegmentMetrics extends Context {
6
+ cssText: {
7
+ count: number
8
+ max: number
9
+ sum: number
10
+ }
11
+ isFullSnapshot: boolean
12
+ ongoingRequests: {
13
+ count: number
14
+ totalSize: number
15
+ }
16
+ recordCount: number
17
+ result: 'failure' | 'queue-full' | 'success'
18
+ serializationDuration: {
19
+ count: number
20
+ max: number
21
+ sum: number
22
+ }
23
+ size: {
24
+ compressed: number
25
+ raw: number
26
+ }
27
+ }
28
+
29
+ export function startSegmentTelemetry(
30
+ telemetry: Telemetry,
31
+ requestObservable: Observable<HttpRequestEvent<ReplayPayload>>
32
+ ) {
33
+ if (!telemetry.metricsEnabled) {
34
+ return { stop: noop }
35
+ }
36
+
37
+ const { unsubscribe } = requestObservable.subscribe((requestEvent) => {
38
+ if (
39
+ requestEvent.type === 'failure' ||
40
+ requestEvent.type === 'queue-full' ||
41
+ (requestEvent.type === 'success' && requestEvent.payload.isFullSnapshot)
42
+ ) {
43
+ const metrics = createSegmentMetrics(requestEvent.type, requestEvent.bandwidth, requestEvent.payload)
44
+ // monitor-until: 2026-07-01
45
+ addTelemetryMetrics(TelemetryMetrics.SEGMENT_METRICS_TELEMETRY_NAME, { metrics })
46
+ }
47
+ })
48
+
49
+ return {
50
+ stop: unsubscribe,
51
+ }
52
+ }
53
+
54
+ function createSegmentMetrics(
55
+ result: SegmentMetrics['result'],
56
+ bandwidthStats: BandwidthStats,
57
+ payload: ReplayPayload
58
+ ): SegmentMetrics {
59
+ return {
60
+ cssText: {
61
+ count: payload.cssText.count,
62
+ max: payload.cssText.max,
63
+ sum: payload.cssText.sum,
64
+ },
65
+ isFullSnapshot: payload.isFullSnapshot,
66
+ ongoingRequests: {
67
+ count: bandwidthStats.ongoingRequestCount,
68
+ totalSize: bandwidthStats.ongoingByteCount,
69
+ },
70
+ recordCount: payload.recordCount,
71
+ result,
72
+ serializationDuration: {
73
+ count: payload.serializationDuration.count,
74
+ max: payload.serializationDuration.max,
75
+ sum: payload.serializationDuration.sum,
76
+ },
77
+ size: {
78
+ compressed: payload.bytesCount,
79
+ raw: payload.rawSize,
80
+ },
81
+ }
82
+ }
@@ -0,0 +1,17 @@
1
+ import { getEventBridge } from '@kubesense/kubesense-browser-core'
2
+ import type { ViewHistory } from '@kubesense/kubesense-browser-rum-core'
3
+ import type { BrowserRecord } from '../types'
4
+
5
+ export function startRecordBridge(viewHistory: ViewHistory) {
6
+ const bridge = getEventBridge<'record', BrowserRecord>()!
7
+
8
+ return {
9
+ addRecord: (record: BrowserRecord) => {
10
+ // Get the current active view, not at the time of the record, aligning with the segment logic.
11
+ // This approach could potentially associate the record to an incorrect view, in case the record date is in the past (e.g. frustration records).
12
+ // However the risk is minimal. We could address the issue when potential negative impact are identified.
13
+ const view = viewHistory.findView()!
14
+ bridge.send('record', record, view.id)
15
+ },
16
+ }
17
+ }
@@ -0,0 +1,90 @@
1
+ import type { Context, Duration, Telemetry, Observable, TimeStamp } from '@kubesense/kubesense-browser-core'
2
+ import { TelemetryMetrics, addTelemetryMetrics, noop, timeStampNow, elapsed } from '@kubesense/kubesense-browser-core'
3
+ import type { RecorderInitEvent } from '../boot/postStartStrategy'
4
+
5
+ type RecorderInitResult = 'aborted' | 'deflate-encoder-load-failed' | 'recorder-load-failed' | 'succeeded'
6
+
7
+ export interface RecorderInitMetrics extends Context {
8
+ forced: boolean
9
+ loadRecorderModuleDuration: number | undefined
10
+ recorderInitDuration: number
11
+ result: RecorderInitResult
12
+ waitForDocReadyDuration: number | undefined
13
+ }
14
+
15
+ export function startRecorderInitTelemetry(telemetry: Telemetry, observable: Observable<RecorderInitEvent>) {
16
+ if (!telemetry.metricsEnabled) {
17
+ return { stop: noop }
18
+ }
19
+
20
+ let startContext:
21
+ | {
22
+ forced: boolean
23
+ timestamp: TimeStamp
24
+ }
25
+ | undefined
26
+
27
+ let documentReadyDuration: Duration | undefined
28
+ let recorderSettledDuration: Duration | undefined
29
+
30
+ const { unsubscribe } = observable.subscribe((event) => {
31
+ switch (event.type) {
32
+ case 'start':
33
+ startContext = { forced: event.forced, timestamp: timeStampNow() }
34
+ documentReadyDuration = undefined
35
+ recorderSettledDuration = undefined
36
+ break
37
+
38
+ case 'document-ready':
39
+ if (startContext) {
40
+ documentReadyDuration = elapsed(startContext.timestamp, timeStampNow())
41
+ }
42
+ break
43
+
44
+ case 'recorder-settled':
45
+ if (startContext) {
46
+ recorderSettledDuration = elapsed(startContext.timestamp, timeStampNow())
47
+ }
48
+ break
49
+
50
+ case 'aborted':
51
+ case 'deflate-encoder-load-failed':
52
+ case 'recorder-load-failed':
53
+ case 'succeeded':
54
+ // Only send metrics for the first attempt at starting the recorder.
55
+ unsubscribe()
56
+
57
+ if (startContext) {
58
+ // monitor-until: 2026-07-01
59
+ addTelemetryMetrics(TelemetryMetrics.RECORDER_INIT_METRICS_TELEMETRY_NAME, {
60
+ metrics: createRecorderInitMetrics(
61
+ startContext.forced,
62
+ recorderSettledDuration,
63
+ elapsed(startContext.timestamp, timeStampNow()),
64
+ event.type,
65
+ documentReadyDuration
66
+ ),
67
+ })
68
+ }
69
+ break
70
+ }
71
+ })
72
+
73
+ return { stop: unsubscribe }
74
+ }
75
+
76
+ function createRecorderInitMetrics(
77
+ forced: boolean,
78
+ loadRecorderModuleDuration: Duration | undefined,
79
+ recorderInitDuration: Duration,
80
+ result: RecorderInitResult,
81
+ waitForDocReadyDuration: Duration | undefined
82
+ ): RecorderInitMetrics {
83
+ return {
84
+ forced,
85
+ loadRecorderModuleDuration,
86
+ recorderInitDuration,
87
+ result,
88
+ waitForDocReadyDuration,
89
+ }
90
+ }