@oneuptime/common 11.7.4 → 12.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 (872) hide show
  1. package/Models/AnalyticsModels/ExceptionInstance.ts +67 -0
  2. package/Models/AnalyticsModels/Index.ts +10 -0
  3. package/Models/AnalyticsModels/Log.ts +60 -0
  4. package/Models/AnalyticsModels/RumSession.ts +1401 -0
  5. package/Models/AnalyticsModels/RumSessionChunk.ts +798 -0
  6. package/Models/AnalyticsModels/Span.ts +60 -0
  7. package/Models/DatabaseModels/AIAgentTaskPullRequest.ts +52 -0
  8. package/Models/DatabaseModels/AIRun.ts +31 -0
  9. package/Models/DatabaseModels/Alert.ts +29 -0
  10. package/Models/DatabaseModels/AlertCustomField.ts +1 -1
  11. package/Models/DatabaseModels/AlertFeed.ts +1 -0
  12. package/Models/DatabaseModels/AutoRemediationRule.ts +989 -0
  13. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +874 -0
  14. package/Models/DatabaseModels/CodeRepository.ts +129 -0
  15. package/Models/DatabaseModels/GlobalConfig.ts +312 -0
  16. package/Models/DatabaseModels/Incident.ts +29 -0
  17. package/Models/DatabaseModels/IncidentCustomField.ts +1 -1
  18. package/Models/DatabaseModels/IncidentFeed.ts +1 -0
  19. package/Models/DatabaseModels/Index.ts +21 -8
  20. package/Models/DatabaseModels/InstanceHealthLog.ts +8 -0
  21. package/Models/DatabaseModels/MonitorCustomField.ts +1 -1
  22. package/Models/DatabaseModels/MonitorStatus.ts +1 -1
  23. package/Models/DatabaseModels/NetworkDeviceLabelRule.ts +2 -2
  24. package/Models/DatabaseModels/NetworkDeviceOwnerRule.ts +2 -2
  25. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +1 -1
  26. package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +1 -1
  27. package/Models/DatabaseModels/Project.ts +231 -0
  28. package/Models/DatabaseModels/RumApplication.ts +906 -0
  29. package/Models/DatabaseModels/RumSessionErasureRequest.ts +561 -0
  30. package/Models/DatabaseModels/RumSessionPin.ts +457 -0
  31. package/Models/DatabaseModels/RumSessionReplayView.ts +406 -0
  32. package/Models/DatabaseModels/RunbookCredential.ts +673 -0
  33. package/Models/DatabaseModels/RunbookSecret.ts +7 -7
  34. package/Models/DatabaseModels/{RunbookAgent.ts → Runner.ts} +206 -46
  35. package/Models/DatabaseModels/{RunbookAgentJob.ts → RunnerJob.ts} +151 -18
  36. package/Models/DatabaseModels/{RunbookAgentOwnerTeam.ts → RunnerOwnerTeam.ts} +41 -43
  37. package/Models/DatabaseModels/{RunbookAgentOwnerUser.ts → RunnerOwnerUser.ts} +41 -43
  38. package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +1 -1
  39. package/Models/DatabaseModels/StatusPageCustomField.ts +1 -1
  40. package/Models/DatabaseModels/TeamCustomField.ts +1 -1
  41. package/Models/DatabaseModels/TeamMemberCustomField.ts +1 -1
  42. package/Server/API/AIAgentDataAPI.ts +179 -48
  43. package/Server/API/AIAgentTaskAPI.ts +36 -37
  44. package/Server/API/AIAgentTaskLogAPI.ts +19 -33
  45. package/Server/API/AutoRemediationAPI.ts +557 -0
  46. package/Server/API/BaseAnalyticsAPI.ts +4 -1
  47. package/Server/API/CommonAPI.ts +35 -0
  48. package/Server/API/DashboardAPI.ts +340 -15
  49. package/Server/API/TelemetryAPI.ts +1622 -3
  50. package/Server/API/UserIncomingCallNumberAPI.ts +31 -0
  51. package/Server/DatabaseConfig.ts +26 -1
  52. package/Server/EnvironmentConfig.ts +13 -0
  53. package/Server/Infrastructure/Postgres/SchemaMigrations/1785417351021-AddSessionReplay.ts +293 -0
  54. package/Server/Infrastructure/Postgres/SchemaMigrations/1785491583874-EnableSessionReplayByDefault.ts +67 -0
  55. package/Server/Infrastructure/Postgres/SchemaMigrations/1785496223183-AddMonitorSummaryToIncidentAndAlert.ts +33 -0
  56. package/Server/Infrastructure/Postgres/SchemaMigrations/1785516996695-AddSessionReplayReliabilityColumns.ts +40 -0
  57. package/Server/Infrastructure/Postgres/SchemaMigrations/1785533806494-AddSessionReplayCorrelationColumns.ts +54 -0
  58. package/Server/Infrastructure/Postgres/SchemaMigrations/1785749674203-AddRedisAndPostgresHealthNotificationColumns.ts +104 -0
  59. package/Server/Infrastructure/Postgres/SchemaMigrations/1785763818197-AddAutoRemediation.ts +349 -0
  60. package/Server/Infrastructure/Postgres/SchemaMigrations/1785768089408-AddRemediationVerification.ts +67 -0
  61. package/Server/Infrastructure/Postgres/SchemaMigrations/1785776960660-AddRunnerCapabilities.ts +23 -0
  62. package/Server/Infrastructure/Postgres/SchemaMigrations/1785790000000-AddIncidentInvestigationGating.ts +42 -0
  63. package/Server/Infrastructure/Postgres/SchemaMigrations/1785800000000-AddRunbookCredential.ts +84 -0
  64. package/Server/Infrastructure/Postgres/SchemaMigrations/1785810000000-RenameRunbookAgentToRunner.ts +152 -0
  65. package/Server/Infrastructure/Postgres/SchemaMigrations/1785860000000-SessionReplayDefaultToSensitiveInputMasking.ts +81 -0
  66. package/Server/Infrastructure/Postgres/SchemaMigrations/1785870000000-AddAiCommandRemediation.ts +151 -0
  67. package/Server/Infrastructure/Postgres/SchemaMigrations/1785880000000-AlignRunnerSchemaWithEntities.ts +597 -0
  68. package/Server/Infrastructure/Postgres/SchemaMigrations/1785890000000-AddFixVerificationAndAutomaticCodeFixes.ts +71 -0
  69. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +32 -0
  70. package/Server/Services/AIRunService.ts +10 -0
  71. package/Server/Services/AIService.ts +30 -0
  72. package/Server/Services/AlertService.ts +41 -4
  73. package/Server/Services/AlertSeverityService.ts +25 -11
  74. package/Server/Services/AlertStateService.ts +25 -11
  75. package/Server/Services/AutoRemediationRuleEngineService.ts +1101 -0
  76. package/Server/Services/{RunbookAgentOwnerTeamService.ts → AutoRemediationRuleService.ts} +1 -1
  77. package/Server/Services/AutoRemediationSuggestionService.ts +183 -0
  78. package/Server/Services/BillingService.ts +50 -1
  79. package/Server/Services/DatabaseService.ts +92 -4
  80. package/Server/Services/IncidentService.ts +56 -4
  81. package/Server/Services/IncidentSeverityService.ts +25 -11
  82. package/Server/Services/IncidentStateService.ts +25 -11
  83. package/Server/Services/Index.ts +19 -0
  84. package/Server/Services/MonitorService.ts +24 -0
  85. package/Server/Services/MonitorStatusService.ts +25 -11
  86. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +18 -19
  87. package/Server/Services/NetworkDeviceLabelRuleService.ts +39 -0
  88. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +18 -19
  89. package/Server/Services/NetworkDeviceOwnerRuleService.ts +37 -0
  90. package/Server/Services/NetworkDeviceService.ts +172 -21
  91. package/Server/Services/NetworkSiteAssignmentRuleService.ts +92 -12
  92. package/Server/Services/NetworkSiteService.ts +27 -10
  93. package/Server/Services/ProjectService.ts +47 -0
  94. package/Server/Services/RumApplicationService.ts +240 -1
  95. package/Server/Services/RumSessionChunkService.ts +11 -0
  96. package/Server/Services/RumSessionErasureRequestService.ts +197 -0
  97. package/Server/Services/RumSessionPinService.ts +213 -0
  98. package/Server/Services/RumSessionReplayViewService.ts +201 -0
  99. package/Server/Services/RumSessionService.ts +123 -0
  100. package/Server/Services/RunbookCredentialService.ts +76 -0
  101. package/Server/Services/{RunbookAgentJobService.ts → RunnerJobService.ts} +202 -51
  102. package/Server/Services/{RunbookAgentOwnerUserService.ts → RunnerOwnerTeamService.ts} +1 -1
  103. package/Server/Services/RunnerOwnerUserService.ts +10 -0
  104. package/Server/Services/RunnerService.ts +172 -0
  105. package/Server/Services/ScheduledMaintenanceStateService.ts +25 -11
  106. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +15 -1
  107. package/Server/Services/ServiceService.ts +8 -2
  108. package/Server/Services/StatusPageService.ts +240 -36
  109. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +20 -1
  110. package/Server/Services/TelemetryExceptionService.ts +3 -16
  111. package/Server/Services/TelemetryUsageBillingService.ts +33 -2
  112. package/Server/Services/TraceAggregationService.ts +196 -32
  113. package/Server/Types/Billing/MeteredPlan/AllMeteredPlans.ts +17 -0
  114. package/Server/Types/Billing/MeteredPlan/ServerMeteredPlan.ts +10 -0
  115. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +63 -7
  116. package/Server/Utils/AI/CodeFix/CodeFixAgentAuth.ts +128 -0
  117. package/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.ts +54 -0
  118. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +17 -10
  119. package/Server/Utils/AI/CodeFix/CodeFixRunQueue.ts +8 -6
  120. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +943 -0
  121. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +866 -0
  122. package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +823 -0
  123. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +103 -12
  124. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +75 -17
  125. package/Server/Utils/AI/SRE/ConfidenceSignal.ts +28 -6
  126. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +202 -12
  127. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +264 -14
  128. package/Server/Utils/AI/SRE/Insights/Triage.ts +2 -7
  129. package/Server/Utils/AI/SRE/InvestigationGrader.ts +5 -24
  130. package/Server/Utils/AI/SRE/InvestigationQueue.ts +259 -20
  131. package/Server/Utils/AI/SRE/PostedRootCause.ts +82 -0
  132. package/Server/Utils/AI/SRE/README.md +3 -2
  133. package/Server/Utils/AI/SRE/RemediationHandoff.ts +82 -0
  134. package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +6 -19
  135. package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +2 -2
  136. package/Server/Utils/Alert/AlertPrivacyFilter.ts +58 -0
  137. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +604 -0
  138. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +619 -0
  139. package/Server/Utils/CorsOptions.ts +52 -0
  140. package/Server/Utils/Database/RelationIdUtil.ts +68 -0
  141. package/Server/Utils/Incident/IncidentPrivacyFilter.ts +60 -0
  142. package/Server/Utils/InstanceHealth/PostgresHealth.ts +286 -0
  143. package/Server/Utils/InstanceHealth/RedisHealth.ts +434 -0
  144. package/Server/Utils/Monitor/MonitorAlert.ts +20 -0
  145. package/Server/Utils/Monitor/MonitorIncident.ts +20 -0
  146. package/Server/Utils/Monitor/MonitorResource.ts +19 -0
  147. package/Server/Utils/Monitor/MonitorSummaryCapture.ts +104 -0
  148. package/Server/Utils/NetworkDevice/RulePatternValidator.ts +44 -0
  149. package/Server/Utils/OpenAPI.ts +2 -1
  150. package/Server/Utils/Runbook/RunbookExecutePermission.ts +94 -0
  151. package/Server/Utils/SessionReplay/SessionReplayErasureTombstone.ts +128 -0
  152. package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +586 -0
  153. package/Server/Utils/SessionReplay/SessionReplayGateCacheStore.ts +188 -0
  154. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +1449 -0
  155. package/Server/Utils/SessionReplay/SessionReplayRetention.ts +114 -0
  156. package/Server/Utils/SessionReplay/SessionReplayTargeting.ts +144 -0
  157. package/Server/Utils/SessionReplay/SessionReplayUsage.ts +92 -0
  158. package/Server/Utils/StartServer.ts +47 -3
  159. package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +44 -10
  160. package/Tests/App/Dashboard/AddWidgetModal.test.tsx +557 -0
  161. package/Tests/App/Dashboard/WidgetCatalog.test.ts +479 -0
  162. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +343 -0
  163. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +320 -0
  164. package/Tests/Models/AnalyticsModels/RumSessionSchema.test.ts +455 -0
  165. package/Tests/Models/AnalyticsModels/SessionIdCorrelation.test.ts +158 -0
  166. package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +447 -0
  167. package/Tests/Models/RunnerVersionLabel.test.ts +223 -0
  168. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +1287 -0
  169. package/Tests/Server/API/LegacyRunbookAgentRoutes.test.ts +117 -0
  170. package/Tests/Server/API/SessionReplayAPI.test.ts +2093 -0
  171. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +429 -0
  172. package/Tests/Server/API/UserSmsApi.test.ts +68 -2
  173. package/Tests/Server/DatabaseConfig.test.ts +150 -0
  174. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +2 -2
  175. package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +2 -3
  176. package/Tests/Server/Services/AIRunCodeFixClaimScoping.test.ts +100 -0
  177. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +8 -0
  178. package/Tests/Server/Services/AutoRemediationCommandRuleEngine.test.ts +334 -0
  179. package/Tests/Server/Services/AutoRemediationRuleEngineService.test.ts +517 -0
  180. package/Tests/Server/Services/BillingService.test.ts +158 -1
  181. package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +24 -2
  182. package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +17 -10
  183. package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +128 -0
  184. package/Tests/Server/Services/DatabaseServiceUpdateWriteRouting.test.ts +178 -0
  185. package/Tests/Server/Services/DatabaseServiceUpdateWriteRoutingMonitor.test.ts +206 -0
  186. package/Tests/Server/Services/MonitorServiceOperationalStatusSelection.test.ts +145 -0
  187. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +726 -0
  188. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +570 -9
  189. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +94 -1
  190. package/Tests/Server/Services/NetworkSiteService.test.ts +85 -0
  191. package/Tests/Server/Services/RumApplicationReplayHealth.test.ts +114 -0
  192. package/Tests/Server/Services/RunbookCredentialService.test.ts +657 -0
  193. package/Tests/Server/Services/SessionReplayCreatePath.test.ts +376 -0
  194. package/Tests/Server/Services/SessionReplayGateCacheInvalidation.test.ts +211 -0
  195. package/Tests/Server/Services/SessionReplayMetering.test.ts +174 -0
  196. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +555 -0
  197. package/Tests/Server/Services/TelemetryExceptionAIFixReadiness.test.ts +25 -4
  198. package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +17 -2
  199. package/Tests/Server/Services/TraceAggregationService.test.ts +48 -0
  200. package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +855 -0
  201. package/Tests/Server/Services/UpdateOneByIdKeepsRowId.test.ts +38 -27
  202. package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +44 -0
  203. package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +475 -0
  204. package/Tests/Server/Utils/AI/CodeFix/CodeFixAgentAuth.test.ts +257 -0
  205. package/Tests/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.test.ts +236 -0
  206. package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +44 -6
  207. package/Tests/Server/Utils/AI/CodeFixRunQueue.test.ts +47 -1
  208. package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +2 -2
  209. package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +294 -0
  210. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +2 -2
  211. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +47 -3
  212. package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +233 -0
  213. package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +463 -0
  214. package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
  215. package/Tests/Server/Utils/AI/RemediationAllowlistNormalization.test.ts +248 -0
  216. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +1008 -0
  217. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +887 -0
  218. package/Tests/Server/Utils/AI/RemediationHandoff.test.ts +306 -0
  219. package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +745 -0
  220. package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +291 -0
  221. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +1050 -0
  222. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +350 -0
  223. package/Tests/Server/Utils/AutoRemediation/RemediationVerifier.test.ts +341 -0
  224. package/Tests/Server/Utils/CorsOptions.test.ts +119 -0
  225. package/Tests/Server/Utils/Database/RelationIdUtil.test.ts +120 -0
  226. package/Tests/Server/Utils/Database/ResolveReferenceId.test.ts +60 -0
  227. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +337 -0
  228. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +671 -0
  229. package/Tests/Server/Utils/Monitor/MonitorSummaryCapture.test.ts +205 -0
  230. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +313 -0
  231. package/Tests/Server/Utils/PushNotificationUtil.test.ts +228 -0
  232. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +177 -0
  233. package/Tests/Server/Utils/SessionReplay/SessionReplayOriginAllowlist.test.ts +108 -0
  234. package/Tests/Server/Utils/SessionReplay/SessionReplayRetention.test.ts +229 -0
  235. package/Tests/Server/Utils/SessionReplay/SessionReplayTargeting.test.ts +246 -0
  236. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +110 -0
  237. package/Tests/Types/AI/AIRunStatus.test.ts +25 -0
  238. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +1063 -0
  239. package/Tests/Types/BaseDatabase/AggregationType.test.ts +56 -0
  240. package/Tests/Types/CustomField/CustomFieldDropdownOption.test.ts +227 -0
  241. package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +811 -0
  242. package/Tests/Types/Dashboard/RumDashboardTemplate.test.ts +1238 -0
  243. package/Tests/Types/Day/DayOfWeek.test.ts +46 -0
  244. package/Tests/Types/Docker/DockerInventoryExtractor.test.ts +249 -0
  245. package/Tests/Types/Kubernetes/KubernetesInventoryExtractor.test.ts +231 -0
  246. package/Tests/Types/Kubernetes/KubernetesRightSizing.test.ts +323 -0
  247. package/Tests/Types/Metrics/MetricDownsamplingRetentionDays.test.ts +77 -0
  248. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +42 -14
  249. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +2 -2
  250. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +3 -2
  251. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +1 -1
  252. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +6 -3
  253. package/Tests/Types/Monitor/RumAlertTemplates.test.ts +285 -0
  254. package/Tests/Types/Podman/PodmanInventoryExtractor.test.ts +159 -0
  255. package/Tests/Types/Runbook/RunbookExecutionDeadline.test.ts +268 -0
  256. package/Tests/Types/Runbook/RunbookStepType.test.ts +242 -0
  257. package/Tests/Types/Telemetry/TelemetryRetentionConfig.test.ts +225 -0
  258. package/Tests/Types/Text.test.ts +60 -0
  259. package/Tests/UI/Components/AutocompleteTextInputMenu.test.tsx +555 -0
  260. package/Tests/UI/Components/BulkLabelActions.test.tsx +1502 -0
  261. package/Tests/UI/Components/BulkOwnerActions.test.tsx +1255 -0
  262. package/Tests/UI/Components/CustomFields/DropdownOptionsInput.test.tsx +228 -0
  263. package/Tests/UI/Components/Detail/DropdownColors.test.tsx +128 -0
  264. package/Tests/UI/Components/Dropdown/DropdownValueBadge.test.tsx +60 -0
  265. package/Tests/UI/Components/FilterModalOperatorMenu.test.tsx +674 -0
  266. package/Tests/UI/Components/Forms/ColorPicker.test.tsx +48 -0
  267. package/Tests/UI/Components/Forms/ColorPickerPopup.test.tsx +222 -0
  268. package/Tests/UI/Components/Forms/IconPickerPopup.test.tsx +270 -0
  269. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +125 -6
  270. package/Tests/UI/Components/OperatorSelectorFilterTypes.test.tsx +1595 -0
  271. package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +851 -0
  272. package/Tests/UI/Components/OperatorSelectorMenu.test.tsx +1229 -0
  273. package/Tests/UI/Components/Pagination.test.tsx +85 -0
  274. package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +248 -0
  275. package/Tests/UI/Rum/ChunkLoader.test.ts +790 -0
  276. package/Tests/UI/Rum/ReplayScrubber.test.tsx +236 -0
  277. package/Tests/UI/Rum/ReplayStage.test.tsx +606 -0
  278. package/Tests/UI/Utils/Timezone.test.ts +86 -0
  279. package/Tests/UI/Utils/UseClockTick.test.tsx +276 -0
  280. package/Tests/Utils/AiRemediation/CommandPolicy.test.ts +1063 -0
  281. package/Tests/Utils/Dashboard/ClockWidgetFormat.test.ts +1374 -0
  282. package/Tests/Utils/Dashboard/DashboardClockComponent.test.ts +362 -0
  283. package/Tests/Utils/Dashboard/DashboardHtmlComponent.test.ts +217 -0
  284. package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +656 -0
  285. package/Tests/Utils/Dashboard/ValueWidgetLayout.test.ts +1007 -0
  286. package/Tests/Utils/Metrics/MetricSeriesScope.test.ts +1197 -0
  287. package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +839 -0
  288. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +69 -0
  289. package/Tests/Utils/Rules/RulePatternMatchUtil.test.ts +274 -0
  290. package/Tests/Utils/Rum/ChunkMath.test.ts +286 -0
  291. package/Tests/Utils/Rum/Masking.test.ts +186 -0
  292. package/Tests/Utils/Rum/SessionIdentity.test.ts +272 -0
  293. package/Tests/Utils/Rum/SessionSampling.test.ts +164 -0
  294. package/Tests/Utils/Rum/UrlScrubber.test.ts +175 -0
  295. package/Tests/Utils/StatusPage/Report.test.ts +708 -0
  296. package/Tests/Utils/ValueFormatter.test.ts +299 -1
  297. package/Types/AI/AIRunStatus.ts +18 -7
  298. package/Types/AI/AIRunType.ts +18 -0
  299. package/Types/AI/FixVerificationStatus.ts +21 -0
  300. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +16 -0
  301. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +304 -0
  302. package/Types/AutoRemediation/AutoRemediationExecutionMode.ts +17 -0
  303. package/Types/AutoRemediation/AutoRemediationSuggestionStatus.ts +35 -0
  304. package/Types/AutoRemediation/AutoRemediationSuggestionType.ts +17 -0
  305. package/Types/AutoRemediation/AutoRemediationTriggerEntity.ts +11 -0
  306. package/Types/AutoRemediation/AutoRemediationVerificationStatus.ts +21 -0
  307. package/Types/CustomField/CustomFieldDropdownOption.ts +190 -0
  308. package/Types/Dashboard/DashboardComponentType.ts +2 -0
  309. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +4 -0
  310. package/Types/Dashboard/DashboardComponents/DashboardClockComponent.ts +45 -0
  311. package/Types/Dashboard/DashboardComponents/DashboardHtmlComponent.ts +27 -0
  312. package/Types/Dashboard/DashboardComponents/DashboardValueComponent.ts +8 -0
  313. package/Types/Dashboard/DashboardTemplates.ts +516 -0
  314. package/Types/Date.ts +6 -0
  315. package/Types/Email/EmailTemplateType.ts +2 -0
  316. package/Types/Kubernetes/KubernetesRightSizing.ts +353 -0
  317. package/Types/MeteredPlan/ProductType.ts +1 -0
  318. package/Types/Monitor/MonitorStepMetricMonitor.ts +27 -1
  319. package/Types/Monitor/MonitorSteps.ts +5 -0
  320. package/Types/Monitor/MonitorSummarySnapshot.ts +88 -0
  321. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +52 -10
  322. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +7 -5
  323. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +101 -20
  324. package/Types/Monitor/RumAlertTemplates.ts +386 -0
  325. package/Types/Permission.ts +204 -24
  326. package/Types/Rum/SessionReplay.ts +452 -0
  327. package/Types/Rum/SessionReplayCaptureTrigger.ts +26 -0
  328. package/Types/Rum/SessionReplayConsentMode.ts +27 -0
  329. package/Types/Rum/SessionReplayMaskingMode.ts +86 -0
  330. package/Types/Rum/SessionReplayTriggerReason.ts +31 -0
  331. package/Types/Runbook/RunbookCredentialType.ts +6 -0
  332. package/Types/Runbook/RunbookStep.ts +66 -1
  333. package/Types/Runbook/RunbookStepType.ts +26 -0
  334. package/Types/Runbook/RunnerJobOrigin.ts +20 -0
  335. package/Types/Runbook/{RunbookAgentJobStatus.ts → RunnerJobStatus.ts} +2 -2
  336. package/Types/StatusPage/StatusPageReport.ts +99 -0
  337. package/Types/Telemetry/TelemetryRetentionConfig.ts +18 -1
  338. package/Types/Text.ts +33 -0
  339. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +260 -75
  340. package/UI/Components/BulkUpdate/BulkLabelActions.tsx +99 -9
  341. package/UI/Components/BulkUpdate/BulkOwnerActions.tsx +11 -0
  342. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +19 -14
  343. package/UI/Components/CustomFields/DropdownOptionsInput.tsx +144 -54
  344. package/UI/Components/Detail/Detail.tsx +9 -22
  345. package/UI/Components/Dropdown/Dropdown.tsx +2 -5
  346. package/UI/Components/Dropdown/DropdownMenuZIndex.ts +7 -0
  347. package/UI/Components/Dropdown/DropdownValueBadge.tsx +61 -0
  348. package/UI/Components/Filters/OperatorSelector.tsx +350 -39
  349. package/UI/Components/Forms/Fields/ColorPicker.tsx +60 -27
  350. package/UI/Components/Forms/Fields/IconPicker.tsx +89 -60
  351. package/UI/Components/Forms/Validation.ts +9 -4
  352. package/UI/Components/List/List.tsx +1 -0
  353. package/UI/Components/ModelTable/CustomFieldColumns.tsx +41 -32
  354. package/UI/Components/Pagination/Pagination.tsx +33 -10
  355. package/UI/Components/Table/Table.tsx +1 -0
  356. package/UI/Types/UseAnchoredFieldPopup.ts +321 -0
  357. package/UI/Utils/Dropdown.ts +26 -0
  358. package/UI/Utils/Timezone.ts +18 -2
  359. package/UI/Utils/UseClockTick.ts +78 -0
  360. package/Utils/AiRemediation/CommandPolicy.ts +398 -0
  361. package/Utils/Dashboard/ClockWidgetFormat.ts +604 -0
  362. package/Utils/Dashboard/Components/DashboardClockComponent.ts +181 -0
  363. package/Utils/Dashboard/Components/DashboardHtmlComponent.ts +162 -0
  364. package/Utils/Dashboard/Components/DashboardValueComponent.ts +12 -1
  365. package/Utils/Dashboard/Components/Index.ts +14 -0
  366. package/Utils/Dashboard/HtmlWidgetDocument.ts +309 -0
  367. package/Utils/Dashboard/ValueWidgetLayout.ts +471 -0
  368. package/Utils/Metrics/MetricSeriesScope.ts +301 -0
  369. package/Utils/Monitor/MonitorSummarySnapshotUtil.ts +593 -0
  370. package/Utils/NetworkSite/CidrMatchUtil.ts +30 -17
  371. package/Utils/Rules/RulePatternMatchUtil.ts +103 -0
  372. package/Utils/Rum/ChunkMath.ts +211 -0
  373. package/Utils/Rum/Masking.ts +168 -0
  374. package/Utils/Rum/SessionIdentity.ts +230 -0
  375. package/Utils/Rum/SessionSampling.ts +108 -0
  376. package/Utils/Rum/UrlScrubber.ts +185 -0
  377. package/Utils/Schema/ModelSchema.ts +27 -3
  378. package/Utils/StatusPage/Report.ts +304 -0
  379. package/Utils/ValueFormatter.ts +300 -54
  380. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +63 -0
  381. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
  382. package/build/dist/Models/AnalyticsModels/Index.js +10 -0
  383. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  384. package/build/dist/Models/AnalyticsModels/Log.js +56 -0
  385. package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
  386. package/build/dist/Models/AnalyticsModels/RumSession.js +1159 -0
  387. package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -0
  388. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js +670 -0
  389. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js.map +1 -0
  390. package/build/dist/Models/AnalyticsModels/Span.js +56 -0
  391. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  392. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js +54 -0
  393. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js.map +1 -1
  394. package/build/dist/Models/DatabaseModels/AIRun.js +32 -0
  395. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  396. package/build/dist/Models/DatabaseModels/Alert.js +30 -0
  397. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  398. package/build/dist/Models/DatabaseModels/AlertCustomField.js +1 -1
  399. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
  400. package/build/dist/Models/DatabaseModels/AlertFeed.js +1 -0
  401. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  402. package/build/dist/Models/DatabaseModels/AutoRemediationRule.js +998 -0
  403. package/build/dist/Models/DatabaseModels/AutoRemediationRule.js.map +1 -0
  404. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +917 -0
  405. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -0
  406. package/build/dist/Models/DatabaseModels/CodeRepository.js +132 -0
  407. package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
  408. package/build/dist/Models/DatabaseModels/GlobalConfig.js +327 -0
  409. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  410. package/build/dist/Models/DatabaseModels/Incident.js +30 -0
  411. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  412. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +1 -1
  413. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  414. package/build/dist/Models/DatabaseModels/IncidentFeed.js +1 -0
  415. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  416. package/build/dist/Models/DatabaseModels/Index.js +20 -8
  417. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  418. package/build/dist/Models/DatabaseModels/InstanceHealthLog.js +8 -0
  419. package/build/dist/Models/DatabaseModels/InstanceHealthLog.js.map +1 -1
  420. package/build/dist/Models/DatabaseModels/MonitorCustomField.js +1 -1
  421. package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
  422. package/build/dist/Models/DatabaseModels/MonitorStatus.js +1 -1
  423. package/build/dist/Models/DatabaseModels/MonitorStatus.js.map +1 -1
  424. package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js +2 -2
  425. package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js.map +1 -1
  426. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js +2 -2
  427. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js.map +1 -1
  428. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +1 -1
  429. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
  430. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +1 -1
  431. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
  432. package/build/dist/Models/DatabaseModels/Project.js +235 -0
  433. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  434. package/build/dist/Models/DatabaseModels/RumApplication.js +930 -0
  435. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  436. package/build/dist/Models/DatabaseModels/RumSessionErasureRequest.js +591 -0
  437. package/build/dist/Models/DatabaseModels/RumSessionErasureRequest.js.map +1 -0
  438. package/build/dist/Models/DatabaseModels/RumSessionPin.js +483 -0
  439. package/build/dist/Models/DatabaseModels/RumSessionPin.js.map +1 -0
  440. package/build/dist/Models/DatabaseModels/RumSessionReplayView.js +433 -0
  441. package/build/dist/Models/DatabaseModels/RumSessionReplayView.js.map +1 -0
  442. package/build/dist/Models/DatabaseModels/RunbookCredential.js +693 -0
  443. package/build/dist/Models/DatabaseModels/RunbookCredential.js.map +1 -0
  444. package/build/dist/Models/DatabaseModels/RunbookSecret.js +8 -8
  445. package/build/dist/Models/DatabaseModels/RunbookSecret.js.map +1 -1
  446. package/build/dist/Models/DatabaseModels/{RunbookAgent.js → Runner.js} +235 -70
  447. package/build/dist/Models/DatabaseModels/Runner.js.map +1 -0
  448. package/build/dist/Models/DatabaseModels/{RunbookAgentJob.js → RunnerJob.js} +173 -40
  449. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -0
  450. package/build/dist/Models/DatabaseModels/{RunbookAgentOwnerTeam.js → RunnerOwnerTeam.js} +57 -57
  451. package/build/dist/Models/DatabaseModels/RunnerOwnerTeam.js.map +1 -0
  452. package/build/dist/Models/DatabaseModels/{RunbookAgentOwnerUser.js → RunnerOwnerUser.js} +57 -57
  453. package/build/dist/Models/DatabaseModels/RunnerOwnerUser.js.map +1 -0
  454. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +1 -1
  455. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
  456. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +1 -1
  457. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
  458. package/build/dist/Models/DatabaseModels/TeamCustomField.js +1 -1
  459. package/build/dist/Models/DatabaseModels/TeamCustomField.js.map +1 -1
  460. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +1 -1
  461. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
  462. package/build/dist/Server/API/AIAgentDataAPI.js +130 -45
  463. package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
  464. package/build/dist/Server/API/AIAgentTaskAPI.js +26 -36
  465. package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
  466. package/build/dist/Server/API/AIAgentTaskLogAPI.js +11 -28
  467. package/build/dist/Server/API/AIAgentTaskLogAPI.js.map +1 -1
  468. package/build/dist/Server/API/AutoRemediationAPI.js +416 -0
  469. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -0
  470. package/build/dist/Server/API/BaseAnalyticsAPI.js +4 -1
  471. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  472. package/build/dist/Server/API/CommonAPI.js +24 -0
  473. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  474. package/build/dist/Server/API/DashboardAPI.js +265 -6
  475. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  476. package/build/dist/Server/API/TelemetryAPI.js +940 -3
  477. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  478. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +18 -0
  479. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  480. package/build/dist/Server/DatabaseConfig.js +23 -4
  481. package/build/dist/Server/DatabaseConfig.js.map +1 -1
  482. package/build/dist/Server/EnvironmentConfig.js +8 -0
  483. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  484. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785417351021-AddSessionReplay.js +106 -0
  485. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785417351021-AddSessionReplay.js.map +1 -0
  486. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785491583874-EnableSessionReplayByDefault.js +37 -0
  487. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785491583874-EnableSessionReplayByDefault.js.map +1 -0
  488. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785496223183-AddMonitorSummaryToIncidentAndAlert.js +18 -0
  489. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785496223183-AddMonitorSummaryToIncidentAndAlert.js.map +1 -0
  490. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785516996695-AddSessionReplayReliabilityColumns.js +29 -0
  491. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785516996695-AddSessionReplayReliabilityColumns.js.map +1 -0
  492. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785533806494-AddSessionReplayCorrelationColumns.js +35 -0
  493. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785533806494-AddSessionReplayCorrelationColumns.js.map +1 -0
  494. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785749674203-AddRedisAndPostgresHealthNotificationColumns.js +40 -0
  495. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785749674203-AddRedisAndPostgresHealthNotificationColumns.js.map +1 -0
  496. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785763818197-AddAutoRemediation.js +128 -0
  497. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785763818197-AddAutoRemediation.js.map +1 -0
  498. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785768089408-AddRemediationVerification.js +28 -0
  499. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785768089408-AddRemediationVerification.js.map +1 -0
  500. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785776960660-AddRunnerCapabilities.js +14 -0
  501. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785776960660-AddRunnerCapabilities.js.map +1 -0
  502. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785790000000-AddIncidentInvestigationGating.js +27 -0
  503. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785790000000-AddIncidentInvestigationGating.js.map +1 -0
  504. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785800000000-AddRunbookCredential.js +44 -0
  505. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785800000000-AddRunbookCredential.js.map +1 -0
  506. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785810000000-RenameRunbookAgentToRunner.js +88 -0
  507. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785810000000-RenameRunbookAgentToRunner.js.map +1 -0
  508. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785860000000-SessionReplayDefaultToSensitiveInputMasking.js +59 -0
  509. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785860000000-SessionReplayDefaultToSensitiveInputMasking.js.map +1 -0
  510. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785870000000-AddAiCommandRemediation.js +76 -0
  511. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785870000000-AddAiCommandRemediation.js.map +1 -0
  512. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785880000000-AlignRunnerSchemaWithEntities.js +214 -0
  513. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785880000000-AlignRunnerSchemaWithEntities.js.map +1 -0
  514. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785890000000-AddFixVerificationAndAutomaticCodeFixes.js +44 -0
  515. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785890000000-AddFixVerificationAndAutomaticCodeFixes.js.map +1 -0
  516. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +32 -0
  517. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  518. package/build/dist/Server/Services/AIRunService.js +1 -4
  519. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  520. package/build/dist/Server/Services/AIService.js +26 -0
  521. package/build/dist/Server/Services/AIService.js.map +1 -1
  522. package/build/dist/Server/Services/AlertService.js +37 -4
  523. package/build/dist/Server/Services/AlertService.js.map +1 -1
  524. package/build/dist/Server/Services/AlertSeverityService.js +24 -11
  525. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  526. package/build/dist/Server/Services/AlertStateService.js +24 -11
  527. package/build/dist/Server/Services/AlertStateService.js.map +1 -1
  528. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +917 -0
  529. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -0
  530. package/build/dist/Server/Services/{RunbookAgentOwnerTeamService.js → AutoRemediationRuleService.js} +2 -2
  531. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -0
  532. package/build/dist/Server/Services/AutoRemediationSuggestionService.js +127 -0
  533. package/build/dist/Server/Services/AutoRemediationSuggestionService.js.map +1 -0
  534. package/build/dist/Server/Services/BillingService.js +45 -1
  535. package/build/dist/Server/Services/BillingService.js.map +1 -1
  536. package/build/dist/Server/Services/DatabaseService.js +72 -4
  537. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  538. package/build/dist/Server/Services/IncidentService.js +52 -4
  539. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  540. package/build/dist/Server/Services/IncidentSeverityService.js +24 -11
  541. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  542. package/build/dist/Server/Services/IncidentStateService.js +24 -11
  543. package/build/dist/Server/Services/IncidentStateService.js.map +1 -1
  544. package/build/dist/Server/Services/Index.js +18 -0
  545. package/build/dist/Server/Services/Index.js.map +1 -1
  546. package/build/dist/Server/Services/MonitorService.js +24 -0
  547. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  548. package/build/dist/Server/Services/MonitorStatusService.js +25 -11
  549. package/build/dist/Server/Services/MonitorStatusService.js.map +1 -1
  550. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +12 -11
  551. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  552. package/build/dist/Server/Services/NetworkDeviceLabelRuleService.js +43 -0
  553. package/build/dist/Server/Services/NetworkDeviceLabelRuleService.js.map +1 -1
  554. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +12 -11
  555. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  556. package/build/dist/Server/Services/NetworkDeviceOwnerRuleService.js +41 -0
  557. package/build/dist/Server/Services/NetworkDeviceOwnerRuleService.js.map +1 -1
  558. package/build/dist/Server/Services/NetworkDeviceService.js +129 -20
  559. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  560. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +67 -10
  561. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -1
  562. package/build/dist/Server/Services/NetworkSiteService.js +19 -8
  563. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  564. package/build/dist/Server/Services/ProjectService.js +43 -0
  565. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  566. package/build/dist/Server/Services/RumApplicationService.js +202 -0
  567. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  568. package/build/dist/Server/Services/RumSessionChunkService.js +9 -0
  569. package/build/dist/Server/Services/RumSessionChunkService.js.map +1 -0
  570. package/build/dist/Server/Services/RumSessionErasureRequestService.js +190 -0
  571. package/build/dist/Server/Services/RumSessionErasureRequestService.js.map +1 -0
  572. package/build/dist/Server/Services/RumSessionPinService.js +208 -0
  573. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -0
  574. package/build/dist/Server/Services/RumSessionReplayViewService.js +180 -0
  575. package/build/dist/Server/Services/RumSessionReplayViewService.js.map +1 -0
  576. package/build/dist/Server/Services/RumSessionService.js +102 -0
  577. package/build/dist/Server/Services/RumSessionService.js.map +1 -0
  578. package/build/dist/Server/Services/RunbookCredentialService.js +67 -0
  579. package/build/dist/Server/Services/RunbookCredentialService.js.map +1 -0
  580. package/build/dist/Server/Services/{RunbookAgentJobService.js → RunnerJobService.js} +158 -46
  581. package/build/dist/Server/Services/RunnerJobService.js.map +1 -0
  582. package/build/dist/Server/Services/{RunbookAgentOwnerUserService.js → RunnerOwnerTeamService.js} +2 -2
  583. package/build/dist/Server/Services/RunnerOwnerTeamService.js.map +1 -0
  584. package/build/dist/Server/Services/RunnerOwnerUserService.js +9 -0
  585. package/build/dist/Server/Services/RunnerOwnerUserService.js.map +1 -0
  586. package/build/dist/Server/Services/RunnerService.js +168 -0
  587. package/build/dist/Server/Services/RunnerService.js.map +1 -0
  588. package/build/dist/Server/Services/ScheduledMaintenanceStateService.js +24 -11
  589. package/build/dist/Server/Services/ScheduledMaintenanceStateService.js.map +1 -1
  590. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +15 -1
  591. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  592. package/build/dist/Server/Services/ServiceService.js +8 -2
  593. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  594. package/build/dist/Server/Services/StatusPageService.js +173 -16
  595. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  596. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +17 -1
  597. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  598. package/build/dist/Server/Services/TelemetryExceptionService.js +3 -16
  599. package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
  600. package/build/dist/Server/Services/TelemetryUsageBillingService.js +31 -3
  601. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  602. package/build/dist/Server/Services/TraceAggregationService.js +106 -2
  603. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  604. package/build/dist/Server/Types/Billing/MeteredPlan/AllMeteredPlans.js +16 -0
  605. package/build/dist/Server/Types/Billing/MeteredPlan/AllMeteredPlans.js.map +1 -1
  606. package/build/dist/Server/Types/Billing/MeteredPlan/ServerMeteredPlan.js +9 -0
  607. package/build/dist/Server/Types/Billing/MeteredPlan/ServerMeteredPlan.js.map +1 -1
  608. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +38 -6
  609. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  610. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js +104 -0
  611. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js.map +1 -0
  612. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.js +54 -0
  613. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.js.map +1 -0
  614. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +11 -7
  615. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  616. package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js +3 -4
  617. package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js.map +1 -1
  618. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +724 -0
  619. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -0
  620. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +668 -0
  621. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -0
  622. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +657 -0
  623. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -0
  624. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +52 -7
  625. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  626. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +53 -5
  627. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  628. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +25 -6
  629. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
  630. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +131 -17
  631. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
  632. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +200 -5
  633. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  634. package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js +2 -7
  635. package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js.map +1 -1
  636. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +4 -17
  637. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
  638. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +203 -19
  639. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  640. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +89 -0
  641. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -0
  642. package/build/dist/Server/Utils/AI/SRE/RemediationHandoff.js +82 -0
  643. package/build/dist/Server/Utils/AI/SRE/RemediationHandoff.js.map +1 -0
  644. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +4 -19
  645. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
  646. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +2 -2
  647. package/build/dist/Server/Utils/Alert/AlertPrivacyFilter.js +36 -0
  648. package/build/dist/Server/Utils/Alert/AlertPrivacyFilter.js.map +1 -1
  649. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +498 -0
  650. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -0
  651. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +492 -0
  652. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -0
  653. package/build/dist/Server/Utils/CorsOptions.js +47 -0
  654. package/build/dist/Server/Utils/CorsOptions.js.map +1 -0
  655. package/build/dist/Server/Utils/Database/RelationIdUtil.js +51 -0
  656. package/build/dist/Server/Utils/Database/RelationIdUtil.js.map +1 -0
  657. package/build/dist/Server/Utils/Incident/IncidentPrivacyFilter.js +38 -0
  658. package/build/dist/Server/Utils/Incident/IncidentPrivacyFilter.js.map +1 -1
  659. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +194 -0
  660. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +1 -0
  661. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +292 -0
  662. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -0
  663. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +9 -0
  664. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  665. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +9 -0
  666. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  667. package/build/dist/Server/Utils/Monitor/MonitorResource.js +16 -0
  668. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  669. package/build/dist/Server/Utils/Monitor/MonitorSummaryCapture.js +92 -0
  670. package/build/dist/Server/Utils/Monitor/MonitorSummaryCapture.js.map +1 -0
  671. package/build/dist/Server/Utils/NetworkDevice/RulePatternValidator.js +27 -0
  672. package/build/dist/Server/Utils/NetworkDevice/RulePatternValidator.js.map +1 -0
  673. package/build/dist/Server/Utils/OpenAPI.js +2 -1
  674. package/build/dist/Server/Utils/OpenAPI.js.map +1 -1
  675. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js +67 -0
  676. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js.map +1 -0
  677. package/build/dist/Server/Utils/SessionReplay/SessionReplayErasureTombstone.js +98 -0
  678. package/build/dist/Server/Utils/SessionReplay/SessionReplayErasureTombstone.js.map +1 -0
  679. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +378 -0
  680. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -0
  681. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js +137 -0
  682. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js.map +1 -0
  683. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +998 -0
  684. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -0
  685. package/build/dist/Server/Utils/SessionReplay/SessionReplayRetention.js +59 -0
  686. package/build/dist/Server/Utils/SessionReplay/SessionReplayRetention.js.map +1 -0
  687. package/build/dist/Server/Utils/SessionReplay/SessionReplayTargeting.js +98 -0
  688. package/build/dist/Server/Utils/SessionReplay/SessionReplayTargeting.js.map +1 -0
  689. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +69 -0
  690. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -0
  691. package/build/dist/Server/Utils/StartServer.js +40 -3
  692. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  693. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +27 -6
  694. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -1
  695. package/build/dist/Types/AI/AIRunStatus.js +17 -5
  696. package/build/dist/Types/AI/AIRunStatus.js.map +1 -1
  697. package/build/dist/Types/AI/AIRunType.js +18 -0
  698. package/build/dist/Types/AI/AIRunType.js.map +1 -1
  699. package/build/dist/Types/AI/FixVerificationStatus.js +22 -0
  700. package/build/dist/Types/AI/FixVerificationStatus.js.map +1 -0
  701. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +16 -0
  702. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  703. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +192 -0
  704. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -0
  705. package/build/dist/Types/AutoRemediation/AutoRemediationExecutionMode.js +18 -0
  706. package/build/dist/Types/AutoRemediation/AutoRemediationExecutionMode.js.map +1 -0
  707. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionStatus.js +31 -0
  708. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionStatus.js.map +1 -0
  709. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionType.js +18 -0
  710. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionType.js.map +1 -0
  711. package/build/dist/Types/AutoRemediation/AutoRemediationTriggerEntity.js +12 -0
  712. package/build/dist/Types/AutoRemediation/AutoRemediationTriggerEntity.js.map +1 -0
  713. package/build/dist/Types/AutoRemediation/AutoRemediationVerificationStatus.js +22 -0
  714. package/build/dist/Types/AutoRemediation/AutoRemediationVerificationStatus.js.map +1 -0
  715. package/build/dist/Types/CustomField/CustomFieldDropdownOption.js +110 -0
  716. package/build/dist/Types/CustomField/CustomFieldDropdownOption.js.map +1 -0
  717. package/build/dist/Types/Dashboard/DashboardComponentType.js +2 -0
  718. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  719. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +4 -0
  720. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  721. package/build/dist/Types/Dashboard/DashboardComponents/DashboardClockComponent.js +19 -0
  722. package/build/dist/Types/Dashboard/DashboardComponents/DashboardClockComponent.js.map +1 -0
  723. package/build/dist/Types/Dashboard/DashboardComponents/DashboardHtmlComponent.js +2 -0
  724. package/build/dist/Types/Dashboard/DashboardComponents/DashboardHtmlComponent.js.map +1 -0
  725. package/build/dist/Types/Dashboard/DashboardTemplates.js +487 -0
  726. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  727. package/build/dist/Types/Date.js +6 -0
  728. package/build/dist/Types/Date.js.map +1 -1
  729. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  730. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  731. package/build/dist/Types/Kubernetes/KubernetesRightSizing.js +229 -0
  732. package/build/dist/Types/Kubernetes/KubernetesRightSizing.js.map +1 -0
  733. package/build/dist/Types/MeteredPlan/ProductType.js +1 -0
  734. package/build/dist/Types/MeteredPlan/ProductType.js.map +1 -1
  735. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +12 -2
  736. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
  737. package/build/dist/Types/Monitor/MonitorSteps.js +5 -0
  738. package/build/dist/Types/Monitor/MonitorSteps.js.map +1 -1
  739. package/build/dist/Types/Monitor/MonitorSummarySnapshot.js +13 -0
  740. package/build/dist/Types/Monitor/MonitorSummarySnapshot.js.map +1 -0
  741. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +40 -8
  742. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  743. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +4 -3
  744. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  745. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +50 -10
  746. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  747. package/build/dist/Types/Monitor/RumAlertTemplates.js +297 -0
  748. package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -0
  749. package/build/dist/Types/Permission.js +184 -24
  750. package/build/dist/Types/Permission.js.map +1 -1
  751. package/build/dist/Types/Rum/SessionReplay.js +155 -0
  752. package/build/dist/Types/Rum/SessionReplay.js.map +1 -0
  753. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js +26 -0
  754. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js.map +1 -0
  755. package/build/dist/Types/Rum/SessionReplayConsentMode.js +27 -0
  756. package/build/dist/Types/Rum/SessionReplayConsentMode.js.map +1 -0
  757. package/build/dist/Types/Rum/SessionReplayMaskingMode.js +79 -0
  758. package/build/dist/Types/Rum/SessionReplayMaskingMode.js.map +1 -0
  759. package/build/dist/Types/Rum/SessionReplayTriggerReason.js +28 -0
  760. package/build/dist/Types/Rum/SessionReplayTriggerReason.js.map +1 -0
  761. package/build/dist/Types/Runbook/RunbookCredentialType.js +7 -0
  762. package/build/dist/Types/Runbook/RunbookCredentialType.js.map +1 -0
  763. package/build/dist/Types/Runbook/RunbookStep.js +20 -1
  764. package/build/dist/Types/Runbook/RunbookStep.js.map +1 -1
  765. package/build/dist/Types/Runbook/RunbookStepType.js +24 -0
  766. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  767. package/build/dist/Types/Runbook/RunnerJobOrigin.js +21 -0
  768. package/build/dist/Types/Runbook/RunnerJobOrigin.js.map +1 -0
  769. package/build/dist/Types/Runbook/RunnerJobStatus.js +22 -0
  770. package/build/dist/Types/Runbook/RunnerJobStatus.js.map +1 -0
  771. package/build/dist/Types/StatusPage/StatusPageReport.js +22 -0
  772. package/build/dist/Types/StatusPage/StatusPageReport.js.map +1 -0
  773. package/build/dist/Types/Telemetry/TelemetryRetentionConfig.js.map +1 -1
  774. package/build/dist/Types/Text.js +29 -0
  775. package/build/dist/Types/Text.js.map +1 -1
  776. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +143 -28
  777. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  778. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +82 -9
  779. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
  780. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js +11 -0
  781. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js.map +1 -1
  782. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +11 -13
  783. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  784. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js +76 -45
  785. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js.map +1 -1
  786. package/build/dist/UI/Components/Detail/Detail.js +3 -8
  787. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  788. package/build/dist/UI/Components/Dropdown/Dropdown.js +2 -5
  789. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  790. package/build/dist/UI/Components/Dropdown/DropdownMenuZIndex.js +7 -0
  791. package/build/dist/UI/Components/Dropdown/DropdownMenuZIndex.js.map +1 -0
  792. package/build/dist/UI/Components/Dropdown/DropdownValueBadge.js +32 -0
  793. package/build/dist/UI/Components/Dropdown/DropdownValueBadge.js.map +1 -0
  794. package/build/dist/UI/Components/Filters/OperatorSelector.js +210 -20
  795. package/build/dist/UI/Components/Filters/OperatorSelector.js.map +1 -1
  796. package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +26 -10
  797. package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
  798. package/build/dist/UI/Components/Forms/Fields/IconPicker.js +28 -13
  799. package/build/dist/UI/Components/Forms/Fields/IconPicker.js.map +1 -1
  800. package/build/dist/UI/Components/Forms/Validation.js +9 -5
  801. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  802. package/build/dist/UI/Components/List/List.js +1 -1
  803. package/build/dist/UI/Components/List/List.js.map +1 -1
  804. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +21 -19
  805. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
  806. package/build/dist/UI/Components/Pagination/Pagination.js +14 -3
  807. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  808. package/build/dist/UI/Components/Table/Table.js +1 -1
  809. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  810. package/build/dist/UI/Types/UseAnchoredFieldPopup.js +197 -0
  811. package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -0
  812. package/build/dist/UI/Utils/Dropdown.js +18 -0
  813. package/build/dist/UI/Utils/Dropdown.js.map +1 -1
  814. package/build/dist/UI/Utils/Timezone.js +13 -2
  815. package/build/dist/UI/Utils/Timezone.js.map +1 -1
  816. package/build/dist/UI/Utils/UseClockTick.js +41 -0
  817. package/build/dist/UI/Utils/UseClockTick.js.map +1 -0
  818. package/build/dist/Utils/AiRemediation/CommandPolicy.js +303 -0
  819. package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -0
  820. package/build/dist/Utils/Dashboard/ClockWidgetFormat.js +232 -0
  821. package/build/dist/Utils/Dashboard/ClockWidgetFormat.js.map +1 -0
  822. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js +146 -0
  823. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js.map +1 -0
  824. package/build/dist/Utils/Dashboard/Components/DashboardHtmlComponent.js +133 -0
  825. package/build/dist/Utils/Dashboard/Components/DashboardHtmlComponent.js.map +1 -0
  826. package/build/dist/Utils/Dashboard/Components/DashboardValueComponent.js +10 -1
  827. package/build/dist/Utils/Dashboard/Components/DashboardValueComponent.js.map +1 -1
  828. package/build/dist/Utils/Dashboard/Components/Index.js +8 -0
  829. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  830. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +198 -0
  831. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -0
  832. package/build/dist/Utils/Dashboard/ValueWidgetLayout.js +276 -0
  833. package/build/dist/Utils/Dashboard/ValueWidgetLayout.js.map +1 -0
  834. package/build/dist/Utils/Metrics/MetricSeriesScope.js +203 -0
  835. package/build/dist/Utils/Metrics/MetricSeriesScope.js.map +1 -0
  836. package/build/dist/Utils/Monitor/MonitorSummarySnapshotUtil.js +382 -0
  837. package/build/dist/Utils/Monitor/MonitorSummarySnapshotUtil.js.map +1 -0
  838. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +13 -7
  839. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
  840. package/build/dist/Utils/Rules/RulePatternMatchUtil.js +87 -0
  841. package/build/dist/Utils/Rules/RulePatternMatchUtil.js.map +1 -0
  842. package/build/dist/Utils/Rum/ChunkMath.js +147 -0
  843. package/build/dist/Utils/Rum/ChunkMath.js.map +1 -0
  844. package/build/dist/Utils/Rum/Masking.js +143 -0
  845. package/build/dist/Utils/Rum/Masking.js.map +1 -0
  846. package/build/dist/Utils/Rum/SessionIdentity.js +161 -0
  847. package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -0
  848. package/build/dist/Utils/Rum/SessionSampling.js +91 -0
  849. package/build/dist/Utils/Rum/SessionSampling.js.map +1 -0
  850. package/build/dist/Utils/Rum/UrlScrubber.js +144 -0
  851. package/build/dist/Utils/Rum/UrlScrubber.js.map +1 -0
  852. package/build/dist/Utils/Schema/ModelSchema.js +28 -3
  853. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  854. package/build/dist/Utils/StatusPage/Report.js +194 -0
  855. package/build/dist/Utils/StatusPage/Report.js.map +1 -0
  856. package/build/dist/Utils/ValueFormatter.js +239 -46
  857. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  858. package/jest.config.json +3 -0
  859. package/package.json +1 -1
  860. package/tsconfig.json +19 -1
  861. package/Server/Services/RunbookAgentService.ts +0 -93
  862. package/build/dist/Models/DatabaseModels/RunbookAgent.js.map +0 -1
  863. package/build/dist/Models/DatabaseModels/RunbookAgentJob.js.map +0 -1
  864. package/build/dist/Models/DatabaseModels/RunbookAgentOwnerTeam.js.map +0 -1
  865. package/build/dist/Models/DatabaseModels/RunbookAgentOwnerUser.js.map +0 -1
  866. package/build/dist/Server/Services/RunbookAgentJobService.js.map +0 -1
  867. package/build/dist/Server/Services/RunbookAgentOwnerTeamService.js.map +0 -1
  868. package/build/dist/Server/Services/RunbookAgentOwnerUserService.js.map +0 -1
  869. package/build/dist/Server/Services/RunbookAgentService.js +0 -91
  870. package/build/dist/Server/Services/RunbookAgentService.js.map +0 -1
  871. package/build/dist/Types/Runbook/RunbookAgentJobStatus.js +0 -22
  872. package/build/dist/Types/Runbook/RunbookAgentJobStatus.js.map +0 -1
@@ -0,0 +1,1449 @@
1
+ import { SQL, Statement } from "../AnalyticsDatabase/Statement";
2
+ import { getQuerySettings } from "../AnalyticsDatabase/QuerySettingsHelper";
3
+ import RumSessionService from "../../Services/RumSessionService";
4
+ import RumSessionChunkService from "../../Services/RumSessionChunkService";
5
+ import {
6
+ DbJSONResponse,
7
+ Results,
8
+ } from "../../Services/AnalyticsDatabaseService";
9
+ import AnalyticsTableName from "../../../Types/AnalyticsDatabase/AnalyticsTableName";
10
+ import TableColumnType from "../../../Types/AnalyticsDatabase/TableColumnType";
11
+ import Includes from "../../../Types/BaseDatabase/Includes";
12
+ import { JSONObject } from "../../../Types/JSON";
13
+ import ObjectID from "../../../Types/ObjectID";
14
+ import ChunkMath from "../../../Utils/Rum/ChunkMath";
15
+ import {
16
+ MAX_SESSION_REPLAY_CHUNKS_PER_READ,
17
+ MAX_SESSION_REPLAY_READ_BYTES,
18
+ SessionReplayChunkManifestEntry,
19
+ SessionReplayGap,
20
+ } from "../../../Types/Rum/SessionReplay";
21
+ import BadDataException from "../../../Types/Exception/BadDataException";
22
+ import CaptureSpan from "../Telemetry/CaptureSpan";
23
+
24
+ /*
25
+ * Bespoke ClickHouse reads for session-replay playback.
26
+ *
27
+ * Why this exists at all instead of BaseAnalyticsAPI / the generic ORM
28
+ * read path:
29
+ *
30
+ * 1. There is NO `FINAL` support anywhere in this repo — neither
31
+ * StatementGenerator nor AnalyticsDatabaseService ever emits it. Both
32
+ * replay tables are ReplacingMergeTree, so until a background merge
33
+ * runs a session is physically several rows: a provisional header
34
+ * written on chunk 0 and a finalized header written minutes later,
35
+ * plus one extra chunk row per retried delivery. A naive SELECT shows
36
+ * every one of them. That is worst for the NEWEST sessions, which are
37
+ * exactly the rows a session list sorts first. Every read here
38
+ * therefore collapses duplicates itself: `argMax(col, version)` over
39
+ * the replace key for the header table (the convention
40
+ * SloHistoryService documents), and `ORDER BY ... version DESC LIMIT
41
+ * 1 BY ...` for the chunk table where whole rows, not aggregates, are
42
+ * wanted.
43
+ *
44
+ * 2. `toFindStatement` clamps limit to LIMIT_PER_PROJECT, has no cursor,
45
+ * and runs with `timeout_overflow_mode = 'break'`, which returns
46
+ * PARTIAL RESULTS WITHOUT ERRORING. A silently short session list is
47
+ * merely annoying; a silently short chunk page renders a DOM the user
48
+ * never saw. Every statement here uses 'throw' instead.
49
+ *
50
+ * 3. The manifest read must never name the `payload` column, so
51
+ * ClickHouse never touches (and never decompresses) the only column
52
+ * in the system that holds a recording of a real person's screen.
53
+ * The byte-cap pre-check is the one exception, and it measures
54
+ * `length(payload)` inside ClickHouse without ever shipping the
55
+ * bytes: the cap has to bound the size of what is actually returned,
56
+ * and the only honest measure of that is the stored column itself.
57
+ *
58
+ * NOTE on aliases: ClickHouse substitutes SELECT aliases into same-level
59
+ * unqualified WHERE references, and an aggregate alias there is an
60
+ * ILLEGAL_AGGREGATION error. Every aggregate below is therefore aliased
61
+ * to a name that does NOT collide with a real column, so WHERE keeps
62
+ * referring to the physical column and HAVING/ORDER BY can safely use the
63
+ * alias.
64
+ */
65
+
66
+ /* Both replay tables carry retentionDate, so both reads need the filter. */
67
+ const RETENTION_FILTER: string = " AND retentionDate >= now()";
68
+
69
+ /*
70
+ * Wall-clock cap. 'throw' rather than 'break': see (2) above. 30s is well
71
+ * inside the App pool's 58s request_timeout, so a query that blows the
72
+ * budget surfaces as an error the player can retry rather than as a
73
+ * truncated recording.
74
+ */
75
+ const READ_QUERY_SETTINGS: string = getQuerySettings({
76
+ maxExecutionTimeInSeconds: 30,
77
+ timeoutOverflowMode: "throw",
78
+ });
79
+
80
+ /* Page sizes for the session list. */
81
+ export const DEFAULT_SESSION_REPLAY_LIST_LIMIT: number = 50;
82
+ export const MAX_SESSION_REPLAY_LIST_LIMIT: number = 200;
83
+
84
+ /* Sessions returned by the exception -> replay lookup. */
85
+ export const MAX_SESSION_REPLAY_FOR_EXCEPTION_LIMIT: number = 20;
86
+
87
+ /*
88
+ * Row ceiling on one manifest. A session is capped at
89
+ * MAX_SESSION_REPLAY_CHUNKS_PER_SESSION (480) chunks PER TAB, and a
90
+ * session can legitimately span several tabs, so the manifest is bounded
91
+ * separately. Hitting it is reported rather than silently truncating the
92
+ * timeline.
93
+ */
94
+ const MAX_MANIFEST_ROWS: number = 4096;
95
+
96
+ export interface SessionReplayListCursor {
97
+ /* Server-clamped session start of the last row of the previous page. */
98
+ startTimeUnixMs: number;
99
+ sessionId: string;
100
+ }
101
+
102
+ export interface SessionReplayListFilters {
103
+ hasError?: boolean | undefined;
104
+ /*
105
+ * Any frustration signal (rage/dead/error clicks, refresh rage).
106
+ * Server-side, so "frustration" filters the whole table — the old
107
+ * client-side version filtered only the fetched page, silently showing
108
+ * an empty list for a project whose frustrated sessions sat on page 2.
109
+ */
110
+ hasFrustration?: boolean | undefined;
111
+ isFinalized?: boolean | undefined;
112
+ triggerReasons?: Array<string> | undefined;
113
+ browserNames?: Array<string> | undefined;
114
+ osNames?: Array<string> | undefined;
115
+ deviceTypes?: Array<string> | undefined;
116
+ countryCodes?: Array<string> | undefined;
117
+ identifiedUserKey?: string | undefined;
118
+ /* "sessions that hit /checkout" - matches the routes array. */
119
+ route?: string | undefined;
120
+ minDurationMs?: number | undefined;
121
+ }
122
+
123
+ export interface SessionReplayListRequest {
124
+ projectId: ObjectID;
125
+ rumApplicationId: ObjectID;
126
+ startTime: Date;
127
+ endTime: Date;
128
+ filters: SessionReplayListFilters;
129
+ limit: number;
130
+ cursor?: SessionReplayListCursor | undefined;
131
+ /*
132
+ * The raw end-user identifier has its own, narrower column ACL than the
133
+ * rest of the header row. This raw-SQL path never invokes
134
+ * ModelPermission, so the caller decides column-by-column and the
135
+ * column is simply not named in the SELECT when it is not permitted.
136
+ */
137
+ includeIdentifiedUserLabel: boolean;
138
+ }
139
+
140
+ export interface SessionReplayListItem {
141
+ sessionId: string;
142
+ rumApplicationId: string;
143
+ startTime: Date;
144
+ endTime: Date;
145
+ durationMs: number;
146
+ isFinalized: boolean;
147
+ sealedReason: string;
148
+ chunkCount: number;
149
+ maxChunkIndex: number;
150
+ missingChunkCount: number;
151
+ eventCount: number;
152
+ payloadBytes: number;
153
+ hasError: boolean;
154
+ errorCount: number;
155
+ rageClickCount: number;
156
+ deadClickCount: number;
157
+ errorClickCount: number;
158
+ refreshRageCount: number;
159
+ pageCount: number;
160
+ triggerReason: string;
161
+ entryUrl: string;
162
+ exitUrl: string;
163
+ browserName: string;
164
+ browserVersion: string;
165
+ osName: string;
166
+ deviceType: string;
167
+ countryCode: string;
168
+ viewportWidth: number;
169
+ viewportHeight: number;
170
+ identifiedUserKey: string;
171
+ /* Present only when the caller holds the narrower identity permission. */
172
+ identifiedUserLabel?: string | undefined;
173
+ samplePercentageAtCapture: number;
174
+ }
175
+
176
+ export interface SessionReplayListResult {
177
+ sessions: Array<SessionReplayListItem>;
178
+ nextCursor: SessionReplayListCursor | null;
179
+ }
180
+
181
+ export interface SessionReplaySessionHeader {
182
+ sessionId: string;
183
+ projectId: string;
184
+ rumApplicationId: string;
185
+ startTime: Date;
186
+ endTime: Date;
187
+ durationMs: number;
188
+ isFinalized: boolean;
189
+ sealedReason: string;
190
+ chunkCount: number;
191
+ maxChunkIndex: number;
192
+ missingChunkCount: number;
193
+ eventCount: number;
194
+ payloadBytes: number;
195
+ hasError: boolean;
196
+ errorCount: number;
197
+ rageClickCount: number;
198
+ deadClickCount: number;
199
+ errorClickCount: number;
200
+ refreshRageCount: number;
201
+ pageCount: number;
202
+ triggerReason: string;
203
+ maskingMode: string;
204
+ consentState: string;
205
+ recorderKind: string;
206
+ recorderVersion: string;
207
+ rrwebVersion: string;
208
+ schemaVersion: number;
209
+ wireVersion: number;
210
+ entryUrl: string;
211
+ exitUrl: string;
212
+ routes: Array<string>;
213
+ browserName: string;
214
+ browserVersion: string;
215
+ osName: string;
216
+ deviceType: string;
217
+ countryCode: string;
218
+ viewportWidth: number;
219
+ viewportHeight: number;
220
+ fidelityNotices: Array<string>;
221
+ fullSnapshotChunkIndexes: Array<number>;
222
+ traceIds: Array<string>;
223
+ exceptionFingerprints: Array<string>;
224
+ clockSkewMs: number;
225
+ }
226
+
227
+ /*
228
+ * One tab's slice of the manifest. chunkIndex is minted PER TAB by the
229
+ * recorder (sessionStorage is copied on tab duplication, so two live tabs
230
+ * legitimately both start at 0), which means gap detection and seek
231
+ * anchors are only meaningful within a tab.
232
+ */
233
+ export interface SessionReplayManifestTab {
234
+ tabId: string;
235
+ chunks: Array<SessionReplayChunkManifestEntry>;
236
+ chunkIndexes: Array<number>;
237
+ fullSnapshotChunkIndexes: Array<number>;
238
+ gaps: Array<SessionReplayGap>;
239
+ maxChunkIndex: number;
240
+ totalPayloadBytes: number;
241
+ }
242
+
243
+ export interface SessionReplayManifest {
244
+ header: SessionReplaySessionHeader;
245
+ tabs: Array<SessionReplayManifestTab>;
246
+ /*
247
+ * True when the chunk index itself was cut short by MAX_MANIFEST_ROWS.
248
+ * Surfaced so the player can say the timeline is incomplete rather than
249
+ * presenting a short recording as a whole one.
250
+ */
251
+ isChunkIndexTruncated: boolean;
252
+ }
253
+
254
+ export interface SessionReplayChunkPayload {
255
+ chunkIndex: number;
256
+ payload: string;
257
+ }
258
+
259
+ export interface SessionReplayExceptionSession {
260
+ sessionId: string;
261
+ rumApplicationId: string;
262
+ startTime: Date;
263
+ endTime: Date;
264
+ durationMs: number;
265
+ hasError: boolean;
266
+ errorCount: number;
267
+ rageClickCount: number;
268
+ deadClickCount: number;
269
+ errorClickCount: number;
270
+ refreshRageCount: number;
271
+ maskingMode: string;
272
+ triggerReason: string;
273
+ entryUrl: string;
274
+ browserName: string;
275
+ osName: string;
276
+ deviceType: string;
277
+ isFinalized: boolean;
278
+ }
279
+
280
+ /*
281
+ * Header columns that are aggregated with argMax and their SELECT alias.
282
+ * Kept as data rather than a hand-written SELECT list so the list, header
283
+ * and exception-lookup queries cannot drift apart on which columns they
284
+ * de-duplicate.
285
+ *
286
+ * `expression` wraps 64-bit and 128-bit columns in toFloat64: the
287
+ * ClickHouse JSON format quotes Int64/UInt64/Int128 as strings by
288
+ * default, and unix-millisecond and byte-count magnitudes are far inside
289
+ * Float64's exact-integer range.
290
+ */
291
+ interface AggregatedColumn {
292
+ alias: string;
293
+ expression: string;
294
+ }
295
+
296
+ function argMaxColumn(column: string): string {
297
+ return `argMax(${column}, version)`;
298
+ }
299
+
300
+ function argMaxNumeric(column: string): string {
301
+ return `toFloat64(${argMaxColumn(column)})`;
302
+ }
303
+
304
+ function argMaxDateTime(column: string): string {
305
+ return `toFloat64(toUnixTimestamp64Milli(${argMaxColumn(column)}))`;
306
+ }
307
+
308
+ /*
309
+ * Aliases deliberately differ from the physical column names. See the
310
+ * ILLEGAL_AGGREGATION note in the file header.
311
+ */
312
+ const HEADER_AGGREGATES: Array<AggregatedColumn> = [
313
+ { alias: "aggStartTime", expression: argMaxDateTime("startTime") },
314
+ { alias: "aggEndTime", expression: argMaxDateTime("endTime") },
315
+ { alias: "aggDurationMs", expression: argMaxNumeric("durationMs") },
316
+ { alias: "aggIsFinalized", expression: argMaxColumn("isFinalized") },
317
+ { alias: "aggSealedReason", expression: argMaxColumn("sealedReason") },
318
+ { alias: "aggChunkCount", expression: argMaxNumeric("chunkCount") },
319
+ { alias: "aggMaxChunkIndex", expression: argMaxNumeric("maxChunkIndex") },
320
+ {
321
+ alias: "aggMissingChunkCount",
322
+ expression: argMaxNumeric("missingChunkCount"),
323
+ },
324
+ { alias: "aggEventCount", expression: argMaxNumeric("eventCount") },
325
+ { alias: "aggPayloadBytes", expression: argMaxNumeric("payloadBytes") },
326
+ { alias: "aggHasError", expression: argMaxColumn("hasError") },
327
+ { alias: "aggErrorCount", expression: argMaxNumeric("errorCount") },
328
+ { alias: "aggRageClickCount", expression: argMaxNumeric("rageClickCount") },
329
+ { alias: "aggDeadClickCount", expression: argMaxNumeric("deadClickCount") },
330
+ { alias: "aggErrorClickCount", expression: argMaxNumeric("errorClickCount") },
331
+ {
332
+ alias: "aggRefreshRageCount",
333
+ expression: argMaxNumeric("refreshRageCount"),
334
+ },
335
+ { alias: "aggPageCount", expression: argMaxNumeric("pageCount") },
336
+ { alias: "aggTriggerReason", expression: argMaxColumn("triggerReason") },
337
+ { alias: "aggEntryUrl", expression: argMaxColumn("entryUrl") },
338
+ { alias: "aggExitUrl", expression: argMaxColumn("exitUrl") },
339
+ { alias: "aggBrowserName", expression: argMaxColumn("browserName") },
340
+ { alias: "aggBrowserVersion", expression: argMaxColumn("browserVersion") },
341
+ { alias: "aggOsName", expression: argMaxColumn("osName") },
342
+ { alias: "aggDeviceType", expression: argMaxColumn("deviceType") },
343
+ { alias: "aggCountryCode", expression: argMaxColumn("countryCode") },
344
+ { alias: "aggViewportWidth", expression: argMaxNumeric("viewportWidth") },
345
+ { alias: "aggViewportHeight", expression: argMaxNumeric("viewportHeight") },
346
+ {
347
+ alias: "aggIdentifiedUserKey",
348
+ expression: argMaxColumn("identifiedUserKey"),
349
+ },
350
+ {
351
+ alias: "aggSamplePercentage",
352
+ expression: argMaxNumeric("samplePercentageAtCapture"),
353
+ },
354
+ ];
355
+
356
+ /* Only the manifest needs these; the list never renders them. */
357
+ const HEADER_DETAIL_AGGREGATES: Array<AggregatedColumn> = [
358
+ { alias: "aggMaskingMode", expression: argMaxColumn("maskingMode") },
359
+ { alias: "aggConsentState", expression: argMaxColumn("consentState") },
360
+ { alias: "aggRecorderKind", expression: argMaxColumn("recorderKind") },
361
+ { alias: "aggRecorderVersion", expression: argMaxColumn("recorderVersion") },
362
+ { alias: "aggRrwebVersion", expression: argMaxColumn("rrwebVersion") },
363
+ { alias: "aggSchemaVersion", expression: argMaxNumeric("schemaVersion") },
364
+ { alias: "aggWireVersion", expression: argMaxNumeric("wireVersion") },
365
+ { alias: "aggRoutes", expression: argMaxColumn("routes") },
366
+ { alias: "aggFidelityNotices", expression: argMaxColumn("fidelityNotices") },
367
+ {
368
+ alias: "aggFullSnapshotChunkIndexes",
369
+ expression: argMaxColumn("fullSnapshotChunkIndexes"),
370
+ },
371
+ { alias: "aggTraceIds", expression: argMaxColumn("traceIds") },
372
+ {
373
+ alias: "aggExceptionFingerprints",
374
+ expression: argMaxColumn("exceptionFingerprints"),
375
+ },
376
+ { alias: "aggClockSkewMs", expression: argMaxNumeric("clockSkewMs") },
377
+ ];
378
+
379
+ function toSelectList(columns: Array<AggregatedColumn>): string {
380
+ return columns
381
+ .map((column: AggregatedColumn): string => {
382
+ return `${column.expression} AS ${column.alias}`;
383
+ })
384
+ .join(",\n ");
385
+ }
386
+
387
+ function readNumber(row: JSONObject, key: string): number {
388
+ const value: unknown = row[key];
389
+
390
+ if (typeof value === "number" && Number.isFinite(value)) {
391
+ return value;
392
+ }
393
+
394
+ /*
395
+ * ClickHouse quotes 64-bit integers in JSON. Everything wide is wrapped
396
+ * in toFloat64 above, but parse defensively so one un-wrapped column
397
+ * added later degrades to a number rather than to NaN in the UI.
398
+ */
399
+ if (typeof value === "string" && value.length > 0) {
400
+ const parsed: number = Number(value);
401
+ return Number.isFinite(parsed) ? parsed : 0;
402
+ }
403
+
404
+ return 0;
405
+ }
406
+
407
+ function readBoolean(row: JSONObject, key: string): boolean {
408
+ const value: unknown = row[key];
409
+
410
+ if (typeof value === "boolean") {
411
+ return value;
412
+ }
413
+
414
+ return value === 1 || value === "1" || value === "true";
415
+ }
416
+
417
+ function readString(row: JSONObject, key: string): string {
418
+ const value: unknown = row[key];
419
+
420
+ return typeof value === "string" ? value : "";
421
+ }
422
+
423
+ function readStringArray(row: JSONObject, key: string): Array<string> {
424
+ const value: unknown = row[key];
425
+
426
+ if (!Array.isArray(value)) {
427
+ return [];
428
+ }
429
+
430
+ return value
431
+ .filter((item: unknown): item is string => {
432
+ return typeof item === "string";
433
+ })
434
+ .map((item: string): string => {
435
+ return item;
436
+ });
437
+ }
438
+
439
+ function readNumberArray(row: JSONObject, key: string): Array<number> {
440
+ const value: unknown = row[key];
441
+
442
+ if (!Array.isArray(value)) {
443
+ return [];
444
+ }
445
+
446
+ const numbers: Array<number> = [];
447
+
448
+ for (const item of value) {
449
+ const parsed: number = typeof item === "number" ? item : Number(item);
450
+
451
+ if (Number.isFinite(parsed)) {
452
+ numbers.push(parsed);
453
+ }
454
+ }
455
+
456
+ return numbers;
457
+ }
458
+
459
+ /*
460
+ * Unix millis -> Date. The queries return epoch milliseconds as a Float64
461
+ * precisely so no ClickHouse datetime string ever has to be re-parsed
462
+ * (its "YYYY-MM-DD hh:mm:ss.nnnnnnnnn" form has no timezone and is a
463
+ * long-standing source of off-by-hours bugs).
464
+ */
465
+ function readDate(row: JSONObject, key: string): Date {
466
+ return new Date(readNumber(row, key));
467
+ }
468
+
469
+ export default class SessionReplayReadService {
470
+ /*
471
+ * Session list.
472
+ *
473
+ * projectId / rumApplicationId / startTime go in the WHERE because they
474
+ * are the first three elements of the sort key AND they are part of the
475
+ * ReplacingMergeTree replace key, so they are byte-identical on every
476
+ * duplicate row of a session. Filtering on them before the GROUP BY is
477
+ * therefore both index-friendly and safe.
478
+ *
479
+ * Everything else is filtered in HAVING against the argMax'd value.
480
+ * That is not a style choice: a provisional header (written on chunk 0,
481
+ * before anything is known) reports hasError = false and errorCount = 0
482
+ * for a session the finalizer later marks as errored. A WHERE on those
483
+ * columns would match the stale row and the argMax would then report
484
+ * the truth - or, worse, would drop the group entirely.
485
+ */
486
+ @CaptureSpan()
487
+ public static async listSessions(
488
+ request: SessionReplayListRequest,
489
+ ): Promise<SessionReplayListResult> {
490
+ const limit: number = Math.max(
491
+ 1,
492
+ Math.min(request.limit, MAX_SESSION_REPLAY_LIST_LIMIT),
493
+ );
494
+
495
+ const selectList: string = toSelectList(HEADER_AGGREGATES);
496
+
497
+ const statement: Statement = SQL`
498
+ SELECT
499
+ sessionId,
500
+ toString(rumApplicationId) AS applicationId,
501
+ `;
502
+
503
+ statement.append(` ${selectList}`);
504
+
505
+ if (request.includeIdentifiedUserLabel) {
506
+ statement.append(
507
+ `,\n ${argMaxColumn("identifiedUserLabel")} AS aggIdentifiedUserLabel`,
508
+ );
509
+ }
510
+
511
+ statement.append(SQL`
512
+ FROM ${AnalyticsTableName.RumSession}
513
+ WHERE projectId = ${{
514
+ type: TableColumnType.ObjectID,
515
+ value: request.projectId,
516
+ }}
517
+ AND rumApplicationId = ${{
518
+ type: TableColumnType.ObjectID,
519
+ value: request.rumApplicationId,
520
+ }}
521
+ AND startTime >= ${{
522
+ type: TableColumnType.DateTime64,
523
+ value: request.startTime,
524
+ }}
525
+ AND startTime <= ${{
526
+ type: TableColumnType.DateTime64,
527
+ value: request.endTime,
528
+ }}
529
+ `);
530
+
531
+ statement.append(RETENTION_FILTER);
532
+
533
+ /*
534
+ * Keyset cursor. The sort key is (projectId, rumApplicationId,
535
+ * startTime, sessionId) and the list is ordered by the same tuple
536
+ * descending, so the previous page's last startTime is a valid
537
+ * WHERE-level upper bound: it prunes granules instead of paging with
538
+ * OFFSET, which on a wide time window would re-read and re-aggregate
539
+ * everything already returned. The exact ties are removed by the
540
+ * HAVING tiebreak below - the WHERE bound is deliberately inclusive
541
+ * so a row sharing the boundary timestamp is not skipped.
542
+ */
543
+ if (request.cursor) {
544
+ statement.append(
545
+ SQL` AND startTime <= ${{
546
+ type: TableColumnType.DateTime64,
547
+ value: new Date(request.cursor.startTimeUnixMs),
548
+ }}`,
549
+ );
550
+ }
551
+
552
+ statement.append(
553
+ " GROUP BY projectId, rumApplicationId, sessionId\n HAVING 1 = 1",
554
+ );
555
+
556
+ SessionReplayReadService.appendListHavingFilters(
557
+ statement,
558
+ request.filters,
559
+ );
560
+
561
+ if (request.cursor) {
562
+ statement.append(
563
+ SQL` AND (aggStartTime < ${{
564
+ type: TableColumnType.Decimal,
565
+ value: request.cursor.startTimeUnixMs,
566
+ }} OR (aggStartTime = ${{
567
+ type: TableColumnType.Decimal,
568
+ value: request.cursor.startTimeUnixMs,
569
+ }} AND sessionId < ${{
570
+ type: TableColumnType.Text,
571
+ value: request.cursor.sessionId,
572
+ }}))`,
573
+ );
574
+ }
575
+
576
+ statement.append(
577
+ SQL` ORDER BY aggStartTime DESC, sessionId DESC
578
+ LIMIT ${{
579
+ type: TableColumnType.Number,
580
+ value: limit + 1,
581
+ }}`,
582
+ );
583
+
584
+ statement.append(READ_QUERY_SETTINGS);
585
+
586
+ const dbResult: Results = await RumSessionService.executeQuery(statement);
587
+ const response: DbJSONResponse = await dbResult.json<{
588
+ data?: Array<JSONObject>;
589
+ }>();
590
+
591
+ const rows: Array<JSONObject> = response.data || [];
592
+
593
+ /*
594
+ * One row over the page size is fetched purely to learn whether a
595
+ * next page exists without a second COUNT query over the same
596
+ * aggregation.
597
+ */
598
+ const hasMore: boolean = rows.length > limit;
599
+ const pageRows: Array<JSONObject> = hasMore ? rows.slice(0, limit) : rows;
600
+
601
+ const sessions: Array<SessionReplayListItem> = pageRows.map(
602
+ (row: JSONObject): SessionReplayListItem => {
603
+ const item: SessionReplayListItem = {
604
+ sessionId: readString(row, "sessionId"),
605
+ rumApplicationId: readString(row, "applicationId"),
606
+ startTime: readDate(row, "aggStartTime"),
607
+ endTime: readDate(row, "aggEndTime"),
608
+ durationMs: readNumber(row, "aggDurationMs"),
609
+ isFinalized: readBoolean(row, "aggIsFinalized"),
610
+ sealedReason: readString(row, "aggSealedReason"),
611
+ chunkCount: readNumber(row, "aggChunkCount"),
612
+ maxChunkIndex: readNumber(row, "aggMaxChunkIndex"),
613
+ missingChunkCount: readNumber(row, "aggMissingChunkCount"),
614
+ eventCount: readNumber(row, "aggEventCount"),
615
+ payloadBytes: readNumber(row, "aggPayloadBytes"),
616
+ hasError: readBoolean(row, "aggHasError"),
617
+ errorCount: readNumber(row, "aggErrorCount"),
618
+ rageClickCount: readNumber(row, "aggRageClickCount"),
619
+ deadClickCount: readNumber(row, "aggDeadClickCount"),
620
+ errorClickCount: readNumber(row, "aggErrorClickCount"),
621
+ refreshRageCount: readNumber(row, "aggRefreshRageCount"),
622
+ pageCount: readNumber(row, "aggPageCount"),
623
+ triggerReason: readString(row, "aggTriggerReason"),
624
+ entryUrl: readString(row, "aggEntryUrl"),
625
+ exitUrl: readString(row, "aggExitUrl"),
626
+ browserName: readString(row, "aggBrowserName"),
627
+ browserVersion: readString(row, "aggBrowserVersion"),
628
+ osName: readString(row, "aggOsName"),
629
+ deviceType: readString(row, "aggDeviceType"),
630
+ countryCode: readString(row, "aggCountryCode"),
631
+ viewportWidth: readNumber(row, "aggViewportWidth"),
632
+ viewportHeight: readNumber(row, "aggViewportHeight"),
633
+ identifiedUserKey: readString(row, "aggIdentifiedUserKey"),
634
+ samplePercentageAtCapture: readNumber(row, "aggSamplePercentage"),
635
+ };
636
+
637
+ if (request.includeIdentifiedUserLabel) {
638
+ item.identifiedUserLabel = readString(row, "aggIdentifiedUserLabel");
639
+ }
640
+
641
+ return item;
642
+ },
643
+ );
644
+
645
+ const lastSession: SessionReplayListItem | undefined =
646
+ sessions[sessions.length - 1];
647
+
648
+ return {
649
+ sessions: sessions,
650
+ nextCursor:
651
+ hasMore && lastSession
652
+ ? {
653
+ startTimeUnixMs: lastSession.startTime.getTime(),
654
+ sessionId: lastSession.sessionId,
655
+ }
656
+ : null,
657
+ };
658
+ }
659
+
660
+ /*
661
+ * The single header row for one session, de-duplicated the same way the
662
+ * list is.
663
+ *
664
+ * This is also what resolves a sessionId to its owning RUM application
665
+ * for the handler-level authorization check, which is why it is keyed
666
+ * on (projectId, sessionId) only and never accepts an application id
667
+ * from the caller: an application id supplied in the request body would
668
+ * make the check circular.
669
+ */
670
+ @CaptureSpan()
671
+ public static async getSessionHeader(data: {
672
+ projectId: ObjectID;
673
+ sessionId: string;
674
+ }): Promise<SessionReplaySessionHeader | null> {
675
+ const selectList: string = toSelectList([
676
+ ...HEADER_AGGREGATES,
677
+ ...HEADER_DETAIL_AGGREGATES,
678
+ ]);
679
+
680
+ const statement: Statement = SQL`
681
+ SELECT
682
+ sessionId,
683
+ toString(projectId) AS headerProjectId,
684
+ toString(rumApplicationId) AS applicationId,
685
+ `;
686
+
687
+ statement.append(` ${selectList}`);
688
+
689
+ statement.append(SQL`
690
+ FROM ${AnalyticsTableName.RumSession}
691
+ WHERE projectId = ${{
692
+ type: TableColumnType.ObjectID,
693
+ value: data.projectId,
694
+ }}
695
+ AND sessionId = ${{
696
+ type: TableColumnType.Text,
697
+ value: data.sessionId,
698
+ }}
699
+ `);
700
+
701
+ statement.append(RETENTION_FILTER);
702
+
703
+ /*
704
+ * Grouped by the full replace-key identity minus startTime, so one
705
+ * group per (application, session).
706
+ *
707
+ * LIMIT 2, not LIMIT 1. sessionId is minted by the browser and is
708
+ * therefore fully caller-controlled, while the chunk table's replace
709
+ * key is (projectId, sessionId, tabId, chunkIndex) with
710
+ * rumApplicationId a plain column - two applications sharing a
711
+ * sessionId share a key space. Picking the newest group would let
712
+ * anyone who can write to application A resolve a sessionId belonging
713
+ * to application B onto their own application and pass the label
714
+ * check. An ambiguous sessionId is refused outright instead: it is
715
+ * either an attack or a collision, and neither has a correct
716
+ * recording to return.
717
+ */
718
+ statement.append(
719
+ " GROUP BY projectId, rumApplicationId, sessionId ORDER BY aggStartTime DESC LIMIT 2",
720
+ );
721
+
722
+ statement.append(READ_QUERY_SETTINGS);
723
+
724
+ const dbResult: Results = await RumSessionService.executeQuery(statement);
725
+ const response: DbJSONResponse = await dbResult.json<{
726
+ data?: Array<JSONObject>;
727
+ }>();
728
+
729
+ const rows: Array<JSONObject> = response.data || [];
730
+
731
+ if (rows.length > 1) {
732
+ throw new BadDataException(
733
+ "This session id resolves to more than one RUM application and cannot be played back.",
734
+ );
735
+ }
736
+
737
+ const row: JSONObject | undefined = rows[0];
738
+
739
+ if (!row) {
740
+ return null;
741
+ }
742
+
743
+ return {
744
+ sessionId: readString(row, "sessionId"),
745
+ projectId: readString(row, "headerProjectId"),
746
+ rumApplicationId: readString(row, "applicationId"),
747
+ startTime: readDate(row, "aggStartTime"),
748
+ endTime: readDate(row, "aggEndTime"),
749
+ durationMs: readNumber(row, "aggDurationMs"),
750
+ isFinalized: readBoolean(row, "aggIsFinalized"),
751
+ sealedReason: readString(row, "aggSealedReason"),
752
+ chunkCount: readNumber(row, "aggChunkCount"),
753
+ maxChunkIndex: readNumber(row, "aggMaxChunkIndex"),
754
+ missingChunkCount: readNumber(row, "aggMissingChunkCount"),
755
+ eventCount: readNumber(row, "aggEventCount"),
756
+ payloadBytes: readNumber(row, "aggPayloadBytes"),
757
+ hasError: readBoolean(row, "aggHasError"),
758
+ errorCount: readNumber(row, "aggErrorCount"),
759
+ rageClickCount: readNumber(row, "aggRageClickCount"),
760
+ deadClickCount: readNumber(row, "aggDeadClickCount"),
761
+ errorClickCount: readNumber(row, "aggErrorClickCount"),
762
+ refreshRageCount: readNumber(row, "aggRefreshRageCount"),
763
+ pageCount: readNumber(row, "aggPageCount"),
764
+ triggerReason: readString(row, "aggTriggerReason"),
765
+ maskingMode: readString(row, "aggMaskingMode"),
766
+ consentState: readString(row, "aggConsentState"),
767
+ recorderKind: readString(row, "aggRecorderKind"),
768
+ recorderVersion: readString(row, "aggRecorderVersion"),
769
+ rrwebVersion: readString(row, "aggRrwebVersion"),
770
+ schemaVersion: readNumber(row, "aggSchemaVersion"),
771
+ wireVersion: readNumber(row, "aggWireVersion"),
772
+ entryUrl: readString(row, "aggEntryUrl"),
773
+ exitUrl: readString(row, "aggExitUrl"),
774
+ routes: readStringArray(row, "aggRoutes"),
775
+ browserName: readString(row, "aggBrowserName"),
776
+ browserVersion: readString(row, "aggBrowserVersion"),
777
+ osName: readString(row, "aggOsName"),
778
+ deviceType: readString(row, "aggDeviceType"),
779
+ countryCode: readString(row, "aggCountryCode"),
780
+ viewportWidth: readNumber(row, "aggViewportWidth"),
781
+ viewportHeight: readNumber(row, "aggViewportHeight"),
782
+ fidelityNotices: readStringArray(row, "aggFidelityNotices"),
783
+ fullSnapshotChunkIndexes: readNumberArray(
784
+ row,
785
+ "aggFullSnapshotChunkIndexes",
786
+ ),
787
+ traceIds: readStringArray(row, "aggTraceIds"),
788
+ exceptionFingerprints: readStringArray(row, "aggExceptionFingerprints"),
789
+ clockSkewMs: readNumber(row, "aggClockSkewMs"),
790
+ };
791
+ }
792
+
793
+ /*
794
+ * Playback manifest: everything the player needs to draw a complete,
795
+ * honest timeline without fetching one payload byte.
796
+ *
797
+ * The `payload` column is deliberately absent from this SELECT. That is
798
+ * the entire performance story of the feature: a 14-chunk session is
799
+ * one 128-row granule of a handful of narrow columns (~2 KB) instead of
800
+ * megabytes of decompressed recording.
801
+ */
802
+ @CaptureSpan()
803
+ public static async getManifest(data: {
804
+ header: SessionReplaySessionHeader;
805
+ projectId: ObjectID;
806
+ /*
807
+ * The application the caller was actually authorized against, always
808
+ * the one resolved from the session header server-side. Every chunk
809
+ * read is pinned to it: the chunk table's replace key does not
810
+ * include rumApplicationId, so (projectId, sessionId) alone is not a
811
+ * tenant-safe key once a sessionId can be reused across
812
+ * applications.
813
+ */
814
+ rumApplicationId: ObjectID;
815
+ sessionId: string;
816
+ }): Promise<SessionReplayManifest> {
817
+ /*
818
+ * LIMIT 1 BY (tabId, chunkIndex) after ORDER BY ... version DESC
819
+ * keeps exactly the highest-version row per chunk. tabId is part of
820
+ * the group because chunkIndex is minted per tab. Ordering by
821
+ * tabId/chunkIndex first (rather than by version alone) leaves the
822
+ * output already sorted for the caller - LIMIT BY runs after ORDER
823
+ * BY, so the version DESC tiebreak still selects the right row.
824
+ */
825
+ const statement: Statement = SQL`
826
+ SELECT
827
+ tabId,
828
+ chunkIndex,
829
+ chunkStartOffsetMs,
830
+ chunkEndOffsetMs,
831
+ eventCount,
832
+ hasFullSnapshot,
833
+ toFloat64(payloadBytes) AS chunkPayloadBytes,
834
+ errorCount,
835
+ rageClickCount,
836
+ deadClickCount,
837
+ errorClickCount,
838
+ refreshRageCount,
839
+ routeCount
840
+ FROM ${AnalyticsTableName.RumSessionChunk}
841
+ WHERE projectId = ${{
842
+ type: TableColumnType.ObjectID,
843
+ value: data.projectId,
844
+ }}
845
+ AND rumApplicationId = ${{
846
+ type: TableColumnType.ObjectID,
847
+ value: data.rumApplicationId,
848
+ }}
849
+ AND sessionId = ${{
850
+ type: TableColumnType.Text,
851
+ value: data.sessionId,
852
+ }}
853
+ `;
854
+
855
+ statement.append(RETENTION_FILTER);
856
+
857
+ statement.append(
858
+ SQL` ORDER BY tabId ASC, chunkIndex ASC, version DESC
859
+ LIMIT 1 BY tabId, chunkIndex
860
+ LIMIT ${{
861
+ type: TableColumnType.Number,
862
+ value: MAX_MANIFEST_ROWS,
863
+ }}`,
864
+ );
865
+
866
+ statement.append(READ_QUERY_SETTINGS);
867
+
868
+ const dbResult: Results =
869
+ await RumSessionChunkService.executeQuery(statement);
870
+ const response: DbJSONResponse = await dbResult.json<{
871
+ data?: Array<JSONObject>;
872
+ }>();
873
+
874
+ const rows: Array<JSONObject> = response.data || [];
875
+
876
+ const tabsById: Map<
877
+ string,
878
+ Array<SessionReplayChunkManifestEntry>
879
+ > = new Map<string, Array<SessionReplayChunkManifestEntry>>();
880
+
881
+ for (const row of rows) {
882
+ const tabId: string = readString(row, "tabId");
883
+
884
+ const entry: SessionReplayChunkManifestEntry = {
885
+ chunkIndex: readNumber(row, "chunkIndex"),
886
+ tabId: tabId,
887
+ chunkStartOffsetMs: readNumber(row, "chunkStartOffsetMs"),
888
+ chunkEndOffsetMs: readNumber(row, "chunkEndOffsetMs"),
889
+ eventCount: readNumber(row, "eventCount"),
890
+ hasFullSnapshot: readBoolean(row, "hasFullSnapshot"),
891
+ payloadBytes: readNumber(row, "chunkPayloadBytes"),
892
+ errorCount: readNumber(row, "errorCount"),
893
+ rageClickCount: readNumber(row, "rageClickCount"),
894
+ deadClickCount: readNumber(row, "deadClickCount"),
895
+ errorClickCount: readNumber(row, "errorClickCount"),
896
+ refreshRageCount: readNumber(row, "refreshRageCount"),
897
+ routeCount: readNumber(row, "routeCount"),
898
+ };
899
+
900
+ const existing: Array<SessionReplayChunkManifestEntry> | undefined =
901
+ tabsById.get(tabId);
902
+
903
+ if (existing) {
904
+ existing.push(entry);
905
+ } else {
906
+ tabsById.set(tabId, [entry]);
907
+ }
908
+ }
909
+
910
+ const tabs: Array<SessionReplayManifestTab> = [];
911
+
912
+ for (const [tabId, entries] of tabsById) {
913
+ tabs.push({
914
+ tabId: tabId,
915
+ chunks: entries,
916
+ chunkIndexes: entries.map(
917
+ (entry: SessionReplayChunkManifestEntry): number => {
918
+ return entry.chunkIndex;
919
+ },
920
+ ),
921
+ /*
922
+ * Seek anchors come from the chunk rows rather than from the
923
+ * header's fullSnapshotChunkIndexes: the header is only written
924
+ * by the finalizer, so a still-recording session would otherwise
925
+ * have no anchors at all and could not be scrubbed.
926
+ */
927
+ fullSnapshotChunkIndexes: entries
928
+ .filter((entry: SessionReplayChunkManifestEntry): boolean => {
929
+ return entry.hasFullSnapshot;
930
+ })
931
+ .map((entry: SessionReplayChunkManifestEntry): number => {
932
+ return entry.chunkIndex;
933
+ }),
934
+ gaps: ChunkMath.detectGaps(entries),
935
+ maxChunkIndex: entries.reduce(
936
+ (max: number, entry: SessionReplayChunkManifestEntry): number => {
937
+ return Math.max(max, entry.chunkIndex);
938
+ },
939
+ 0,
940
+ ),
941
+ totalPayloadBytes: entries.reduce(
942
+ (total: number, entry: SessionReplayChunkManifestEntry): number => {
943
+ return total + entry.payloadBytes;
944
+ },
945
+ 0,
946
+ ),
947
+ });
948
+ }
949
+
950
+ return {
951
+ header: data.header,
952
+ tabs: tabs,
953
+ isChunkIndexTruncated: rows.length >= MAX_MANIFEST_ROWS,
954
+ };
955
+ }
956
+
957
+ /*
958
+ * Total STORED bytes for a specific set of chunks, without shipping the
959
+ * payload column to the application.
960
+ *
961
+ * `length(payload)`, deliberately NOT `payloadBytes`. Those are two
962
+ * different quantities: payloadBytes is the post-gzip WIRE size the
963
+ * recorder uploaded (the metering signal), while the payload column
964
+ * holds the DECOMPRESSED JSON and is what this endpoint actually
965
+ * returns. rrweb JSON gzips 10-20x, so a cap applied to payloadBytes
966
+ * bounds a number an order of magnitude smaller than the response and
967
+ * therefore bounds nothing useful.
968
+ *
969
+ * The cost is that ClickHouse has to decompress the column to measure
970
+ * it, which is exactly what naming `payload` was meant to avoid. It is
971
+ * still worth doing before the read rather than after: the bytes are
972
+ * measured inside ClickHouse and never cross the wire, and the marks
973
+ * the following read needs are warm by the time it runs.
974
+ */
975
+ @CaptureSpan()
976
+ public static async getChunkStoredBytes(data: {
977
+ projectId: ObjectID;
978
+ rumApplicationId: ObjectID;
979
+ sessionId: string;
980
+ tabId: string;
981
+ chunkIndexes: Array<number>;
982
+ }): Promise<number> {
983
+ if (data.chunkIndexes.length === 0) {
984
+ return 0;
985
+ }
986
+
987
+ const statement: Statement = SQL`
988
+ SELECT
989
+ chunkIndex,
990
+ toFloat64(length(payload)) AS chunkStoredBytes
991
+ FROM ${AnalyticsTableName.RumSessionChunk}
992
+ WHERE projectId = ${{
993
+ type: TableColumnType.ObjectID,
994
+ value: data.projectId,
995
+ }}
996
+ AND rumApplicationId = ${{
997
+ type: TableColumnType.ObjectID,
998
+ value: data.rumApplicationId,
999
+ }}
1000
+ AND sessionId = ${{
1001
+ type: TableColumnType.Text,
1002
+ value: data.sessionId,
1003
+ }}
1004
+ AND tabId = ${{
1005
+ type: TableColumnType.Text,
1006
+ value: data.tabId,
1007
+ }}
1008
+ AND chunkIndex IN (${{
1009
+ type: TableColumnType.Number,
1010
+ value: new Includes(data.chunkIndexes),
1011
+ }})
1012
+ `;
1013
+
1014
+ statement.append(RETENTION_FILTER);
1015
+
1016
+ /*
1017
+ * Deduplicated exactly like the payload read, so the pre-check and
1018
+ * the read it guards can never disagree about which rows count.
1019
+ * Summed in TypeScript rather than in SQL because the row count is
1020
+ * bounded by MAX_SESSION_REPLAY_CHUNKS_PER_READ, and a wrapping
1021
+ * aggregate would need a subquery whose LIMIT BY semantics are
1022
+ * easier to get subtly wrong than to read.
1023
+ */
1024
+ statement.append(
1025
+ " ORDER BY chunkIndex ASC, version DESC LIMIT 1 BY chunkIndex",
1026
+ );
1027
+
1028
+ statement.append(READ_QUERY_SETTINGS);
1029
+
1030
+ const dbResult: Results =
1031
+ await RumSessionChunkService.executeQuery(statement);
1032
+ const response: DbJSONResponse = await dbResult.json<{
1033
+ data?: Array<JSONObject>;
1034
+ }>();
1035
+
1036
+ return (response.data || []).reduce(
1037
+ (total: number, row: JSONObject): number => {
1038
+ return total + readNumber(row, "chunkStoredBytes");
1039
+ },
1040
+ 0,
1041
+ );
1042
+ }
1043
+
1044
+ /*
1045
+ * The payload read. The only query in the system that names the
1046
+ * `payload` column.
1047
+ *
1048
+ * Both caps are enforced here rather than only at the route so no
1049
+ * future caller can reach the payload column without them.
1050
+ */
1051
+ @CaptureSpan()
1052
+ public static async getChunks(data: {
1053
+ projectId: ObjectID;
1054
+ rumApplicationId: ObjectID;
1055
+ sessionId: string;
1056
+ tabId: string;
1057
+ chunkIndexes: Array<number>;
1058
+ }): Promise<Array<SessionReplayChunkPayload>> {
1059
+ if (data.chunkIndexes.length === 0) {
1060
+ return [];
1061
+ }
1062
+
1063
+ if (data.chunkIndexes.length > MAX_SESSION_REPLAY_CHUNKS_PER_READ) {
1064
+ throw new BadDataException(
1065
+ `A maximum of ${MAX_SESSION_REPLAY_CHUNKS_PER_READ} chunks may be requested at a time.`,
1066
+ );
1067
+ }
1068
+
1069
+ const totalBytes: number =
1070
+ await SessionReplayReadService.getChunkStoredBytes(data);
1071
+
1072
+ if (totalBytes > MAX_SESSION_REPLAY_READ_BYTES) {
1073
+ throw new BadDataException(
1074
+ `The requested chunks total ${totalBytes} bytes, which exceeds the ${MAX_SESSION_REPLAY_READ_BYTES} byte limit for a single read. Request fewer chunks.`,
1075
+ );
1076
+ }
1077
+
1078
+ const statement: Statement = SQL`
1079
+ SELECT
1080
+ chunkIndex,
1081
+ payload
1082
+ FROM ${AnalyticsTableName.RumSessionChunk}
1083
+ WHERE projectId = ${{
1084
+ type: TableColumnType.ObjectID,
1085
+ value: data.projectId,
1086
+ }}
1087
+ AND rumApplicationId = ${{
1088
+ type: TableColumnType.ObjectID,
1089
+ value: data.rumApplicationId,
1090
+ }}
1091
+ AND sessionId = ${{
1092
+ type: TableColumnType.Text,
1093
+ value: data.sessionId,
1094
+ }}
1095
+ AND tabId = ${{
1096
+ type: TableColumnType.Text,
1097
+ value: data.tabId,
1098
+ }}
1099
+ AND chunkIndex IN (${{
1100
+ type: TableColumnType.Number,
1101
+ value: new Includes(data.chunkIndexes),
1102
+ }})
1103
+ `;
1104
+
1105
+ statement.append(RETENTION_FILTER);
1106
+
1107
+ /*
1108
+ * A retried delivery is two physically present rows on a
1109
+ * ReplacingMergeTree until a merge runs. Feeding both to the player
1110
+ * would replay the same mutations twice, which rrweb resolves against
1111
+ * node ids and would either throw or render a DOM that never existed.
1112
+ */
1113
+ statement.append(
1114
+ " ORDER BY chunkIndex ASC, version DESC LIMIT 1 BY chunkIndex",
1115
+ );
1116
+
1117
+ statement.append(READ_QUERY_SETTINGS);
1118
+
1119
+ const dbResult: Results =
1120
+ await RumSessionChunkService.executeQuery(statement);
1121
+ const response: DbJSONResponse = await dbResult.json<{
1122
+ data?: Array<JSONObject>;
1123
+ }>();
1124
+
1125
+ /*
1126
+ * The cap is re-applied to the bytes actually being handed back, not
1127
+ * only to what the pre-check believed. The pre-check reads a
1128
+ * different snapshot of a ReplacingMergeTree than the read it guards,
1129
+ * and any future change to how stored size is derived would otherwise
1130
+ * silently unbound the response. Accumulated as the rows are mapped
1131
+ * so an oversized read fails before the caller ever holds the whole
1132
+ * set.
1133
+ */
1134
+ let totalReturnedBytes: number = 0;
1135
+ const chunks: Array<SessionReplayChunkPayload> = [];
1136
+
1137
+ for (const row of response.data || []) {
1138
+ const payload: string = readString(row, "payload");
1139
+
1140
+ totalReturnedBytes += Buffer.byteLength(payload, "utf8");
1141
+
1142
+ if (totalReturnedBytes > MAX_SESSION_REPLAY_READ_BYTES) {
1143
+ throw new BadDataException(
1144
+ `The requested chunks exceed the ${MAX_SESSION_REPLAY_READ_BYTES} byte limit for a single read. Request fewer chunks.`,
1145
+ );
1146
+ }
1147
+
1148
+ chunks.push({
1149
+ chunkIndex: readNumber(row, "chunkIndex"),
1150
+ payload: payload,
1151
+ });
1152
+ }
1153
+
1154
+ return chunks;
1155
+ }
1156
+
1157
+ /*
1158
+ * Sessions that observed a given exception fingerprint.
1159
+ *
1160
+ * hasAny() appears twice on purpose. In the WHERE it is a bloom-pruned
1161
+ * pre-filter over physical rows; a group survives it if ANY of its rows
1162
+ * carries the fingerprint, which necessarily includes the case where
1163
+ * the winning (highest version) row does - so the pre-filter cannot
1164
+ * drop a true match. The HAVING then re-checks the argMax'd array so a
1165
+ * fingerprint present only on a superseded row does not produce a false
1166
+ * positive.
1167
+ */
1168
+ @CaptureSpan()
1169
+ public static async getSessionsForException(data: {
1170
+ projectId: ObjectID;
1171
+ exceptionFingerprint: string;
1172
+ /*
1173
+ * null means "no label restriction". An EMPTY array means the caller
1174
+ * can reach no applications at all and must get no rows - the two are
1175
+ * not the same and collapsing them would leak every session in the
1176
+ * project.
1177
+ */
1178
+ accessibleRumApplicationIds: Array<ObjectID> | null;
1179
+ startTime?: Date | undefined;
1180
+ endTime?: Date | undefined;
1181
+ limit: number;
1182
+ }): Promise<Array<SessionReplayExceptionSession>> {
1183
+ if (
1184
+ data.accessibleRumApplicationIds &&
1185
+ data.accessibleRumApplicationIds.length === 0
1186
+ ) {
1187
+ return [];
1188
+ }
1189
+
1190
+ const limit: number = Math.max(
1191
+ 1,
1192
+ Math.min(data.limit, MAX_SESSION_REPLAY_FOR_EXCEPTION_LIMIT),
1193
+ );
1194
+
1195
+ const selectList: string = toSelectList([
1196
+ { alias: "aggStartTime", expression: argMaxDateTime("startTime") },
1197
+ { alias: "aggEndTime", expression: argMaxDateTime("endTime") },
1198
+ { alias: "aggDurationMs", expression: argMaxNumeric("durationMs") },
1199
+ { alias: "aggHasError", expression: argMaxColumn("hasError") },
1200
+ { alias: "aggErrorCount", expression: argMaxNumeric("errorCount") },
1201
+ /*
1202
+ * The frustration counters and masking mode feed the "Watch what the
1203
+ * user saw" card: the signals line ("2 rage clicks before the error")
1204
+ * and the up-front masking disclosure both come from here. Omitting
1205
+ * them renders the card with empty signals and "unknown" masking.
1206
+ */
1207
+ {
1208
+ alias: "aggRageClickCount",
1209
+ expression: argMaxNumeric("rageClickCount"),
1210
+ },
1211
+ {
1212
+ alias: "aggDeadClickCount",
1213
+ expression: argMaxNumeric("deadClickCount"),
1214
+ },
1215
+ {
1216
+ alias: "aggErrorClickCount",
1217
+ expression: argMaxNumeric("errorClickCount"),
1218
+ },
1219
+ {
1220
+ alias: "aggRefreshRageCount",
1221
+ expression: argMaxNumeric("refreshRageCount"),
1222
+ },
1223
+ { alias: "aggMaskingMode", expression: argMaxColumn("maskingMode") },
1224
+ { alias: "aggTriggerReason", expression: argMaxColumn("triggerReason") },
1225
+ { alias: "aggEntryUrl", expression: argMaxColumn("entryUrl") },
1226
+ { alias: "aggBrowserName", expression: argMaxColumn("browserName") },
1227
+ { alias: "aggOsName", expression: argMaxColumn("osName") },
1228
+ { alias: "aggDeviceType", expression: argMaxColumn("deviceType") },
1229
+ { alias: "aggIsFinalized", expression: argMaxColumn("isFinalized") },
1230
+ {
1231
+ alias: "aggExceptionFingerprints",
1232
+ expression: argMaxColumn("exceptionFingerprints"),
1233
+ },
1234
+ ]);
1235
+
1236
+ const statement: Statement = SQL`
1237
+ SELECT
1238
+ sessionId,
1239
+ toString(rumApplicationId) AS applicationId,
1240
+ `;
1241
+
1242
+ statement.append(` ${selectList}`);
1243
+
1244
+ statement.append(SQL`
1245
+ FROM ${AnalyticsTableName.RumSession}
1246
+ WHERE projectId = ${{
1247
+ type: TableColumnType.ObjectID,
1248
+ value: data.projectId,
1249
+ }}
1250
+ AND hasAny(exceptionFingerprints, [${{
1251
+ type: TableColumnType.Text,
1252
+ value: data.exceptionFingerprint,
1253
+ }}])
1254
+ `);
1255
+
1256
+ statement.append(RETENTION_FILTER);
1257
+
1258
+ if (data.accessibleRumApplicationIds) {
1259
+ statement.append(
1260
+ SQL` AND rumApplicationId IN (${{
1261
+ type: TableColumnType.ObjectID,
1262
+ value: new Includes(data.accessibleRumApplicationIds),
1263
+ }})`,
1264
+ );
1265
+ }
1266
+
1267
+ if (data.startTime) {
1268
+ statement.append(
1269
+ SQL` AND startTime >= ${{
1270
+ type: TableColumnType.DateTime64,
1271
+ value: data.startTime,
1272
+ }}`,
1273
+ );
1274
+ }
1275
+
1276
+ if (data.endTime) {
1277
+ statement.append(
1278
+ SQL` AND startTime <= ${{
1279
+ type: TableColumnType.DateTime64,
1280
+ value: data.endTime,
1281
+ }}`,
1282
+ );
1283
+ }
1284
+
1285
+ statement.append(
1286
+ SQL` GROUP BY projectId, rumApplicationId, sessionId
1287
+ HAVING hasAny(aggExceptionFingerprints, [${{
1288
+ type: TableColumnType.Text,
1289
+ value: data.exceptionFingerprint,
1290
+ }}])
1291
+ ORDER BY aggStartTime DESC
1292
+ LIMIT ${{
1293
+ type: TableColumnType.Number,
1294
+ value: limit,
1295
+ }}`,
1296
+ );
1297
+
1298
+ statement.append(READ_QUERY_SETTINGS);
1299
+
1300
+ const dbResult: Results = await RumSessionService.executeQuery(statement);
1301
+ const response: DbJSONResponse = await dbResult.json<{
1302
+ data?: Array<JSONObject>;
1303
+ }>();
1304
+
1305
+ return (response.data || []).map(
1306
+ (row: JSONObject): SessionReplayExceptionSession => {
1307
+ return {
1308
+ sessionId: readString(row, "sessionId"),
1309
+ rumApplicationId: readString(row, "applicationId"),
1310
+ startTime: readDate(row, "aggStartTime"),
1311
+ endTime: readDate(row, "aggEndTime"),
1312
+ durationMs: readNumber(row, "aggDurationMs"),
1313
+ hasError: readBoolean(row, "aggHasError"),
1314
+ errorCount: readNumber(row, "aggErrorCount"),
1315
+ rageClickCount: readNumber(row, "aggRageClickCount"),
1316
+ deadClickCount: readNumber(row, "aggDeadClickCount"),
1317
+ errorClickCount: readNumber(row, "aggErrorClickCount"),
1318
+ refreshRageCount: readNumber(row, "aggRefreshRageCount"),
1319
+ maskingMode: readString(row, "aggMaskingMode"),
1320
+ triggerReason: readString(row, "aggTriggerReason"),
1321
+ entryUrl: readString(row, "aggEntryUrl"),
1322
+ browserName: readString(row, "aggBrowserName"),
1323
+ osName: readString(row, "aggOsName"),
1324
+ deviceType: readString(row, "aggDeviceType"),
1325
+ isFinalized: readBoolean(row, "aggIsFinalized"),
1326
+ };
1327
+ },
1328
+ );
1329
+ }
1330
+
1331
+ private static appendListHavingFilters(
1332
+ statement: Statement,
1333
+ filters: SessionReplayListFilters,
1334
+ ): void {
1335
+ if (filters.hasError !== undefined) {
1336
+ statement.append(
1337
+ SQL` AND aggHasError = ${{
1338
+ type: TableColumnType.Boolean,
1339
+ value: filters.hasError,
1340
+ }}`,
1341
+ );
1342
+ }
1343
+
1344
+ if (filters.hasFrustration === true) {
1345
+ /*
1346
+ * Over the argMax aliases, like every HAVING predicate here — the
1347
+ * raw columns would sum across ReplacingMergeTree versions.
1348
+ */
1349
+ statement.append(
1350
+ " AND (aggRageClickCount + aggDeadClickCount + aggErrorClickCount + aggRefreshRageCount) > 0",
1351
+ );
1352
+ }
1353
+
1354
+ if (filters.isFinalized !== undefined) {
1355
+ statement.append(
1356
+ SQL` AND aggIsFinalized = ${{
1357
+ type: TableColumnType.Boolean,
1358
+ value: filters.isFinalized,
1359
+ }}`,
1360
+ );
1361
+ }
1362
+
1363
+ if (filters.triggerReasons && filters.triggerReasons.length > 0) {
1364
+ statement.append(
1365
+ SQL` AND aggTriggerReason IN (${{
1366
+ type: TableColumnType.Text,
1367
+ value: new Includes(filters.triggerReasons),
1368
+ }})`,
1369
+ );
1370
+ }
1371
+
1372
+ if (filters.browserNames && filters.browserNames.length > 0) {
1373
+ statement.append(
1374
+ SQL` AND aggBrowserName IN (${{
1375
+ type: TableColumnType.Text,
1376
+ value: new Includes(filters.browserNames),
1377
+ }})`,
1378
+ );
1379
+ }
1380
+
1381
+ if (filters.osNames && filters.osNames.length > 0) {
1382
+ statement.append(
1383
+ SQL` AND aggOsName IN (${{
1384
+ type: TableColumnType.Text,
1385
+ value: new Includes(filters.osNames),
1386
+ }})`,
1387
+ );
1388
+ }
1389
+
1390
+ if (filters.deviceTypes && filters.deviceTypes.length > 0) {
1391
+ statement.append(
1392
+ SQL` AND aggDeviceType IN (${{
1393
+ type: TableColumnType.Text,
1394
+ value: new Includes(filters.deviceTypes),
1395
+ }})`,
1396
+ );
1397
+ }
1398
+
1399
+ if (filters.countryCodes && filters.countryCodes.length > 0) {
1400
+ statement.append(
1401
+ SQL` AND aggCountryCode IN (${{
1402
+ type: TableColumnType.Text,
1403
+ value: new Includes(filters.countryCodes),
1404
+ }})`,
1405
+ );
1406
+ }
1407
+
1408
+ if (filters.identifiedUserKey) {
1409
+ statement.append(
1410
+ SQL` AND aggIdentifiedUserKey = ${{
1411
+ type: TableColumnType.Text,
1412
+ value: filters.identifiedUserKey,
1413
+ }}`,
1414
+ );
1415
+ }
1416
+
1417
+ if (filters.route) {
1418
+ /*
1419
+ * `has`, not a Search/LIKE. StatementGenerator's own comment calls
1420
+ * restoring the exact-match array fast path "the single biggest
1421
+ * performance fix" - a lowerUTF8 arrayExists has no bloom
1422
+ * pre-filter and full-scans the table.
1423
+ *
1424
+ * The argMax expression is appended as raw SQL rather than
1425
+ * interpolated into the template: a plain string substituted into
1426
+ * an SQL`` literal is bound as an Identifier and would be quoted.
1427
+ */
1428
+ statement.append(` AND has(${argMaxColumn("routes")}, `);
1429
+ statement.append(
1430
+ SQL`${{
1431
+ type: TableColumnType.Text,
1432
+ value: filters.route,
1433
+ }})`,
1434
+ );
1435
+ }
1436
+
1437
+ if (
1438
+ filters.minDurationMs !== undefined &&
1439
+ Number.isFinite(filters.minDurationMs)
1440
+ ) {
1441
+ statement.append(
1442
+ SQL` AND aggDurationMs >= ${{
1443
+ type: TableColumnType.Decimal,
1444
+ value: filters.minDurationMs,
1445
+ }}`,
1446
+ );
1447
+ }
1448
+ }
1449
+ }