@oneuptime/common 12.0.32 → 12.0.34

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 (1191) hide show
  1. package/Models/AnalyticsModels/RumSession.ts +117 -1
  2. package/Models/AnalyticsModels/RumSessionChunk.ts +13 -0
  3. package/Models/AnalyticsModels/Span.ts +14 -0
  4. package/Models/DatabaseModels/AlertCustomField.ts +77 -3
  5. package/Models/DatabaseModels/ApiKeyPermission.ts +3 -27
  6. package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
  7. package/Models/DatabaseModels/IncidentCustomField.ts +77 -3
  8. package/Models/DatabaseModels/Index.ts +10 -0
  9. package/Models/DatabaseModels/InventoryItemCustomField.ts +77 -3
  10. package/Models/DatabaseModels/Monitor.ts +76 -0
  11. package/Models/DatabaseModels/MonitorCustomField.ts +77 -3
  12. package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
  13. package/Models/DatabaseModels/NetworkDevice.ts +176 -1
  14. package/Models/DatabaseModels/NetworkSite.ts +201 -2
  15. package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
  16. package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
  17. package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +77 -3
  18. package/Models/DatabaseModels/RumApplication.ts +6 -6
  19. package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +77 -3
  20. package/Models/DatabaseModels/StatusPageCustomField.ts +77 -3
  21. package/Models/DatabaseModels/TeamCustomField.ts +77 -3
  22. package/Models/DatabaseModels/TeamMember.ts +0 -9
  23. package/Models/DatabaseModels/TeamMemberCustomField.ts +77 -3
  24. package/Models/DatabaseModels/TeamPermission.ts +3 -24
  25. package/Models/DatabaseModels/TelemetryException.ts +119 -0
  26. package/Models/DatabaseModels/TelemetryIngestionKey.ts +260 -0
  27. package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
  28. package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
  29. package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
  30. package/Models/DatabaseModels/UserTelegram.ts +0 -4
  31. package/Scripts/benchmark-fanin-capacity.js +181 -0
  32. package/Server/API/EnterpriseLicenseAPI.ts +391 -64
  33. package/Server/API/LlmProviderAPI.ts +137 -22
  34. package/Server/API/TelemetryAPI.ts +1284 -164
  35. package/Server/API/UserNotificationSettingAPI.ts +55 -0
  36. package/Server/API/UserTelegramAPI.ts +48 -4
  37. package/Server/EnvironmentConfig.ts +49 -2
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
  40. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
  41. package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.ts +91 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.ts +67 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.ts +139 -0
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.ts +121 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
  49. package/Server/Infrastructure/QueueWorker.ts +59 -23
  50. package/Server/Infrastructure/Semaphore.ts +2 -0
  51. package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
  52. package/Server/Middleware/ProjectAuthorization.ts +11 -0
  53. package/Server/Middleware/SCIMAuthorization.ts +12 -0
  54. package/Server/Middleware/TelemetryIngest.ts +464 -7
  55. package/Server/Services/AIBillingService.ts +101 -27
  56. package/Server/Services/AccessTokenService.ts +1 -0
  57. package/Server/Services/AlertCustomFieldService.ts +98 -0
  58. package/Server/Services/AlertService.ts +37 -0
  59. package/Server/Services/ApiKeyPermissionService.ts +461 -29
  60. package/Server/Services/CustomFieldMappingService.ts +879 -0
  61. package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
  62. package/Server/Services/EnterpriseLicenseService.ts +55 -0
  63. package/Server/Services/GlobalConfigService.ts +194 -0
  64. package/Server/Services/IncidentCustomFieldService.ts +98 -0
  65. package/Server/Services/IncidentService.ts +35 -0
  66. package/Server/Services/Index.ts +10 -0
  67. package/Server/Services/MetricService.ts +194 -0
  68. package/Server/Services/MonitorService.ts +175 -21
  69. package/Server/Services/MonitorStatusTimelineService.ts +150 -8
  70. package/Server/Services/MonitorTemplateService.ts +217 -1
  71. package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
  72. package/Server/Services/NetworkAlertPolicyService.ts +944 -0
  73. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +87 -35
  74. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
  75. package/Server/Services/NetworkDeviceService.ts +1032 -73
  76. package/Server/Services/NetworkSiteService.ts +1502 -129
  77. package/Server/Services/NetworkSiteTypeService.ts +1216 -0
  78. package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
  79. package/Server/Services/NotificationService.ts +118 -28
  80. package/Server/Services/ProjectService.ts +127 -48
  81. package/Server/Services/RoutineEmailSettingsService.ts +73 -0
  82. package/Server/Services/RumSessionReplayViewService.ts +104 -24
  83. package/Server/Services/ScheduledMaintenanceCustomFieldService.ts +98 -0
  84. package/Server/Services/ScheduledMaintenanceService.ts +32 -0
  85. package/Server/Services/StatusPagePrivateUserService.ts +103 -3
  86. package/Server/Services/TeamMemberService.ts +78 -0
  87. package/Server/Services/TeamPermissionService.ts +235 -3
  88. package/Server/Services/TelemetryIngestionKeyService.ts +722 -19
  89. package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
  90. package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
  91. package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
  92. package/Server/Services/UserNotificationSettingService.ts +90 -25
  93. package/Server/Services/UserService.ts +95 -0
  94. package/Server/Services/UserTelegramService.ts +326 -5
  95. package/Server/Types/Database/QueryHelper.ts +4 -2
  96. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
  97. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
  98. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
  99. package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
  100. package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
  101. package/Server/Utils/APIKey/AccessPermission.ts +5 -2
  102. package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
  103. package/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.ts +54 -0
  104. package/Server/Utils/CustomField/CustomFieldMappingRegistry.ts +415 -0
  105. package/Server/Utils/CustomField/CustomFieldMappingValidator.ts +335 -0
  106. package/Server/Utils/DataSource/EgressGuard.ts +177 -8
  107. package/Server/Utils/DataSource/HttpFetch.ts +9 -2
  108. package/Server/Utils/EmailRollup/EmailRollupConstants.ts +131 -0
  109. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +925 -0
  110. package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
  111. package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
  112. package/Server/Utils/FrontendEnvironment.ts +40 -0
  113. package/Server/Utils/LLM/LLMService.ts +78 -0
  114. package/Server/Utils/LogRedaction.ts +28 -0
  115. package/Server/Utils/Logger.ts +90 -1
  116. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +338 -77
  117. package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
  118. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
  119. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +30 -4
  120. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
  121. package/Server/Utils/Monitor/MonitorAlert.ts +29 -6
  122. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
  123. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +159 -15
  124. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
  125. package/Server/Utils/Monitor/MonitorIncident.ts +22 -6
  126. package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
  127. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +72 -0
  128. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
  129. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
  130. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
  131. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
  132. package/Server/Utils/Monitor/SeriesContextEnricher.ts +304 -0
  133. package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
  134. package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
  135. package/Server/Utils/OutboundUserAgent.ts +152 -0
  136. package/Server/Utils/SSRFProtection.ts +217 -10
  137. package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +239 -138
  138. package/Server/Utils/SessionReplay/SessionReplayHealthCounters.ts +305 -0
  139. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +1430 -289
  140. package/Server/Utils/StartServer.ts +53 -36
  141. package/Server/Utils/TelegramVerificationToken.ts +185 -0
  142. package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
  143. package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
  144. package/Server/Utils/Telemetry/PinServiceName.ts +197 -0
  145. package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
  146. package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +38 -16
  147. package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +92 -0
  148. package/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.ts +217 -0
  149. package/Server/Utils/Telemetry.ts +198 -51
  150. package/Server/Utils/VM/VMAPI.ts +1 -0
  151. package/Server/Utils/VM/VMRunner.ts +975 -95
  152. package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
  153. package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +202 -0
  154. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
  155. package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
  156. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
  157. package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +404 -0
  158. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
  159. package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
  160. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +486 -9
  161. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
  162. package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
  163. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
  164. package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
  165. package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
  166. package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
  167. package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
  168. package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
  169. package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
  170. package/Tests/App/Dashboard/NotificationEmailPreferences.test.tsx +399 -0
  171. package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
  172. package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
  173. package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
  174. package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
  175. package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
  176. package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
  177. package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
  178. package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
  179. package/Tests/App/StatusPage/StatusPageLastUpdated.test.tsx +263 -0
  180. package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
  181. package/Tests/App/StatusPage/StatusPageOverviewLiveAndSearch.test.tsx +753 -0
  182. package/Tests/App/StatusPage/StatusPageResourceSearchBox.test.tsx +224 -0
  183. package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +262 -0
  184. package/Tests/Models/CustomFieldMappingColumns.test.ts +166 -0
  185. package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +20 -6
  186. package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
  187. package/Tests/ResponsiveVisibility.test.ts +115 -0
  188. package/Tests/ResponsiveVisibility.ts +183 -0
  189. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
  190. package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
  191. package/Tests/Server/API/SessionReplayAPI.test.ts +1940 -216
  192. package/Tests/Server/API/UserNotificationSettingAPI.test.ts +186 -0
  193. package/Tests/Server/API/UserTelegramAPISecurity.test.ts +231 -0
  194. package/Tests/Server/EnvironmentConfigFrontendSecurity.test.ts +234 -0
  195. package/Tests/Server/Infrastructure/Postgres/CustomFieldValueMappingMigration.test.ts +202 -0
  196. package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +41 -0
  197. package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
  198. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
  199. package/Tests/Server/Infrastructure/Postgres/SessionReplayRecordEverySessionByDefaultMigration.test.ts +169 -0
  200. package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
  201. package/Tests/Server/Infrastructure/QueueWorkerTimeout.test.ts +210 -0
  202. package/Tests/Server/Infrastructure/TelemetryExporterDeploymentConfig.test.ts +130 -0
  203. package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -1
  204. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +1163 -0
  205. package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +5 -3
  206. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
  207. package/Tests/Server/Services/AddTelemetryIngestionKeyTypeMigration.test.ts +555 -0
  208. package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +678 -0
  209. package/Tests/Server/Services/ApiKeyPermissionService.test.ts +276 -28
  210. package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
  211. package/Tests/Server/Services/CustomFieldDropdownOptionsColumnWidth.test.ts +431 -0
  212. package/Tests/Server/Services/CustomFieldMappingService.test.ts +850 -0
  213. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +32 -0
  214. package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
  215. package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
  216. package/Tests/Server/Services/GlobalConfigService.test.ts +414 -1
  217. package/Tests/Server/Services/MetricRawEntityKeyPrune.test.ts +592 -0
  218. package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
  219. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
  220. package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
  221. package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
  222. package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
  223. package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
  224. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +273 -5
  225. package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
  226. package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
  227. package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
  228. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
  229. package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
  230. package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
  231. package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
  232. package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
  233. package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
  234. package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
  235. package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
  236. package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
  237. package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
  238. package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
  239. package/Tests/Server/Services/RoutineEmailSettingsPostgres.test.ts +329 -0
  240. package/Tests/Server/Services/RumSessionReplayViewService.test.ts +267 -0
  241. package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
  242. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +9 -0
  243. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +9 -0
  244. package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +834 -0
  245. package/Tests/Server/Services/TelemetryIngestionKeyPolicyResolution.test.ts +814 -0
  246. package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +998 -0
  247. package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
  248. package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
  249. package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
  250. package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
  251. package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +997 -0
  252. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +110 -1
  253. package/Tests/Server/Services/UserTelegramVerificationSecurity.test.ts +688 -0
  254. package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
  255. package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
  256. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
  257. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
  258. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
  259. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
  260. package/Tests/Server/Utils/AI/SRE/Insights/FixRouting.test.ts +497 -0
  261. package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +383 -0
  262. package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +7 -3
  263. package/Tests/Server/Utils/AnalyticsDatabase/ClusterConfig.test.ts +315 -0
  264. package/Tests/Server/Utils/Captcha.test.ts +422 -0
  265. package/Tests/Server/Utils/CustomField/CustomFieldMappingValidator.test.ts +437 -0
  266. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +300 -11
  267. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
  268. package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
  269. package/Tests/Server/Utils/EmailRollup/EmailRollupBurstWindow.test.ts +83 -0
  270. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
  271. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
  272. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerPreferences.test.ts +362 -0
  273. package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
  274. package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +828 -0
  275. package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
  276. package/Tests/Server/Utils/FrontendEnvironment.test.ts +190 -0
  277. package/Tests/Server/Utils/LogRedaction.test.ts +26 -0
  278. package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +23 -9
  279. package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
  280. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +584 -0
  281. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
  282. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestHeaderCriteria.test.ts +236 -0
  283. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
  284. package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
  285. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +437 -0
  286. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
  287. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
  288. package/Tests/Server/Utils/Monitor/MonitorTemplateUtilSeriesContext.test.ts +176 -0
  289. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
  290. package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
  291. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
  292. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
  293. package/Tests/Server/Utils/Monitor/SeriesContextEnricher.test.ts +356 -0
  294. package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
  295. package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
  296. package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
  297. package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +595 -0
  298. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
  299. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +198 -1
  300. package/Tests/Server/Utils/SessionReplay/SessionReplayHealthCounters.test.ts +453 -0
  301. package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1378 -0
  302. package/Tests/Server/Utils/SessionReplayOriginAllowListRefactor.test.ts +420 -0
  303. package/Tests/Server/Utils/TelegramVerificationToken.test.ts +253 -0
  304. package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
  305. package/Tests/Server/Utils/Telemetry/PinServiceName.test.ts +666 -0
  306. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriterCapacity.test.ts +458 -0
  307. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +424 -0
  308. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.test.ts +528 -0
  309. package/Tests/Server/Utils/Telemetry.test.ts +456 -66
  310. package/Tests/Server/Utils/TelemetryExporterEnvironment.test.ts +56 -0
  311. package/Tests/Server/Utils/VM/VMRunnerHostBridgeLatency.test.ts +74 -0
  312. package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +100 -7
  313. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +1176 -6
  314. package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +220 -0
  315. package/Tests/Types/CustomField/CustomFieldValueMapping.test.ts +348 -0
  316. package/Tests/Types/JSONFunctions.test.ts +260 -0
  317. package/Tests/Types/Monitor/CephAlertTemplates.test.ts +422 -53
  318. package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
  319. package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +495 -15
  320. package/Tests/Types/Monitor/DockerSwarmAlertTemplates.test.ts +191 -45
  321. package/Tests/Types/Monitor/HostAlertTemplates.test.ts +370 -42
  322. package/Tests/Types/Monitor/IotAlertTemplates.test.ts +375 -20
  323. package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +636 -42
  324. package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +189 -0
  325. package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +95 -14
  326. package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
  327. package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
  328. package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
  329. package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
  330. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
  331. package/Tests/Types/Monitor/PodmanAlertTemplates.test.ts +190 -21
  332. package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +352 -22
  333. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationAlertDebuggability.test.ts +363 -0
  334. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +93 -18
  335. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +259 -0
  336. package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +476 -0
  337. package/Tests/Types/Monitor/RumAlertTemplates.test.ts +136 -0
  338. package/Tests/Types/Monitor/SeriesContext/SeriesDebugHints.test.ts +661 -0
  339. package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +507 -0
  340. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +270 -0
  341. package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +38 -10
  342. package/Tests/Types/Monitor/Utils/RecommendationCriteriaAssertions.ts +102 -0
  343. package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
  344. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
  345. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
  346. package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
  347. package/Tests/Types/NotificationSetting/RoutineEmailEvents.test.ts +47 -0
  348. package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +608 -0
  349. package/Tests/Types/Rum/SessionReplayCustomEvents.test.ts +434 -0
  350. package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
  351. package/Tests/Types/WebsiteRequest.test.ts +285 -3
  352. package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
  353. package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +16 -3
  354. package/Tests/UI/Components/Charts/ChartTrailingBucketGap.test.ts +691 -0
  355. package/Tests/UI/Components/ComponentsModal.test.tsx +12 -4
  356. package/Tests/UI/Components/ComponentsModalUsability.test.tsx +518 -0
  357. package/Tests/UI/Components/CustomFields/CustomFieldsDetailMapping.test.tsx +324 -0
  358. package/Tests/UI/Components/CustomFields/MapFromCustomFieldInput.test.tsx +176 -0
  359. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +484 -0
  360. package/Tests/UI/Components/HeaderRightRail.test.tsx +157 -0
  361. package/Tests/UI/Components/IconDropdownItem.test.tsx +102 -0
  362. package/Tests/UI/Components/JSONTablePrototypePollution.test.tsx +117 -0
  363. package/Tests/UI/Components/KeyboardShortcutsModal.test.tsx +214 -0
  364. package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +561 -0
  365. package/Tests/UI/Components/MonitorGraphs/UptimeBarDayModal.test.tsx +302 -0
  366. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +43 -12
  367. package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
  368. package/Tests/UI/Components/ShortcutDialogGuard.test.tsx +74 -0
  369. package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
  370. package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
  371. package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
  372. package/Tests/UI/Components/StatusPage/ResourceGroupSectionAutoExpand.test.tsx +248 -0
  373. package/Tests/UI/Components/TableCellWrapping.test.tsx +625 -0
  374. package/Tests/UI/Components/TableLoadingStates.test.tsx +205 -0
  375. package/Tests/UI/Components/Workflow/NodePlacement.test.ts +148 -0
  376. package/Tests/UI/Components/Workflow/Workflow.test.tsx +981 -0
  377. package/Tests/UI/ConfigBrowserTelemetry.test.ts +70 -0
  378. package/Tests/UI/Rum/ChunkLoader.test.ts +1036 -2
  379. package/Tests/UI/Rum/FidelityNotices.test.ts +187 -0
  380. package/Tests/UI/Rum/InactivityMap.test.ts +341 -0
  381. package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +259 -0
  382. package/Tests/UI/Rum/RecordingHealthCard.test.tsx +855 -0
  383. package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +594 -0
  384. package/Tests/UI/Rum/ReplayCard.test.tsx +451 -0
  385. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +536 -0
  386. package/Tests/UI/Rum/ReplayEngine.test.ts +2503 -0
  387. package/Tests/UI/Rum/ReplayEngineTypes.test.ts +171 -0
  388. package/Tests/UI/Rum/ReplayHeader.test.tsx +711 -0
  389. package/Tests/UI/Rum/ReplayLink.test.tsx +119 -0
  390. package/Tests/UI/Rum/ReplayPinControl.test.tsx +408 -0
  391. package/Tests/UI/Rum/ReplayPlaybackIntent.test.ts +152 -0
  392. package/Tests/UI/Rum/ReplayRail.test.tsx +1296 -0
  393. package/Tests/UI/Rum/ReplayRailDetail.test.tsx +900 -0
  394. package/Tests/UI/Rum/ReplayScrubber.test.tsx +763 -147
  395. package/Tests/UI/Rum/ReplaySignalTypes.test.ts +189 -0
  396. package/Tests/UI/Rum/ReplaySignals.test.ts +1579 -0
  397. package/Tests/UI/Rum/ReplayStage.test.tsx +396 -473
  398. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +918 -0
  399. package/Tests/UI/Rum/ReplayTimeline.test.tsx +696 -0
  400. package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +499 -0
  401. package/Tests/UI/Rum/SessionReplaySearchBar.test.tsx +346 -0
  402. package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +545 -0
  403. package/Tests/UI/Rum/SessionReplayTable.test.tsx +991 -0
  404. package/Tests/UI/Rum/TargetedCapturePanel.test.tsx +254 -0
  405. package/Tests/UI/Telemetry/BrowserExporterIsolation.test.ts +71 -0
  406. package/Tests/UI/Utils/GlobalKeyboardShortcut.test.ts +344 -0
  407. package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
  408. package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
  409. package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
  410. package/Tests/Utils/API.test.ts +308 -0
  411. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
  412. package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
  413. package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
  414. package/Tests/Utils/HTTPResponseBodyReader.test.ts +323 -0
  415. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
  416. package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
  417. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
  418. package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
  419. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
  420. package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
  421. package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
  422. package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
  423. package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
  424. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
  425. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
  426. package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
  427. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
  428. package/Tests/Utils/NetworkDiscovery/DiscoveryScanStatus.test.ts +117 -0
  429. package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
  430. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
  431. package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
  432. package/Tests/Utils/Rum/ChunkMath.test.ts +83 -0
  433. package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +993 -0
  434. package/Tests/Utils/Rum/SessionReplayStringMap.test.ts +245 -0
  435. package/Tests/Utils/StatusPage/ResourceSearch.test.ts +631 -0
  436. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
  437. package/Tests/Utils/Telemetry/OriginAllowList.test.ts +633 -0
  438. package/Tests/Utils/Uptime/DayUptimeGraphUtil.test.ts +461 -0
  439. package/Tests/Utils/ValueFormatter.test.ts +148 -0
  440. package/Types/AI/ExceptionAIClassification.ts +10 -24
  441. package/Types/CustomField/CustomFieldMappingCatalog.ts +161 -0
  442. package/Types/CustomField/CustomFieldMappingSourceResource.ts +19 -0
  443. package/Types/CustomField/CustomFieldValueMapping.ts +288 -0
  444. package/Types/Email/EmailTemplateType.ts +2 -0
  445. package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
  446. package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
  447. package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
  448. package/Types/Exception/ApiException.ts +10 -0
  449. package/Types/Exception/BadDataException.ts +11 -0
  450. package/Types/Exception/BadRequestException.ts +11 -0
  451. package/Types/Exception/Exception.ts +65 -0
  452. package/Types/Exception/ForbiddenException.ts +10 -0
  453. package/Types/Exception/NotAuthenticatedException.ts +10 -0
  454. package/Types/Exception/NotAuthorizedException.ts +10 -0
  455. package/Types/Exception/NotFoundException.ts +11 -0
  456. package/Types/Exception/PayloadTooLargeException.ts +11 -0
  457. package/Types/Exception/PaymentRequiredException.ts +10 -0
  458. package/Types/Exception/ServiceUnavailableException.ts +10 -0
  459. package/Types/Exception/SsoAuthorizationException.ts +10 -0
  460. package/Types/Exception/TenantNotFoundException.ts +11 -0
  461. package/Types/Exception/TimeoutException.ts +10 -0
  462. package/Types/Exception/TooManyRequestsException.ts +10 -0
  463. package/Types/Exception/UnableToReachServer.ts +10 -0
  464. package/Types/Exception/WebsiteRequestException.ts +10 -0
  465. package/Types/Icon/IconProp.ts +1 -0
  466. package/Types/JSONFunctions.ts +189 -43
  467. package/Types/Monitor/CephAlertTemplates.ts +157 -195
  468. package/Types/Monitor/CriteriaFilter.ts +60 -2
  469. package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
  470. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
  471. package/Types/Monitor/DockerAlertTemplates.ts +338 -128
  472. package/Types/Monitor/DockerSwarmAlertTemplates.ts +95 -112
  473. package/Types/Monitor/HostAlertTemplates.ts +302 -130
  474. package/Types/Monitor/IotAlertTemplates.ts +112 -104
  475. package/Types/Monitor/KubernetesAlertTemplates.ts +415 -224
  476. package/Types/Monitor/KubernetesMetricCatalog.ts +23 -19
  477. package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
  478. package/Types/Monitor/MonitorMetricType.ts +71 -0
  479. package/Types/Monitor/MonitorStep.ts +76 -0
  480. package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
  481. package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
  482. package/Types/Monitor/MonitorType.ts +47 -1
  483. package/Types/Monitor/PodmanAlertTemplates.ts +116 -163
  484. package/Types/Monitor/ProxmoxAlertTemplates.ts +217 -99
  485. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +98 -6
  486. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +44 -7
  487. package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +383 -0
  488. package/Types/Monitor/RumAlertTemplates.ts +46 -7
  489. package/Types/Monitor/SeriesContext/SeriesDebugHints.ts +596 -0
  490. package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +554 -0
  491. package/Types/Monitor/ServiceAlertTemplates.ts +98 -11
  492. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
  493. package/Types/Monitor/SqlConnectionConfig.ts +31 -0
  494. package/Types/Monitor/UptimeHistoryLabels.ts +56 -0
  495. package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
  496. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
  497. package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
  498. package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
  499. package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
  500. package/Types/NotificationSetting/RoutineEmailEvents.ts +30 -0
  501. package/Types/Permission.ts +90 -0
  502. package/Types/Probe/ProbeMonitorResponse.ts +16 -0
  503. package/Types/Rum/SessionReplay.ts +209 -0
  504. package/Types/Rum/SessionReplayApi.ts +722 -0
  505. package/Types/Rum/SessionReplayCaptureTrigger.ts +21 -12
  506. package/Types/Rum/SessionReplayConsentMode.ts +11 -7
  507. package/Types/Rum/SessionReplayCustomEvents.ts +549 -0
  508. package/Types/Rum/SessionReplayHealth.ts +238 -0
  509. package/Types/Telemetry/ErrorClass.ts +274 -0
  510. package/Types/Telemetry/TelemetryIngestSurface.ts +95 -0
  511. package/Types/Telemetry/TelemetryIngestionKeyPolicy.ts +75 -0
  512. package/Types/Telemetry/TelemetryIngestionKeyType.ts +29 -0
  513. package/Types/Telemetry/UnitOfWork.ts +59 -0
  514. package/Types/WebsiteRequest.ts +85 -3
  515. package/UI/Components/Charts/Area/AreaChart.tsx +13 -2
  516. package/UI/Components/Charts/Bar/BarChart.tsx +6 -2
  517. package/UI/Components/Charts/Line/LineChart.tsx +13 -2
  518. package/UI/Components/Charts/Types/XAxis/XAxis.ts +29 -0
  519. package/UI/Components/Charts/Utils/DataPoint.ts +22 -3
  520. package/UI/Components/Charts/Utils/TimeAnnotation.ts +76 -9
  521. package/UI/Components/Charts/Utils/XAxis.ts +217 -0
  522. package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
  523. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +143 -25
  524. package/UI/Components/CustomFields/MapFromCustomFieldInput.tsx +216 -0
  525. package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
  526. package/UI/Components/Graphs/DayUptimeGraph.tsx +173 -8
  527. package/UI/Components/Graphs/UptimeBarTooltip.tsx +22 -278
  528. package/UI/Components/Graphs/UptimeDaySummary.tsx +327 -0
  529. package/UI/Components/Header/Header.tsx +25 -9
  530. package/UI/Components/Header/IconDropdown/IconDropdownItem.tsx +10 -1
  531. package/UI/Components/Header/IconDropdown/IconDropdownMenu.tsx +6 -1
  532. package/UI/Components/Header/ProjectPicker/ProjectPicker.tsx +6 -1
  533. package/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.tsx +6 -1
  534. package/UI/Components/Icon/Icon.tsx +11 -0
  535. package/UI/Components/JSONTable/JSONTable.tsx +2 -2
  536. package/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.tsx +125 -0
  537. package/UI/Components/KeyboardShortcut/Screenshots/README.md +19 -0
  538. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-command-palette.png +0 -0
  539. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog-dark.png +0 -0
  540. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog.png +0 -0
  541. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-help-menu.png +0 -0
  542. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-narrow.png +0 -0
  543. package/UI/Components/Modal/Modal.tsx +2 -8
  544. package/UI/Components/ModelTable/Column.ts +15 -0
  545. package/UI/Components/Monitor/SeriesDebugCommandsViewer.tsx +64 -0
  546. package/UI/Components/Monitor/SeriesLabelsViewer.tsx +93 -0
  547. package/UI/Components/MonitorGraphs/Uptime.tsx +14 -2
  548. package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +63 -10
  549. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +88 -0
  550. package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
  551. package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
  552. package/UI/Components/SideMenu/SideMenu.tsx +123 -5
  553. package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
  554. package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
  555. package/UI/Components/SideOver/SideOver.tsx +21 -20
  556. package/UI/Components/StatusPage/ResourceGroupSection.tsx +40 -0
  557. package/UI/Components/Table/CellClassName.ts +81 -0
  558. package/UI/Components/Table/TableRow.tsx +20 -14
  559. package/UI/Components/Table/TableSkeletonRows.tsx +9 -9
  560. package/UI/Components/Table/Types/Column.ts +36 -0
  561. package/UI/Components/Tooltip/Tooltip.tsx +11 -1
  562. package/UI/Components/Workflow/ComponentsModal.tsx +60 -39
  563. package/UI/Components/Workflow/NodePlacement.ts +57 -0
  564. package/UI/Components/Workflow/Workflow.tsx +47 -18
  565. package/UI/Config.ts +15 -33
  566. package/UI/Utils/GlobalKeyboardShortcut.ts +208 -0
  567. package/UI/Utils/PageScrollLock.ts +79 -3
  568. package/UI/Utils/PermissionGate.ts +61 -0
  569. package/UI/Utils/SensitiveUrlToken.ts +112 -0
  570. package/UI/Utils/Telemetry/BrowserTelemetryConfig.ts +28 -0
  571. package/UI/Utils/Telemetry/Telemetry.ts +10 -8
  572. package/UI/Utils/TestLLMProvider.ts +11 -0
  573. package/Utils/API.ts +129 -3
  574. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
  575. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
  576. package/Utils/HTTPResponseBodyReader.ts +221 -0
  577. package/Utils/Monitor/MonitorMetricType.ts +153 -1
  578. package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
  579. package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
  580. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
  581. package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
  582. package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
  583. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
  584. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
  585. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
  586. package/Utils/NetworkDiscovery/DiscoveryScanStatus.ts +77 -0
  587. package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
  588. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
  589. package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
  590. package/Utils/Rum/ChunkMath.ts +106 -0
  591. package/Utils/Rum/SessionReplayHealth.ts +732 -0
  592. package/Utils/Rum/SessionReplayStringMap.ts +226 -0
  593. package/Utils/Schema/ModelSchema.ts +1 -0
  594. package/Utils/StatusPage/ResourceSearch.ts +290 -0
  595. package/Utils/Telemetry/OriginAllowList.ts +355 -0
  596. package/Utils/Uptime/DayUptimeGraphUtil.ts +205 -0
  597. package/Utils/ValueFormatter.ts +35 -1
  598. package/build/dist/Models/AnalyticsModels/RumSession.js +102 -19
  599. package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -1
  600. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js +11 -9
  601. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js.map +1 -1
  602. package/build/dist/Models/AnalyticsModels/Span.js +14 -0
  603. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  604. package/build/dist/Models/DatabaseModels/AlertCustomField.js +79 -3
  605. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
  606. package/build/dist/Models/DatabaseModels/ApiKeyPermission.js +3 -27
  607. package/build/dist/Models/DatabaseModels/ApiKeyPermission.js.map +1 -1
  608. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
  609. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
  610. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +79 -3
  611. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  612. package/build/dist/Models/DatabaseModels/Index.js +10 -0
  613. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  614. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +79 -3
  615. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -1
  616. package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
  617. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  618. package/build/dist/Models/DatabaseModels/MonitorCustomField.js +79 -3
  619. package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
  620. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
  621. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
  622. package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
  623. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  624. package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
  625. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  626. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
  627. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
  628. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
  629. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
  630. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +79 -3
  631. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
  632. package/build/dist/Models/DatabaseModels/RumApplication.js +6 -6
  633. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  634. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +79 -3
  635. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
  636. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +79 -3
  637. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
  638. package/build/dist/Models/DatabaseModels/TeamCustomField.js +79 -3
  639. package/build/dist/Models/DatabaseModels/TeamCustomField.js.map +1 -1
  640. package/build/dist/Models/DatabaseModels/TeamMember.js +0 -9
  641. package/build/dist/Models/DatabaseModels/TeamMember.js.map +1 -1
  642. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +79 -3
  643. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
  644. package/build/dist/Models/DatabaseModels/TeamPermission.js +3 -24
  645. package/build/dist/Models/DatabaseModels/TeamPermission.js.map +1 -1
  646. package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
  647. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  648. package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js +267 -0
  649. package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
  650. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
  651. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
  652. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
  653. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
  654. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
  655. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
  656. package/build/dist/Models/DatabaseModels/UserTelegram.js +0 -4
  657. package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
  658. package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
  659. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
  660. package/build/dist/Server/API/LlmProviderAPI.js +108 -13
  661. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
  662. package/build/dist/Server/API/TelemetryAPI.js +769 -109
  663. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  664. package/build/dist/Server/API/UserNotificationSettingAPI.js +35 -0
  665. package/build/dist/Server/API/UserNotificationSettingAPI.js.map +1 -0
  666. package/build/dist/Server/API/UserTelegramAPI.js +28 -6
  667. package/build/dist/Server/API/UserTelegramAPI.js.map +1 -1
  668. package/build/dist/Server/EnvironmentConfig.js +41 -2
  669. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  670. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
  671. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
  672. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
  673. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
  674. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
  675. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
  676. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
  677. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
  678. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
  679. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
  680. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
  681. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
  682. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js +60 -0
  683. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js.map +1 -0
  684. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js +53 -0
  685. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js.map +1 -0
  686. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js +82 -0
  687. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js.map +1 -0
  688. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js +46 -0
  689. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js.map +1 -0
  690. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
  691. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  692. package/build/dist/Server/Infrastructure/QueueWorker.js +52 -12
  693. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  694. package/build/dist/Server/Infrastructure/Semaphore.js +1 -0
  695. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  696. package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
  697. package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
  698. package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
  699. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  700. package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
  701. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
  702. package/build/dist/Server/Middleware/TelemetryIngest.js +326 -8
  703. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  704. package/build/dist/Server/Services/AIBillingService.js +70 -16
  705. package/build/dist/Server/Services/AIBillingService.js.map +1 -1
  706. package/build/dist/Server/Services/AccessTokenService.js +1 -0
  707. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  708. package/build/dist/Server/Services/AlertCustomFieldService.js +93 -0
  709. package/build/dist/Server/Services/AlertCustomFieldService.js.map +1 -1
  710. package/build/dist/Server/Services/AlertService.js +34 -0
  711. package/build/dist/Server/Services/AlertService.js.map +1 -1
  712. package/build/dist/Server/Services/ApiKeyPermissionService.js +331 -28
  713. package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
  714. package/build/dist/Server/Services/CustomFieldMappingService.js +614 -0
  715. package/build/dist/Server/Services/CustomFieldMappingService.js.map +1 -0
  716. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
  717. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
  718. package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
  719. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  720. package/build/dist/Server/Services/GlobalConfigService.js +133 -0
  721. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  722. package/build/dist/Server/Services/IncidentCustomFieldService.js +93 -0
  723. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  724. package/build/dist/Server/Services/IncidentService.js +32 -0
  725. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  726. package/build/dist/Server/Services/Index.js +10 -0
  727. package/build/dist/Server/Services/Index.js.map +1 -1
  728. package/build/dist/Server/Services/MetricService.js +163 -0
  729. package/build/dist/Server/Services/MetricService.js.map +1 -1
  730. package/build/dist/Server/Services/MonitorService.js +148 -21
  731. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  732. package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
  733. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  734. package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
  735. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  736. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
  737. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
  738. package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
  739. package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
  740. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +89 -36
  741. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  742. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
  743. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  744. package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
  745. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  746. package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
  747. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  748. package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
  749. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
  750. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
  751. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
  752. package/build/dist/Server/Services/NotificationService.js +80 -17
  753. package/build/dist/Server/Services/NotificationService.js.map +1 -1
  754. package/build/dist/Server/Services/ProjectService.js +88 -30
  755. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  756. package/build/dist/Server/Services/RoutineEmailSettingsService.js +69 -0
  757. package/build/dist/Server/Services/RoutineEmailSettingsService.js.map +1 -0
  758. package/build/dist/Server/Services/RumSessionReplayViewService.js +86 -24
  759. package/build/dist/Server/Services/RumSessionReplayViewService.js.map +1 -1
  760. package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js +93 -0
  761. package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js.map +1 -1
  762. package/build/dist/Server/Services/ScheduledMaintenanceService.js +29 -0
  763. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  764. package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
  765. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  766. package/build/dist/Server/Services/TeamMemberService.js +62 -2
  767. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  768. package/build/dist/Server/Services/TeamPermissionService.js +166 -3
  769. package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
  770. package/build/dist/Server/Services/TelemetryIngestionKeyService.js +562 -18
  771. package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
  772. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
  773. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
  774. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
  775. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
  776. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
  777. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
  778. package/build/dist/Server/Services/UserNotificationSettingService.js +66 -20
  779. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  780. package/build/dist/Server/Services/UserService.js +90 -0
  781. package/build/dist/Server/Services/UserService.js.map +1 -1
  782. package/build/dist/Server/Services/UserTelegramService.js +257 -4
  783. package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
  784. package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
  785. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  786. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
  787. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  788. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
  789. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  790. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
  791. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  792. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
  793. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
  794. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
  795. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  796. package/build/dist/Server/Utils/APIKey/AccessPermission.js +2 -2
  797. package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
  798. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
  799. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
  800. package/build/dist/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.js +27 -0
  801. package/build/dist/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.js.map +1 -0
  802. package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js +226 -0
  803. package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js.map +1 -0
  804. package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js +189 -0
  805. package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js.map +1 -0
  806. package/build/dist/Server/Utils/DataSource/EgressGuard.js +121 -7
  807. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  808. package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
  809. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  810. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +124 -0
  811. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
  812. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +733 -0
  813. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
  814. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
  815. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
  816. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
  817. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
  818. package/build/dist/Server/Utils/FrontendEnvironment.js +33 -0
  819. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -0
  820. package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
  821. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  822. package/build/dist/Server/Utils/LogRedaction.js +28 -0
  823. package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
  824. package/build/dist/Server/Utils/Logger.js +73 -1
  825. package/build/dist/Server/Utils/Logger.js.map +1 -1
  826. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +287 -68
  827. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  828. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
  829. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
  830. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  831. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  832. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +20 -4
  833. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  834. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
  835. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  836. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +29 -6
  837. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  838. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
  839. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  840. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +125 -13
  841. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  842. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
  843. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  844. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
  845. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  846. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
  847. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  848. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +54 -0
  849. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  850. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
  851. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  852. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
  853. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  854. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
  855. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  856. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
  857. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  858. package/build/dist/Server/Utils/Monitor/SeriesContextEnricher.js +237 -0
  859. package/build/dist/Server/Utils/Monitor/SeriesContextEnricher.js.map +1 -0
  860. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
  861. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
  862. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
  863. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
  864. package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
  865. package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
  866. package/build/dist/Server/Utils/SSRFProtection.js +136 -9
  867. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  868. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +174 -89
  869. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
  870. package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js +223 -0
  871. package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js.map +1 -0
  872. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +945 -164
  873. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
  874. package/build/dist/Server/Utils/StartServer.js +41 -28
  875. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  876. package/build/dist/Server/Utils/TelegramVerificationToken.js +129 -0
  877. package/build/dist/Server/Utils/TelegramVerificationToken.js.map +1 -0
  878. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
  879. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  880. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
  881. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
  882. package/build/dist/Server/Utils/Telemetry/PinServiceName.js +163 -0
  883. package/build/dist/Server/Utils/Telemetry/PinServiceName.js.map +1 -0
  884. package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
  885. package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
  886. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +28 -15
  887. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -1
  888. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +64 -0
  889. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -0
  890. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js +171 -0
  891. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js.map +1 -0
  892. package/build/dist/Server/Utils/Telemetry.js +162 -46
  893. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  894. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  895. package/build/dist/Server/Utils/VM/VMRunner.js +780 -69
  896. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  897. package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
  898. package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
  899. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +60 -0
  900. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -0
  901. package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js +20 -0
  902. package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js.map +1 -0
  903. package/build/dist/Types/CustomField/CustomFieldValueMapping.js +141 -0
  904. package/build/dist/Types/CustomField/CustomFieldValueMapping.js.map +1 -0
  905. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  906. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  907. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
  908. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
  909. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
  910. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
  911. package/build/dist/Types/Exception/ApiException.js +9 -0
  912. package/build/dist/Types/Exception/ApiException.js.map +1 -1
  913. package/build/dist/Types/Exception/BadDataException.js +10 -0
  914. package/build/dist/Types/Exception/BadDataException.js.map +1 -1
  915. package/build/dist/Types/Exception/BadRequestException.js +10 -0
  916. package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
  917. package/build/dist/Types/Exception/Exception.js +56 -0
  918. package/build/dist/Types/Exception/Exception.js.map +1 -1
  919. package/build/dist/Types/Exception/ForbiddenException.js +9 -0
  920. package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
  921. package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
  922. package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
  923. package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
  924. package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
  925. package/build/dist/Types/Exception/NotFoundException.js +10 -0
  926. package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
  927. package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
  928. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
  929. package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
  930. package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
  931. package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
  932. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
  933. package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
  934. package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
  935. package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
  936. package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
  937. package/build/dist/Types/Exception/TimeoutException.js +9 -0
  938. package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
  939. package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
  940. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
  941. package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
  942. package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
  943. package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
  944. package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
  945. package/build/dist/Types/Icon/IconProp.js +1 -0
  946. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  947. package/build/dist/Types/JSONFunctions.js +118 -37
  948. package/build/dist/Types/JSONFunctions.js.map +1 -1
  949. package/build/dist/Types/Monitor/CephAlertTemplates.js +130 -171
  950. package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
  951. package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
  952. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  953. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
  954. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
  955. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
  956. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
  957. package/build/dist/Types/Monitor/DockerAlertTemplates.js +286 -121
  958. package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
  959. package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js +84 -105
  960. package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js.map +1 -1
  961. package/build/dist/Types/Monitor/HostAlertTemplates.js +250 -122
  962. package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
  963. package/build/dist/Types/Monitor/IotAlertTemplates.js +81 -81
  964. package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -1
  965. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +375 -215
  966. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  967. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +19 -19
  968. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
  969. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
  970. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  971. package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
  972. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  973. package/build/dist/Types/Monitor/MonitorStep.js +54 -0
  974. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  975. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
  976. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
  977. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
  978. package/build/dist/Types/Monitor/MonitorType.js +45 -1
  979. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  980. package/build/dist/Types/Monitor/PodmanAlertTemplates.js +104 -153
  981. package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
  982. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +156 -91
  983. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
  984. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +67 -6
  985. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  986. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +38 -7
  987. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  988. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +261 -0
  989. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -0
  990. package/build/dist/Types/Monitor/RumAlertTemplates.js +46 -7
  991. package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
  992. package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js +422 -0
  993. package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js.map +1 -0
  994. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +441 -0
  995. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -0
  996. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +79 -15
  997. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -1
  998. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
  999. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  1000. package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
  1001. package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
  1002. package/build/dist/Types/Monitor/UptimeHistoryLabels.js +17 -0
  1003. package/build/dist/Types/Monitor/UptimeHistoryLabels.js.map +1 -0
  1004. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
  1005. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
  1006. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
  1007. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
  1008. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
  1009. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
  1010. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
  1011. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
  1012. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
  1013. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
  1014. package/build/dist/Types/NotificationSetting/RoutineEmailEvents.js +29 -0
  1015. package/build/dist/Types/NotificationSetting/RoutineEmailEvents.js.map +1 -0
  1016. package/build/dist/Types/Permission.js +80 -0
  1017. package/build/dist/Types/Permission.js.map +1 -1
  1018. package/build/dist/Types/Rum/SessionReplay.js +117 -0
  1019. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  1020. package/build/dist/Types/Rum/SessionReplayApi.js +181 -0
  1021. package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -0
  1022. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js +21 -12
  1023. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js.map +1 -1
  1024. package/build/dist/Types/Rum/SessionReplayConsentMode.js +11 -7
  1025. package/build/dist/Types/Rum/SessionReplayConsentMode.js.map +1 -1
  1026. package/build/dist/Types/Rum/SessionReplayCustomEvents.js +172 -0
  1027. package/build/dist/Types/Rum/SessionReplayCustomEvents.js.map +1 -0
  1028. package/build/dist/Types/Rum/SessionReplayHealth.js +37 -0
  1029. package/build/dist/Types/Rum/SessionReplayHealth.js.map +1 -0
  1030. package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
  1031. package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
  1032. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +85 -0
  1033. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -0
  1034. package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js +15 -0
  1035. package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js.map +1 -0
  1036. package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.js +30 -0
  1037. package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.js.map +1 -0
  1038. package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
  1039. package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
  1040. package/build/dist/Types/WebsiteRequest.js +55 -3
  1041. package/build/dist/Types/WebsiteRequest.js.map +1 -1
  1042. package/build/dist/UI/Components/Charts/Area/AreaChart.js +13 -2
  1043. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  1044. package/build/dist/UI/Components/Charts/Bar/BarChart.js +6 -2
  1045. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  1046. package/build/dist/UI/Components/Charts/Line/LineChart.js +13 -2
  1047. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  1048. package/build/dist/UI/Components/Charts/Types/XAxis/XAxis.js.map +1 -1
  1049. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -3
  1050. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  1051. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +40 -9
  1052. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
  1053. package/build/dist/UI/Components/Charts/Utils/XAxis.js +186 -0
  1054. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  1055. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
  1056. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  1057. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +80 -6
  1058. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  1059. package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js +118 -0
  1060. package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js.map +1 -0
  1061. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
  1062. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  1063. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +112 -7
  1064. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  1065. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +5 -162
  1066. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
  1067. package/build/dist/UI/Components/Graphs/UptimeDaySummary.js +181 -0
  1068. package/build/dist/UI/Components/Graphs/UptimeDaySummary.js.map +1 -0
  1069. package/build/dist/UI/Components/Header/Header.js +2 -3
  1070. package/build/dist/UI/Components/Header/Header.js.map +1 -1
  1071. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js +2 -1
  1072. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js.map +1 -1
  1073. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js +7 -1
  1074. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js.map +1 -1
  1075. package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js +7 -1
  1076. package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js.map +1 -1
  1077. package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js +7 -1
  1078. package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js.map +1 -1
  1079. package/build/dist/UI/Components/Icon/Icon.js +5 -0
  1080. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  1081. package/build/dist/UI/Components/JSONTable/JSONTable.js +2 -2
  1082. package/build/dist/UI/Components/JSONTable/JSONTable.js.map +1 -1
  1083. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js +35 -0
  1084. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js.map +1 -0
  1085. package/build/dist/UI/Components/Modal/Modal.js +2 -7
  1086. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  1087. package/build/dist/UI/Components/Monitor/SeriesDebugCommandsViewer.js +34 -0
  1088. package/build/dist/UI/Components/Monitor/SeriesDebugCommandsViewer.js.map +1 -0
  1089. package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js +49 -0
  1090. package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js.map +1 -0
  1091. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +1 -1
  1092. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  1093. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +32 -6
  1094. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
  1095. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +77 -0
  1096. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  1097. package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
  1098. package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
  1099. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
  1100. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
  1101. package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
  1102. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  1103. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
  1104. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  1105. package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
  1106. package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
  1107. package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
  1108. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  1109. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +22 -1
  1110. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -1
  1111. package/build/dist/UI/Components/Table/CellClassName.js +55 -0
  1112. package/build/dist/UI/Components/Table/CellClassName.js.map +1 -0
  1113. package/build/dist/UI/Components/Table/TableRow.js +16 -13
  1114. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  1115. package/build/dist/UI/Components/Table/TableSkeletonRows.js +9 -8
  1116. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -1
  1117. package/build/dist/UI/Components/Tooltip/Tooltip.js +25 -1
  1118. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  1119. package/build/dist/UI/Components/Workflow/ComponentsModal.js +47 -30
  1120. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  1121. package/build/dist/UI/Components/Workflow/NodePlacement.js +37 -0
  1122. package/build/dist/UI/Components/Workflow/NodePlacement.js.map +1 -0
  1123. package/build/dist/UI/Components/Workflow/Workflow.js +35 -18
  1124. package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
  1125. package/build/dist/UI/Config.js +10 -20
  1126. package/build/dist/UI/Config.js.map +1 -1
  1127. package/build/dist/UI/Utils/GlobalKeyboardShortcut.js +138 -0
  1128. package/build/dist/UI/Utils/GlobalKeyboardShortcut.js.map +1 -0
  1129. package/build/dist/UI/Utils/PageScrollLock.js +31 -3
  1130. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
  1131. package/build/dist/UI/Utils/PermissionGate.js +42 -1
  1132. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  1133. package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
  1134. package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
  1135. package/build/dist/UI/Utils/Telemetry/BrowserTelemetryConfig.js +14 -0
  1136. package/build/dist/UI/Utils/Telemetry/BrowserTelemetryConfig.js.map +1 -0
  1137. package/build/dist/UI/Utils/Telemetry/Telemetry.js +7 -5
  1138. package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
  1139. package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
  1140. package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
  1141. package/build/dist/Utils/API.js +67 -5
  1142. package/build/dist/Utils/API.js.map +1 -1
  1143. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
  1144. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
  1145. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
  1146. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  1147. package/build/dist/Utils/HTTPResponseBodyReader.js +157 -0
  1148. package/build/dist/Utils/HTTPResponseBodyReader.js.map +1 -0
  1149. package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
  1150. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  1151. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
  1152. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  1153. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
  1154. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
  1155. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
  1156. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  1157. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
  1158. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
  1159. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
  1160. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
  1161. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
  1162. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  1163. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
  1164. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  1165. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
  1166. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
  1167. package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js +69 -0
  1168. package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js.map +1 -0
  1169. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
  1170. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
  1171. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
  1172. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  1173. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
  1174. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
  1175. package/build/dist/Utils/Rum/ChunkMath.js +76 -0
  1176. package/build/dist/Utils/Rum/ChunkMath.js.map +1 -1
  1177. package/build/dist/Utils/Rum/SessionReplayHealth.js +534 -0
  1178. package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -0
  1179. package/build/dist/Utils/Rum/SessionReplayStringMap.js +165 -0
  1180. package/build/dist/Utils/Rum/SessionReplayStringMap.js.map +1 -0
  1181. package/build/dist/Utils/Schema/ModelSchema.js +1 -0
  1182. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  1183. package/build/dist/Utils/StatusPage/ResourceSearch.js +200 -0
  1184. package/build/dist/Utils/StatusPage/ResourceSearch.js.map +1 -0
  1185. package/build/dist/Utils/Telemetry/OriginAllowList.js +299 -0
  1186. package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -0
  1187. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js +147 -0
  1188. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js.map +1 -0
  1189. package/build/dist/Utils/ValueFormatter.js +32 -1
  1190. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  1191. package/package.json +2 -2
@@ -11,11 +11,15 @@ import { SQL } from "../AnalyticsDatabase/Statement";
11
11
  import { getQuerySettings } from "../AnalyticsDatabase/QuerySettingsHelper";
12
12
  import RumSessionService from "../../Services/RumSessionService";
13
13
  import RumSessionChunkService from "../../Services/RumSessionChunkService";
14
+ import ExceptionInstanceService from "../../Services/ExceptionInstanceService";
15
+ import logger from "../Logger";
14
16
  import AnalyticsTableName from "../../../Types/AnalyticsDatabase/AnalyticsTableName";
15
17
  import TableColumnType from "../../../Types/AnalyticsDatabase/TableColumnType";
16
18
  import Includes from "../../../Types/BaseDatabase/Includes";
19
+ import OneUptimeDate from "../../../Types/Date";
17
20
  import ChunkMath from "../../../Utils/Rum/ChunkMath";
18
- import { MAX_SESSION_REPLAY_CHUNKS_PER_READ, MAX_SESSION_REPLAY_READ_BYTES, } from "../../../Types/Rum/SessionReplay";
21
+ import { MAX_SESSION_REPLAY_CHUNKS_PER_READ, MAX_SESSION_REPLAY_READ_BYTES, SESSION_REPLAY_LIST_SEARCH_MAX_LENGTH, SESSION_REPLAY_MAX_SESSION_MS, SESSION_REPLAY_MAX_TAG_KEYS, SESSION_REPLAY_RECORDER_CAPABILITIES, SessionReplaySealedReason, } from "../../../Types/Rum/SessionReplay";
22
+ import { SESSION_REPLAY_SORT_BY_VALUES, } from "../../../Types/Rum/SessionReplayApi";
19
23
  import BadDataException from "../../../Types/Exception/BadDataException";
20
24
  import CaptureSpan from "../Telemetry/CaptureSpan";
21
25
  /*
@@ -47,10 +51,9 @@ import CaptureSpan from "../Telemetry/CaptureSpan";
47
51
  * 3. The manifest read must never name the `payload` column, so
48
52
  * ClickHouse never touches (and never decompresses) the only column
49
53
  * in the system that holds a recording of a real person's screen.
50
- * The byte-cap pre-check is the one exception, and it measures
51
- * `length(payload)` inside ClickHouse without ever shipping the
52
- * bytes: the cap has to bound the size of what is actually returned,
53
- * and the only honest measure of that is the stored column itself.
54
+ * getChunks is the one read that names it, and it measures
55
+ * `length(payload)` in the same statement that ships the bytes, so
56
+ * the column is decompressed exactly once per page.
54
57
  *
55
58
  * NOTE on aliases: ClickHouse substitutes SELECT aliases into same-level
56
59
  * unqualified WHERE references, and an aggregate alias there is an
@@ -76,6 +79,26 @@ export const DEFAULT_SESSION_REPLAY_LIST_LIMIT = 50;
76
79
  export const MAX_SESSION_REPLAY_LIST_LIMIT = 200;
77
80
  /* Sessions returned by the exception -> replay lookup. */
78
81
  export const MAX_SESSION_REPLAY_FOR_EXCEPTION_LIMIT = 20;
82
+ /*
83
+ * Default window for the exception -> replay lookup when the caller gives
84
+ * none. RumSession is partitioned by day, so an unbounded lookup scans
85
+ * every partition the project has ever written; 30 days covers every
86
+ * retention tier a recording can still be played under.
87
+ */
88
+ export const DEFAULT_SESSION_REPLAY_FOR_EXCEPTION_WINDOW_DAYS = 30;
89
+ /*
90
+ * Sessions the exception-instance side index may name. The instance table
91
+ * carries the session id of the page that threw, which is how a session
92
+ * is found BEFORE the finalizer has written its fingerprint list.
93
+ */
94
+ const MAX_EXCEPTION_INSTANCE_SESSION_IDS = 100;
95
+ /*
96
+ * Padding around an exception's own timestamp when the caller pins the
97
+ * lookup to a moment: a session that contains the error started at most
98
+ * SESSION_REPLAY_MAX_SESSION_MS before it, and clock skew between the
99
+ * browser and the server is bounded far below this.
100
+ */
101
+ export const SESSION_REPLAY_EXCEPTION_WINDOW_PADDING_MS = 5 * 60 * 1000;
79
102
  /*
80
103
  * Row ceiling on one manifest. A session is capped at
81
104
  * MAX_SESSION_REPLAY_CHUNKS_PER_SESSION (480) chunks PER TAB, and a
@@ -84,6 +107,18 @@ export const MAX_SESSION_REPLAY_FOR_EXCEPTION_LIMIT = 20;
84
107
  * timeline.
85
108
  */
86
109
  const MAX_MANIFEST_ROWS = 4096;
110
+ /*
111
+ * How long one application's activity summary is served from memory. The
112
+ * health card polls every 10-60s per viewer and the summary is a small
113
+ * aggregate over a day of headers, so a 30s cache turns N viewers into
114
+ * one ClickHouse query per pod per half minute.
115
+ */
116
+ export const SESSION_REPLAY_ACTIVITY_SUMMARY_CACHE_TTL_MS = 30 * 1000;
117
+ const MAX_ACTIVITY_SUMMARY_CACHE_ENTRIES = 1000;
118
+ /* The header attribute the ingest writes chunk 0's capability list into. */
119
+ export const RECORDER_CAPABILITIES_ATTRIBUTE = "recorder.capabilities";
120
+ /* Routes projected onto a list row; the table shows three and says "(N pages)". */
121
+ export const MAX_LIST_ROUTES = 5;
87
122
  function argMaxColumn(column) {
88
123
  return `argMax(${column}, version)`;
89
124
  }
@@ -93,6 +128,34 @@ function argMaxNumeric(column) {
93
128
  function argMaxDateTime(column) {
94
129
  return `toFloat64(toUnixTimestamp64Milli(${argMaxColumn(column)}))`;
95
130
  }
131
+ /* A Date column (retentionDate) as unix milliseconds. */
132
+ function argMaxDate(column) {
133
+ return `toFloat64(toUnixTimestamp(${argMaxColumn(column)})) * 1000`;
134
+ }
135
+ /*
136
+ * Duration that stays honest for a session the finalizer has not reached.
137
+ *
138
+ * The provisional header is written on chunk 0 with durationMs 0 and
139
+ * endTime = chunk 0's end, and it stays that way for the 10+ minutes of
140
+ * idleness the finalizer waits for. Reported verbatim, every live or
141
+ * recently finished session read "0s" in the list and a "longer than"
142
+ * filter hid all of them - the first thing a person testing their install
143
+ * sees is a session that claims to be empty. Until the finalized row
144
+ * exists, the span the header itself asserts (endTime - startTime) is the
145
+ * best lower bound there is, so the live value is the larger of the two.
146
+ * The finalized row's durationMs is authoritative and is used as-is.
147
+ */
148
+ /*
149
+ * durationMs is Int128 on disk while the clock arithmetic is Int64; both
150
+ * branches are cast to Int64 (a session is capped at four hours, so the
151
+ * cast cannot overflow) so `if` and `greatest` see one type.
152
+ */
153
+ const LIVE_DURATION_EXPRESSION = `toFloat64(if(${argMaxColumn("isFinalized")}, toInt64(${argMaxColumn("durationMs")}), greatest(toInt64(${argMaxColumn("durationMs")}), toUnixTimestamp64Milli(${argMaxColumn("endTime")}) - toUnixTimestamp64Milli(${argMaxColumn("startTime")}))))`;
154
+ /*
155
+ * The frustration total, shared by the hasFrustration predicate and the
156
+ * "frustration" sort so the two can never disagree about what counts.
157
+ */
158
+ const FRUSTRATION_TOTAL_EXPRESSION = "(aggRageClickCount + aggDeadClickCount + aggErrorClickCount + aggRefreshRageCount)";
96
159
  /*
97
160
  * Aliases deliberately differ from the physical column names. See the
98
161
  * ILLEGAL_AGGREGATION note in the file header.
@@ -100,7 +163,7 @@ function argMaxDateTime(column) {
100
163
  const HEADER_AGGREGATES = [
101
164
  { alias: "aggStartTime", expression: argMaxDateTime("startTime") },
102
165
  { alias: "aggEndTime", expression: argMaxDateTime("endTime") },
103
- { alias: "aggDurationMs", expression: argMaxNumeric("durationMs") },
166
+ { alias: "aggDurationMs", expression: LIVE_DURATION_EXPRESSION },
104
167
  { alias: "aggIsFinalized", expression: argMaxColumn("isFinalized") },
105
168
  { alias: "aggSealedReason", expression: argMaxColumn("sealedReason") },
106
169
  { alias: "aggChunkCount", expression: argMaxNumeric("chunkCount") },
@@ -124,6 +187,12 @@ const HEADER_AGGREGATES = [
124
187
  { alias: "aggTriggerReason", expression: argMaxColumn("triggerReason") },
125
188
  { alias: "aggEntryUrl", expression: argMaxColumn("entryUrl") },
126
189
  { alias: "aggExitUrl", expression: argMaxColumn("exitUrl") },
190
+ /*
191
+ * The full routes array: the list projects the first MAX_LIST_ROUTES and
192
+ * the urlPrefix / search predicates run over the argMax'd whole, never
193
+ * the raw column (which would match a superseded header version).
194
+ */
195
+ { alias: "aggRoutes", expression: argMaxColumn("routes") },
127
196
  { alias: "aggBrowserName", expression: argMaxColumn("browserName") },
128
197
  { alias: "aggBrowserVersion", expression: argMaxColumn("browserVersion") },
129
198
  { alias: "aggOsName", expression: argMaxColumn("osName") },
@@ -139,6 +208,36 @@ const HEADER_AGGREGATES = [
139
208
  alias: "aggSamplePercentage",
140
209
  expression: argMaxNumeric("samplePercentageAtCapture"),
141
210
  },
211
+ /*
212
+ * Counts rather than the arrays themselves: the list only says "3 traces"
213
+ * and "2 exception groups", and the hasTraces predicate needs a number.
214
+ */
215
+ {
216
+ alias: "aggTraceCount",
217
+ expression: `toFloat64(length(${argMaxColumn("traceIds")}))`,
218
+ },
219
+ {
220
+ alias: "aggExceptionGroupCount",
221
+ expression: `toFloat64(length(${argMaxColumn("exceptionFingerprints")}))`,
222
+ },
223
+ /*
224
+ * The first fingerprint, so the list's "3 errors" badge can link at the
225
+ * exception group instead of at an unfiltered Exceptions page. Empty
226
+ * string when the session recorded no exception group; arrayElement on
227
+ * an empty array returns the type's default, which for String is ''.
228
+ */
229
+ {
230
+ alias: "aggTopExceptionFingerprint",
231
+ expression: `arrayElement(${argMaxColumn("exceptionFingerprints")}, 1)`,
232
+ },
233
+ { alias: "aggClickCount", expression: argMaxNumeric("clickCount") },
234
+ { alias: "aggActiveMs", expression: argMaxNumeric("activeMs") },
235
+ {
236
+ alias: "aggFirstErrorOffsetMs",
237
+ expression: argMaxNumeric("firstErrorOffsetMs"),
238
+ },
239
+ { alias: "aggExpiresAt", expression: argMaxDate("retentionDate") },
240
+ { alias: "aggTags", expression: argMaxColumn("tags") },
142
241
  ];
143
242
  /* Only the manifest needs these; the list never renders them. */
144
243
  const HEADER_DETAIL_AGGREGATES = [
@@ -149,7 +248,6 @@ const HEADER_DETAIL_AGGREGATES = [
149
248
  { alias: "aggRrwebVersion", expression: argMaxColumn("rrwebVersion") },
150
249
  { alias: "aggSchemaVersion", expression: argMaxNumeric("schemaVersion") },
151
250
  { alias: "aggWireVersion", expression: argMaxNumeric("wireVersion") },
152
- { alias: "aggRoutes", expression: argMaxColumn("routes") },
153
251
  { alias: "aggFidelityNotices", expression: argMaxColumn("fidelityNotices") },
154
252
  {
155
253
  alias: "aggFullSnapshotChunkIndexes",
@@ -161,6 +259,30 @@ const HEADER_DETAIL_AGGREGATES = [
161
259
  expression: argMaxColumn("exceptionFingerprints"),
162
260
  },
163
261
  { alias: "aggClockSkewMs", expression: argMaxNumeric("clockSkewMs") },
262
+ {
263
+ alias: "aggClientReportedStart",
264
+ expression: argMaxDateTime("clientReportedStartTime"),
265
+ },
266
+ {
267
+ alias: "aggCustomEventCount",
268
+ expression: argMaxNumeric("customEventCount"),
269
+ },
270
+ { alias: "aggAttributes", expression: argMaxColumn("attributes") },
271
+ ];
272
+ /*
273
+ * The two columns under the identity ACL. Named in a statement ONLY when
274
+ * the caller has already passed canReadIdentifiedUserLabel for the
275
+ * application the statement is pinned to.
276
+ */
277
+ const IDENTITY_AGGREGATES = [
278
+ {
279
+ alias: "aggIdentifiedUserLabel",
280
+ expression: argMaxColumn("identifiedUserLabel"),
281
+ },
282
+ {
283
+ alias: "aggIdentifiedUserTraits",
284
+ expression: argMaxColumn("identifiedUserTraits"),
285
+ },
164
286
  ];
165
287
  function toSelectList(columns) {
166
288
  return columns
@@ -223,6 +345,28 @@ function readNumberArray(row, key) {
223
345
  }
224
346
  return numbers;
225
347
  }
348
+ /*
349
+ * A Map(String, String) column. ClickHouse serialises it as a JSON object;
350
+ * anything else (including an array, or a row that predates the column)
351
+ * reads as an empty map.
352
+ */
353
+ function readStringMap(row, key) {
354
+ const value = row[key];
355
+ const result = {};
356
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
357
+ return result;
358
+ }
359
+ for (const entryKey of Object.keys(value)) {
360
+ const entry = value[entryKey];
361
+ if (typeof entry === "string") {
362
+ result[entryKey] = entry;
363
+ }
364
+ else if (typeof entry === "number" || typeof entry === "boolean") {
365
+ result[entryKey] = String(entry);
366
+ }
367
+ }
368
+ return result;
369
+ }
226
370
  /*
227
371
  * Unix millis -> Date. The queries return epoch milliseconds as a Float64
228
372
  * precisely so no ClickHouse datetime string ever has to be re-parsed
@@ -232,7 +376,47 @@ function readNumberArray(row, key) {
232
376
  function readDate(row, key) {
233
377
  return new Date(readNumber(row, key));
234
378
  }
379
+ /*
380
+ * The capability list chunk 0 declared, filtered to the vocabulary this
381
+ * build knows so a stored typo never reaches the player as a capability.
382
+ */
383
+ function readRecorderCapabilities(row) {
384
+ const attributes = readStringMap(row, "aggAttributes");
385
+ const raw = attributes[RECORDER_CAPABILITIES_ATTRIBUTE];
386
+ if (!raw) {
387
+ return [];
388
+ }
389
+ return raw
390
+ .split(",")
391
+ .map((capability) => {
392
+ return capability.trim();
393
+ })
394
+ .filter((capability) => {
395
+ return SESSION_REPLAY_RECORDER_CAPABILITIES.includes(capability);
396
+ });
397
+ }
398
+ const activitySummaryCache = new Map();
399
+ let publishedRecorderVersionProvider = null;
235
400
  export default class SessionReplayReadService {
401
+ static setPublishedRecorderVersionProvider(provider) {
402
+ publishedRecorderVersionProvider = provider;
403
+ }
404
+ static getPublishedRecorderVersion() {
405
+ if (!publishedRecorderVersionProvider) {
406
+ return null;
407
+ }
408
+ try {
409
+ const version = publishedRecorderVersionProvider();
410
+ return typeof version === "string" && version.length > 0 ? version : null;
411
+ }
412
+ catch (_a) {
413
+ return null;
414
+ }
415
+ }
416
+ /* Test seam: the summary cache is process-local. */
417
+ static clearActivitySummaryCache() {
418
+ activitySummaryCache.clear();
419
+ }
236
420
  /*
237
421
  * Session list.
238
422
  *
@@ -240,7 +424,10 @@ export default class SessionReplayReadService {
240
424
  * are the first three elements of the sort key AND they are part of the
241
425
  * ReplacingMergeTree replace key, so they are byte-identical on every
242
426
  * duplicate row of a session. Filtering on them before the GROUP BY is
243
- * therefore both index-friendly and safe.
427
+ * therefore both index-friendly and safe. Nothing else is ever added to
428
+ * the WHERE: any other predicate would have to run over raw rows and
429
+ * would either match a superseded header version or force a scan that
430
+ * the (projectId, rumApplicationId, startTime) prefix cannot prune.
244
431
  *
245
432
  * Everything else is filtered in HAVING against the argMax'd value.
246
433
  * That is not a style choice: a provisional header (written on chunk 0,
@@ -251,6 +438,17 @@ export default class SessionReplayReadService {
251
438
  */
252
439
  static async listSessions(request) {
253
440
  const limit = Math.max(1, Math.min(request.limit, MAX_SESSION_REPLAY_LIST_LIMIT));
441
+ const sortBy = request.sortBy || "startTime";
442
+ if (!SESSION_REPLAY_SORT_BY_VALUES.includes(sortBy)) {
443
+ throw new BadDataException(`sortBy must be one of ${SESSION_REPLAY_SORT_BY_VALUES.join(", ")}.`);
444
+ }
445
+ if (request.cursor && request.cursor.sortBy !== sortBy) {
446
+ /*
447
+ * A cursor is a position in ONE ordering. Applying a "most errors"
448
+ * cursor to a "newest" list would silently skip or repeat sessions.
449
+ */
450
+ throw new BadDataException(`The cursor belongs to a list sorted by ${request.cursor.sortBy}, not ${sortBy}. Start from the first page.`);
451
+ }
254
452
  const selectList = toSelectList(HEADER_AGGREGATES);
255
453
  const statement = SQL `
256
454
  SELECT
@@ -259,7 +457,7 @@ export default class SessionReplayReadService {
259
457
  `;
260
458
  statement.append(` ${selectList}`);
261
459
  if (request.includeIdentifiedUserLabel) {
262
- statement.append(`,\n ${argMaxColumn("identifiedUserLabel")} AS aggIdentifiedUserLabel`);
460
+ statement.append(`,\n ${toSelectList(IDENTITY_AGGREGATES)}`);
263
461
  }
264
462
  statement.append(SQL `
265
463
  FROM ${AnalyticsTableName.RumSession}
@@ -283,36 +481,45 @@ export default class SessionReplayReadService {
283
481
  statement.append(RETENTION_FILTER);
284
482
  /*
285
483
  * Keyset cursor. The sort key is (projectId, rumApplicationId,
286
- * startTime, sessionId) and the list is ordered by the same tuple
287
- * descending, so the previous page's last startTime is a valid
288
- * WHERE-level upper bound: it prunes granules instead of paging with
289
- * OFFSET, which on a wide time window would re-read and re-aggregate
290
- * everything already returned. The exact ties are removed by the
291
- * HAVING tiebreak below - the WHERE bound is deliberately inclusive
292
- * so a row sharing the boundary timestamp is not skipped.
484
+ * startTime, sessionId) and the newest-first list is ordered by the
485
+ * same tuple descending, so the previous page's last startTime is a
486
+ * valid WHERE-level upper bound: it prunes granules instead of paging
487
+ * with OFFSET, which on a wide time window would re-read and
488
+ * re-aggregate everything already returned. The exact ties are
489
+ * removed by the HAVING tiebreak below - the WHERE bound is
490
+ * deliberately inclusive so a row sharing the boundary timestamp is
491
+ * not skipped.
492
+ *
493
+ * Only for the startTime sort: for any other key the cursor value is
494
+ * an aggregate, and a WHERE on startTime would drop sessions that
495
+ * belong on later pages.
293
496
  */
294
- if (request.cursor) {
497
+ if (request.cursor && sortBy === "startTime") {
295
498
  statement.append(SQL ` AND startTime <= ${{
296
499
  type: TableColumnType.DateTime64,
297
- value: new Date(request.cursor.startTimeUnixMs),
500
+ value: new Date(request.cursor.sortValue),
298
501
  }}`);
299
502
  }
300
503
  statement.append(" GROUP BY projectId, rumApplicationId, sessionId\n HAVING 1 = 1");
301
- SessionReplayReadService.appendListHavingFilters(statement, request.filters);
504
+ SessionReplayReadService.appendListHavingFilters(statement, request.filters, request.includeIdentifiedUserLabel);
505
+ const sortExpression = SessionReplayReadService.getSortExpression(sortBy);
302
506
  if (request.cursor) {
303
- statement.append(SQL ` AND (aggStartTime < ${{
507
+ statement.append(` AND (${sortExpression} < `);
508
+ statement.append(SQL `${{
304
509
  type: TableColumnType.Decimal,
305
- value: request.cursor.startTimeUnixMs,
306
- }} OR (aggStartTime = ${{
510
+ value: request.cursor.sortValue,
511
+ }}`);
512
+ statement.append(` OR (${sortExpression} = `);
513
+ statement.append(SQL `${{
307
514
  type: TableColumnType.Decimal,
308
- value: request.cursor.startTimeUnixMs,
515
+ value: request.cursor.sortValue,
309
516
  }} AND sessionId < ${{
310
517
  type: TableColumnType.Text,
311
518
  value: request.cursor.sessionId,
312
519
  }}))`);
313
520
  }
314
- statement.append(SQL ` ORDER BY aggStartTime DESC, sessionId DESC
315
- LIMIT ${{
521
+ statement.append(` ORDER BY ${sortExpression} DESC, sessionId DESC`);
522
+ statement.append(SQL ` LIMIT ${{
316
523
  type: TableColumnType.Number,
317
524
  value: limit + 1,
318
525
  }}`);
@@ -328,11 +535,13 @@ export default class SessionReplayReadService {
328
535
  const hasMore = rows.length > limit;
329
536
  const pageRows = hasMore ? rows.slice(0, limit) : rows;
330
537
  const sessions = pageRows.map((row) => {
538
+ const startTime = readDate(row, "aggStartTime");
539
+ const endTime = readDate(row, "aggEndTime");
331
540
  const item = {
332
541
  sessionId: readString(row, "sessionId"),
333
542
  rumApplicationId: readString(row, "applicationId"),
334
- startTime: readDate(row, "aggStartTime"),
335
- endTime: readDate(row, "aggEndTime"),
543
+ startTime: startTime,
544
+ endTime: endTime,
336
545
  durationMs: readNumber(row, "aggDurationMs"),
337
546
  isFinalized: readBoolean(row, "aggIsFinalized"),
338
547
  sealedReason: readString(row, "aggSealedReason"),
@@ -360,9 +569,21 @@ export default class SessionReplayReadService {
360
569
  viewportHeight: readNumber(row, "aggViewportHeight"),
361
570
  identifiedUserKey: readString(row, "aggIdentifiedUserKey"),
362
571
  samplePercentageAtCapture: readNumber(row, "aggSamplePercentage"),
572
+ routes: readStringArray(row, "aggRoutes").slice(0, MAX_LIST_ROUTES),
573
+ traceCount: readNumber(row, "aggTraceCount"),
574
+ exceptionGroupCount: readNumber(row, "aggExceptionGroupCount"),
575
+ topExceptionFingerprint: readString(row, "aggTopExceptionFingerprint"),
576
+ clickCount: readNumber(row, "aggClickCount"),
577
+ activeMs: readNumber(row, "aggActiveMs"),
578
+ firstErrorOffsetMs: readNumber(row, "aggFirstErrorOffsetMs"),
579
+ expiresAtUnixMs: readNumber(row, "aggExpiresAt"),
580
+ tags: readStringMap(row, "aggTags"),
581
+ startTimeUnixMs: startTime.getTime(),
582
+ endTimeUnixMs: endTime.getTime(),
363
583
  };
364
584
  if (request.includeIdentifiedUserLabel) {
365
585
  item.identifiedUserLabel = readString(row, "aggIdentifiedUserLabel");
586
+ item.identifiedUserTraits = readStringMap(row, "aggIdentifiedUserTraits");
366
587
  }
367
588
  return item;
368
589
  });
@@ -371,7 +592,8 @@ export default class SessionReplayReadService {
371
592
  sessions: sessions,
372
593
  nextCursor: hasMore && lastSession
373
594
  ? {
374
- startTimeUnixMs: lastSession.startTime.getTime(),
595
+ sortBy: sortBy,
596
+ sortValue: SessionReplayReadService.getSortValue(sortBy, lastSession),
375
597
  sessionId: lastSession.sessionId,
376
598
  }
377
599
  : null,
@@ -383,9 +605,10 @@ export default class SessionReplayReadService {
383
605
  *
384
606
  * This is also what resolves a sessionId to its owning RUM application
385
607
  * for the handler-level authorization check, which is why it is keyed
386
- * on (projectId, sessionId) only and never accepts an application id
387
- * from the caller: an application id supplied in the request body would
388
- * make the check circular.
608
+ * on (projectId, sessionId) and the optional rumApplicationId is a
609
+ * DISAMBIGUATOR, never a substitute for the check: a supplied id only
610
+ * narrows which header row is read, and the handler still authorizes
611
+ * the application that row names.
389
612
  */
390
613
  static async getSessionHeader(data) {
391
614
  const selectList = toSelectList([
@@ -410,6 +633,12 @@ export default class SessionReplayReadService {
410
633
  value: data.sessionId,
411
634
  }}
412
635
  `);
636
+ if (data.rumApplicationId) {
637
+ statement.append(SQL ` AND rumApplicationId = ${{
638
+ type: TableColumnType.ObjectID,
639
+ value: data.rumApplicationId,
640
+ }}`);
641
+ }
413
642
  statement.append(RETENTION_FILTER);
414
643
  /*
415
644
  * Grouped by the full replace-key identity minus startTime, so one
@@ -422,9 +651,10 @@ export default class SessionReplayReadService {
422
651
  * sessionId share a key space. Picking the newest group would let
423
652
  * anyone who can write to application A resolve a sessionId belonging
424
653
  * to application B onto their own application and pass the label
425
- * check. An ambiguous sessionId is refused outright instead: it is
426
- * either an attack or a collision, and neither has a correct
427
- * recording to return.
654
+ * check. An ambiguous sessionId is refused outright unless the caller
655
+ * named the application it wants (which is then authorized on its own
656
+ * merits): it is either an attack or a collision, and neither has a
657
+ * single correct recording to return.
428
658
  */
429
659
  statement.append(" GROUP BY projectId, rumApplicationId, sessionId ORDER BY aggStartTime DESC LIMIT 2");
430
660
  statement.append(READ_QUERY_SETTINGS);
@@ -432,18 +662,20 @@ export default class SessionReplayReadService {
432
662
  const response = await dbResult.json();
433
663
  const rows = response.data || [];
434
664
  if (rows.length > 1) {
435
- throw new BadDataException("This session id resolves to more than one RUM application and cannot be played back.");
665
+ throw new BadDataException("This session id was recorded under more than one application in this project. Open it from the session list of the application you want to watch, which passes rumApplicationId to choose the recording.");
436
666
  }
437
667
  const row = rows[0];
438
668
  if (!row) {
439
669
  return null;
440
670
  }
671
+ const startTime = readDate(row, "aggStartTime");
672
+ const endTime = readDate(row, "aggEndTime");
441
673
  return {
442
674
  sessionId: readString(row, "sessionId"),
443
675
  projectId: readString(row, "headerProjectId"),
444
676
  rumApplicationId: readString(row, "applicationId"),
445
- startTime: readDate(row, "aggStartTime"),
446
- endTime: readDate(row, "aggEndTime"),
677
+ startTime: startTime,
678
+ endTime: endTime,
447
679
  durationMs: readNumber(row, "aggDurationMs"),
448
680
  isFinalized: readBoolean(row, "aggIsFinalized"),
449
681
  sealedReason: readString(row, "aggSealedReason"),
@@ -482,6 +714,106 @@ export default class SessionReplayReadService {
482
714
  traceIds: readStringArray(row, "aggTraceIds"),
483
715
  exceptionFingerprints: readStringArray(row, "aggExceptionFingerprints"),
484
716
  clockSkewMs: readNumber(row, "aggClockSkewMs"),
717
+ startTimeUnixMs: startTime.getTime(),
718
+ endTimeUnixMs: endTime.getTime(),
719
+ clientReportedStartUnixMs: readNumber(row, "aggClientReportedStart"),
720
+ tags: readStringMap(row, "aggTags"),
721
+ expiresAtUnixMs: readNumber(row, "aggExpiresAt"),
722
+ clickCount: readNumber(row, "aggClickCount"),
723
+ customEventCount: readNumber(row, "aggCustomEventCount"),
724
+ activeMs: readNumber(row, "aggActiveMs"),
725
+ firstErrorOffsetMs: readNumber(row, "aggFirstErrorOffsetMs"),
726
+ recorderCapabilities: readRecorderCapabilities(row),
727
+ };
728
+ }
729
+ /*
730
+ * The identity columns for one session, pinned to the application the
731
+ * caller was authorized against. This is the ONLY statement outside the
732
+ * identity-gated list projection that names identifiedUserLabel or
733
+ * identifiedUserTraits, and the manifest handler calls it strictly
734
+ * after canReadIdentifiedUserLabel has passed for this application. It
735
+ * is a separate, tiny read rather than two more columns on
736
+ * getSessionHeader because the header is resolved BEFORE the
737
+ * application (and therefore the identity decision) is known.
738
+ */
739
+ static async getSessionIdentity(data) {
740
+ const statement = SQL `
741
+ SELECT
742
+ `;
743
+ statement.append(` ${toSelectList(IDENTITY_AGGREGATES)}`);
744
+ statement.append(SQL `
745
+ FROM ${AnalyticsTableName.RumSession}
746
+ WHERE projectId = ${{
747
+ type: TableColumnType.ObjectID,
748
+ value: data.projectId,
749
+ }}
750
+ AND rumApplicationId = ${{
751
+ type: TableColumnType.ObjectID,
752
+ value: data.rumApplicationId,
753
+ }}
754
+ AND sessionId = ${{
755
+ type: TableColumnType.Text,
756
+ value: data.sessionId,
757
+ }}
758
+ `);
759
+ statement.append(RETENTION_FILTER);
760
+ statement.append(" GROUP BY projectId, rumApplicationId, sessionId LIMIT 1");
761
+ statement.append(READ_QUERY_SETTINGS);
762
+ const dbResult = await RumSessionService.executeQuery(statement);
763
+ const response = await dbResult.json();
764
+ const row = (response.data || [])[0];
765
+ if (!row) {
766
+ return { identifiedUserLabel: "", identifiedUserTraits: {} };
767
+ }
768
+ return {
769
+ identifiedUserLabel: readString(row, "aggIdentifiedUserLabel"),
770
+ identifiedUserTraits: readStringMap(row, "aggIdentifiedUserTraits"),
771
+ };
772
+ }
773
+ /*
774
+ * For a sessionId that getSessionHeader could not find: did a header
775
+ * ever exist, and when did (or does) it expire? Runs WITHOUT the
776
+ * retention filter, which is safe only because it returns dates and an
777
+ * application id and never a row's content - it lets the handler say
778
+ * "this recording expired on <date>" instead of "not found".
779
+ *
780
+ * null when no row exists at all (never recorded, or already dropped by
781
+ * the ClickHouse TTL, or erased).
782
+ */
783
+ static async getExpiredSessionInfo(data) {
784
+ const statement = SQL `
785
+ SELECT
786
+ toString(rumApplicationId) AS applicationId,
787
+ toFloat64(toUnixTimestamp(max(retentionDate))) * 1000 AS expiresAtUnixMs,
788
+ toFloat64(toUnixTimestamp64Milli(min(startTime))) AS startTimeUnixMs
789
+ FROM ${AnalyticsTableName.RumSession}
790
+ WHERE projectId = ${{
791
+ type: TableColumnType.ObjectID,
792
+ value: data.projectId,
793
+ }}
794
+ AND sessionId = ${{
795
+ type: TableColumnType.Text,
796
+ value: data.sessionId,
797
+ }}
798
+ `;
799
+ if (data.rumApplicationId) {
800
+ statement.append(SQL ` AND rumApplicationId = ${{
801
+ type: TableColumnType.ObjectID,
802
+ value: data.rumApplicationId,
803
+ }}`);
804
+ }
805
+ statement.append(" GROUP BY rumApplicationId ORDER BY expiresAtUnixMs DESC LIMIT 1");
806
+ statement.append(READ_QUERY_SETTINGS);
807
+ const dbResult = await RumSessionService.executeQuery(statement);
808
+ const response = await dbResult.json();
809
+ const row = (response.data || [])[0];
810
+ if (!row) {
811
+ return null;
812
+ }
813
+ return {
814
+ rumApplicationId: readString(row, "applicationId"),
815
+ startTime: readDate(row, "startTimeUnixMs"),
816
+ expiresAt: readDate(row, "expiresAtUnixMs"),
485
817
  };
486
818
  }
487
819
  /*
@@ -501,6 +833,11 @@ export default class SessionReplayReadService {
501
833
  * tabId/chunkIndex first (rather than by version alone) leaves the
502
834
  * output already sorted for the caller - LIMIT BY runs after ORDER
503
835
  * BY, so the version DESC tiebreak still selects the right row.
836
+ *
837
+ * clickCount and url are narrow columns: the activity lane and the
838
+ * URL bar read them before any chunk is decoded. payloadBytes stays
839
+ * the WIRE size the recorder posted; the stored size is only ever
840
+ * measured by getChunks, which is the read the cap actually bounds.
504
841
  */
505
842
  const statement = SQL `
506
843
  SELECT
@@ -516,7 +853,9 @@ export default class SessionReplayReadService {
516
853
  deadClickCount,
517
854
  errorClickCount,
518
855
  refreshRageCount,
519
- routeCount
856
+ routeCount,
857
+ clickCount,
858
+ url
520
859
  FROM ${AnalyticsTableName.RumSessionChunk}
521
860
  WHERE projectId = ${{
522
861
  type: TableColumnType.ObjectID,
@@ -543,6 +882,9 @@ export default class SessionReplayReadService {
543
882
  const response = await dbResult.json();
544
883
  const rows = response.data || [];
545
884
  const tabsById = new Map();
885
+ let liveDurationMs = 0;
886
+ let liveEventCount = 0;
887
+ let liveMaxChunkIndex = 0;
546
888
  for (const row of rows) {
547
889
  const tabId = readString(row, "tabId");
548
890
  const entry = {
@@ -559,7 +901,12 @@ export default class SessionReplayReadService {
559
901
  errorClickCount: readNumber(row, "errorClickCount"),
560
902
  refreshRageCount: readNumber(row, "refreshRageCount"),
561
903
  routeCount: readNumber(row, "routeCount"),
904
+ clickCount: readNumber(row, "clickCount"),
905
+ url: readString(row, "url"),
562
906
  };
907
+ liveDurationMs = Math.max(liveDurationMs, entry.chunkEndOffsetMs);
908
+ liveEventCount += entry.eventCount;
909
+ liveMaxChunkIndex = Math.max(liveMaxChunkIndex, entry.chunkIndex);
563
910
  const existing = tabsById.get(tabId);
564
911
  if (existing) {
565
912
  existing.push(entry);
@@ -596,161 +943,179 @@ export default class SessionReplayReadService {
596
943
  totalPayloadBytes: entries.reduce((total, entry) => {
597
944
  return total + entry.payloadBytes;
598
945
  }, 0),
946
+ firstChunkStartOffsetMs: entries.reduce((min, entry) => {
947
+ return Math.min(min, entry.chunkStartOffsetMs);
948
+ }, Number.POSITIVE_INFINITY),
599
949
  });
600
950
  }
951
+ for (const tab of tabs) {
952
+ if (!Number.isFinite(tab.firstChunkStartOffsetMs)) {
953
+ tab.firstChunkStartOffsetMs = 0;
954
+ }
955
+ }
601
956
  return {
602
- header: data.header,
957
+ header: SessionReplayReadService.reconcileLiveHeader({
958
+ header: data.header,
959
+ chunkRowCount: rows.length,
960
+ liveDurationMs: liveDurationMs,
961
+ liveEventCount: liveEventCount,
962
+ liveMaxChunkIndex: liveMaxChunkIndex,
963
+ }),
603
964
  tabs: tabs,
604
965
  isChunkIndexTruncated: rows.length >= MAX_MANIFEST_ROWS,
605
966
  };
606
967
  }
607
968
  /*
608
- * Total STORED bytes for a specific set of chunks, without shipping the
609
- * payload column to the application.
610
- *
611
- * `length(payload)`, deliberately NOT `payloadBytes`. Those are two
612
- * different quantities: payloadBytes is the post-gzip WIRE size the
613
- * recorder uploaded (the metering signal), while the payload column
614
- * holds the DECOMPRESSED JSON and is what this endpoint actually
615
- * returns. rrweb JSON gzips 10-20x, so a cap applied to payloadBytes
616
- * bounds a number an order of magnitude smaller than the response and
617
- * therefore bounds nothing useful.
618
- *
619
- * The cost is that ClickHouse has to decompress the column to measure
620
- * it, which is exactly what naming `payload` was meant to avoid. It is
621
- * still worth doing before the read rather than after: the bytes are
622
- * measured inside ClickHouse and never cross the wire, and the marks
623
- * the following read needs are warm by the time it runs.
969
+ * A provisional header (isFinalized false) says durationMs 0, chunkCount
970
+ * 0 and eventCount 0 while its chunk rows say otherwise; the manifest
971
+ * has just read every chunk row, so it reports what the rows prove. A
972
+ * finalized header is authoritative and returned untouched.
624
973
  */
625
- static async getChunkStoredBytes(data) {
626
- if (data.chunkIndexes.length === 0) {
627
- return 0;
974
+ static reconcileLiveHeader(data) {
975
+ if (data.header.isFinalized || data.chunkRowCount === 0) {
976
+ return data.header;
628
977
  }
629
- const statement = SQL `
630
- SELECT
631
- chunkIndex,
632
- toFloat64(length(payload)) AS chunkStoredBytes
633
- FROM ${AnalyticsTableName.RumSessionChunk}
634
- WHERE projectId = ${{
635
- type: TableColumnType.ObjectID,
636
- value: data.projectId,
637
- }}
638
- AND rumApplicationId = ${{
639
- type: TableColumnType.ObjectID,
640
- value: data.rumApplicationId,
641
- }}
642
- AND sessionId = ${{
643
- type: TableColumnType.Text,
644
- value: data.sessionId,
645
- }}
646
- AND tabId = ${{
647
- type: TableColumnType.Text,
648
- value: data.tabId,
649
- }}
650
- AND chunkIndex IN (${{
651
- type: TableColumnType.Number,
652
- value: new Includes(data.chunkIndexes),
653
- }})
654
- `;
655
- statement.append(RETENTION_FILTER);
656
- /*
657
- * Deduplicated exactly like the payload read, so the pre-check and
658
- * the read it guards can never disagree about which rows count.
659
- * Summed in TypeScript rather than in SQL because the row count is
660
- * bounded by MAX_SESSION_REPLAY_CHUNKS_PER_READ, and a wrapping
661
- * aggregate would need a subquery whose LIMIT BY semantics are
662
- * easier to get subtly wrong than to read.
663
- */
664
- statement.append(" ORDER BY chunkIndex ASC, version DESC LIMIT 1 BY chunkIndex");
665
- statement.append(READ_QUERY_SETTINGS);
666
- const dbResult = await RumSessionChunkService.executeQuery(statement);
667
- const response = await dbResult.json();
668
- return (response.data || []).reduce((total, row) => {
669
- return total + readNumber(row, "chunkStoredBytes");
670
- }, 0);
978
+ const durationMs = Math.max(data.header.durationMs, data.liveDurationMs);
979
+ const endTimeUnixMs = Math.max(data.header.endTimeUnixMs, data.header.startTimeUnixMs + durationMs);
980
+ return Object.assign(Object.assign({}, data.header), { durationMs: durationMs, endTime: new Date(endTimeUnixMs), endTimeUnixMs: endTimeUnixMs, chunkCount: Math.max(data.header.chunkCount, data.chunkRowCount), eventCount: Math.max(data.header.eventCount, data.liveEventCount), maxChunkIndex: Math.max(data.header.maxChunkIndex, data.liveMaxChunkIndex) });
671
981
  }
672
982
  /*
673
983
  * The payload read. The only query in the system that names the
674
984
  * `payload` column.
675
985
  *
986
+ * The byte cap is measured on `length(payload)` - the DECOMPRESSED
987
+ * stored JSON that is actually returned - in the SAME statement that
988
+ * ships the bytes, so the column is decompressed once per page rather
989
+ * than once for a pre-check and again for the read. `payloadBytes` is
990
+ * the post-gzip WIRE size the recorder uploaded; rrweb JSON gzips
991
+ * 10-20x, so a cap on it bounds a number an order of magnitude smaller
992
+ * than the response and therefore bounds nothing useful.
993
+ *
994
+ * Prefix semantics rather than refusal. A page that does not fit is
995
+ * answered with the longest prefix of whole chunks that does, and ALWAYS
996
+ * with at least the first chunk: the ingest cap
997
+ * (SESSION_REPLAY_MAX_DECOMPRESSED_FRAME_BYTES) already bounds a single
998
+ * frame, so a lone chunk can never exceed what the ingest let in, and a
999
+ * single oversized snapshot that could never be served would dead-end
1000
+ * playback at that chunk forever. The player plans pages against the
1001
+ * wire size it has, requests, and reads back whichever chunks arrived.
1002
+ *
676
1003
  * Both caps are enforced here rather than only at the route so no
677
1004
  * future caller can reach the payload column without them.
678
1005
  */
679
1006
  static async getChunks(data) {
680
1007
  if (data.chunkIndexes.length === 0) {
681
- return [];
1008
+ return { chunks: [], omittedChunkIndexes: [] };
682
1009
  }
683
1010
  if (data.chunkIndexes.length > MAX_SESSION_REPLAY_CHUNKS_PER_READ) {
684
1011
  throw new BadDataException(`A maximum of ${MAX_SESSION_REPLAY_CHUNKS_PER_READ} chunks may be requested at a time.`);
685
1012
  }
686
- const totalBytes = await SessionReplayReadService.getChunkStoredBytes(data);
687
- if (totalBytes > MAX_SESSION_REPLAY_READ_BYTES) {
688
- throw new BadDataException(`The requested chunks total ${totalBytes} bytes, which exceeds the ${MAX_SESSION_REPLAY_READ_BYTES} byte limit for a single read. Request fewer chunks.`);
689
- }
1013
+ /*
1014
+ * Innermost: the de-duplicated rows. A retried delivery is two
1015
+ * physically present rows on a ReplacingMergeTree until a merge runs.
1016
+ * Feeding both to the player would replay the same mutations twice,
1017
+ * which rrweb resolves against node ids and would either throw or
1018
+ * render a DOM that never existed.
1019
+ *
1020
+ * Middle: a running total of stored bytes in chunk order. Outermost:
1021
+ * a row is SERVED when the total up to and including it is under the
1022
+ * cap, or when it is the first row; a row that is not served keeps
1023
+ * its index (so the caller can name what was omitted) but ships an
1024
+ * empty payload, so the bytes crossing the wire are bounded inside
1025
+ * ClickHouse and never in the application.
1026
+ *
1027
+ * The outer projection is aliased servedPayload rather than payload:
1028
+ * an alias that names the column its own expression reads is a
1029
+ * cyclic alias to ClickHouse.
1030
+ */
690
1031
  const statement = SQL `
691
1032
  SELECT
692
1033
  chunkIndex,
693
- payload
694
- FROM ${AnalyticsTableName.RumSessionChunk}
695
- WHERE projectId = ${{
1034
+ if(isServed, payload, '') AS servedPayload,
1035
+ isServed
1036
+ FROM (
1037
+ SELECT
1038
+ chunkIndex,
1039
+ payload,
1040
+ (sum(length(payload)) OVER (ORDER BY chunkIndex ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) <= ${{
1041
+ type: TableColumnType.Decimal,
1042
+ value: MAX_SESSION_REPLAY_READ_BYTES,
1043
+ }}
1044
+ OR row_number() OVER (ORDER BY chunkIndex ASC) = 1) AS isServed
1045
+ FROM (
1046
+ SELECT
1047
+ chunkIndex,
1048
+ payload
1049
+ FROM ${AnalyticsTableName.RumSessionChunk}
1050
+ WHERE projectId = ${{
696
1051
  type: TableColumnType.ObjectID,
697
1052
  value: data.projectId,
698
1053
  }}
699
- AND rumApplicationId = ${{
1054
+ AND rumApplicationId = ${{
700
1055
  type: TableColumnType.ObjectID,
701
1056
  value: data.rumApplicationId,
702
1057
  }}
703
- AND sessionId = ${{
1058
+ AND sessionId = ${{
704
1059
  type: TableColumnType.Text,
705
1060
  value: data.sessionId,
706
1061
  }}
707
- AND tabId = ${{
1062
+ AND tabId = ${{
708
1063
  type: TableColumnType.Text,
709
1064
  value: data.tabId,
710
1065
  }}
711
- AND chunkIndex IN (${{
1066
+ AND chunkIndex IN (${{
712
1067
  type: TableColumnType.Number,
713
1068
  value: new Includes(data.chunkIndexes),
714
1069
  }})
715
1070
  `;
716
1071
  statement.append(RETENTION_FILTER);
717
- /*
718
- * A retried delivery is two physically present rows on a
719
- * ReplacingMergeTree until a merge runs. Feeding both to the player
720
- * would replay the same mutations twice, which rrweb resolves against
721
- * node ids and would either throw or render a DOM that never existed.
722
- */
723
- statement.append(" ORDER BY chunkIndex ASC, version DESC LIMIT 1 BY chunkIndex");
1072
+ statement.append(" ORDER BY chunkIndex ASC, version DESC LIMIT 1 BY chunkIndex\n )\n )\n ORDER BY chunkIndex ASC");
724
1073
  statement.append(READ_QUERY_SETTINGS);
725
1074
  const dbResult = await RumSessionChunkService.executeQuery(statement);
726
1075
  const response = await dbResult.json();
727
1076
  /*
728
1077
  * The cap is re-applied to the bytes actually being handed back, not
729
- * only to what the pre-check believed. The pre-check reads a
730
- * different snapshot of a ReplacingMergeTree than the read it guards,
731
- * and any future change to how stored size is derived would otherwise
732
- * silently unbound the response. Accumulated as the rows are mapped
733
- * so an oversized read fails before the caller ever holds the whole
734
- * set.
1078
+ * only to what ClickHouse computed: any future change to how stored
1079
+ * size is derived would otherwise silently unbound the response. The
1080
+ * prefix is also re-established here - a served row behind an
1081
+ * unserved one would be a hole the player cannot play across, so the
1082
+ * served set stops at the first omission.
735
1083
  */
736
1084
  let totalReturnedBytes = 0;
737
1085
  const chunks = [];
738
- for (const row of response.data || []) {
739
- const payload = readString(row, "payload");
740
- totalReturnedBytes += Buffer.byteLength(payload, "utf8");
741
- if (totalReturnedBytes > MAX_SESSION_REPLAY_READ_BYTES) {
742
- throw new BadDataException(`The requested chunks exceed the ${MAX_SESSION_REPLAY_READ_BYTES} byte limit for a single read. Request fewer chunks.`);
1086
+ const omittedChunkIndexes = [];
1087
+ const chunkRows = response.data || [];
1088
+ for (const row of chunkRows) {
1089
+ const chunkIndex = readNumber(row, "chunkIndex");
1090
+ const payload = readString(row, "servedPayload");
1091
+ const isServed = row["isServed"] === undefined ? true : readBoolean(row, "isServed");
1092
+ const payloadBytes = Buffer.byteLength(payload, "utf8");
1093
+ const fits = chunks.length === 0 ||
1094
+ totalReturnedBytes + payloadBytes <= MAX_SESSION_REPLAY_READ_BYTES;
1095
+ if (!isServed || !fits || omittedChunkIndexes.length > 0) {
1096
+ omittedChunkIndexes.push(chunkIndex);
1097
+ continue;
743
1098
  }
1099
+ totalReturnedBytes += payloadBytes;
744
1100
  chunks.push({
745
- chunkIndex: readNumber(row, "chunkIndex"),
1101
+ chunkIndex: chunkIndex,
746
1102
  payload: payload,
747
1103
  });
748
1104
  }
749
- return chunks;
1105
+ return { chunks: chunks, omittedChunkIndexes: omittedChunkIndexes };
750
1106
  }
751
1107
  /*
752
1108
  * Sessions that observed a given exception fingerprint.
753
1109
  *
1110
+ * Two sources, one header query. The header's exceptionFingerprints
1111
+ * array is written by the finalizer, so for the first 10+ minutes after
1112
+ * the error - the whole incident, from the reporter's point of view -
1113
+ * the session's header knows nothing about it. The exception instance
1114
+ * table, however, carries the session id of the page that threw, from
1115
+ * the moment the exception is ingested. Those ids are looked up first
1116
+ * (cheap: bloom-indexed fingerprint, bounded window) and OR-ed into the
1117
+ * header predicate, so a live session is found as soon as its error is.
1118
+ *
754
1119
  * hasAny() appears twice on purpose. In the WHERE it is a bloom-pruned
755
1120
  * pre-filter over physical rows; a group survives it if ANY of its rows
756
1121
  * carries the fingerprint, which necessarily includes the case where
@@ -758,6 +1123,10 @@ export default class SessionReplayReadService {
758
1123
  * drop a true match. The HAVING then re-checks the argMax'd array so a
759
1124
  * fingerprint present only on a superseded row does not produce a false
760
1125
  * positive.
1126
+ *
1127
+ * Always windowed. RumSession is partitioned by day, so without a
1128
+ * window this scanned every partition the project ever wrote on every
1129
+ * exception page load.
761
1130
  */
762
1131
  static async getSessionsForException(data) {
763
1132
  if (data.accessibleRumApplicationIds &&
@@ -765,10 +1134,20 @@ export default class SessionReplayReadService {
765
1134
  return [];
766
1135
  }
767
1136
  const limit = Math.max(1, Math.min(data.limit, MAX_SESSION_REPLAY_FOR_EXCEPTION_LIMIT));
1137
+ const endTime = data.endTime || OneUptimeDate.getCurrentDate();
1138
+ const startTime = data.startTime ||
1139
+ OneUptimeDate.addRemoveDays(endTime, -DEFAULT_SESSION_REPLAY_FOR_EXCEPTION_WINDOW_DAYS);
1140
+ const instanceSessionIds = await SessionReplayReadService.getSessionIdsForExceptionInstances({
1141
+ projectId: data.projectId,
1142
+ exceptionFingerprint: data.exceptionFingerprint,
1143
+ startTime: startTime,
1144
+ endTime: endTime,
1145
+ sessionId: data.sessionId,
1146
+ });
768
1147
  const selectList = toSelectList([
769
1148
  { alias: "aggStartTime", expression: argMaxDateTime("startTime") },
770
1149
  { alias: "aggEndTime", expression: argMaxDateTime("endTime") },
771
- { alias: "aggDurationMs", expression: argMaxNumeric("durationMs") },
1150
+ { alias: "aggDurationMs", expression: LIVE_DURATION_EXPRESSION },
772
1151
  { alias: "aggHasError", expression: argMaxColumn("hasError") },
773
1152
  { alias: "aggErrorCount", expression: argMaxNumeric("errorCount") },
774
1153
  /*
@@ -817,36 +1196,51 @@ export default class SessionReplayReadService {
817
1196
  type: TableColumnType.ObjectID,
818
1197
  value: data.projectId,
819
1198
  }}
820
- AND hasAny(exceptionFingerprints, [${{
821
- type: TableColumnType.Text,
822
- value: data.exceptionFingerprint,
823
- }}])
824
1199
  `);
825
- statement.append(RETENTION_FILTER);
826
1200
  if (data.accessibleRumApplicationIds) {
827
1201
  statement.append(SQL ` AND rumApplicationId IN (${{
828
1202
  type: TableColumnType.ObjectID,
829
1203
  value: new Includes(data.accessibleRumApplicationIds),
830
1204
  }})`);
831
1205
  }
832
- if (data.startTime) {
833
- statement.append(SQL ` AND startTime >= ${{
834
- type: TableColumnType.DateTime64,
835
- value: data.startTime,
1206
+ statement.append(SQL ` AND startTime >= ${{
1207
+ type: TableColumnType.DateTime64,
1208
+ value: startTime,
1209
+ }} AND startTime <= ${{
1210
+ type: TableColumnType.DateTime64,
1211
+ value: endTime,
1212
+ }}`);
1213
+ statement.append(RETENTION_FILTER);
1214
+ if (data.sessionId) {
1215
+ statement.append(SQL ` AND sessionId = ${{
1216
+ type: TableColumnType.Text,
1217
+ value: data.sessionId,
836
1218
  }}`);
837
1219
  }
838
- if (data.endTime) {
839
- statement.append(SQL ` AND startTime <= ${{
840
- type: TableColumnType.DateTime64,
841
- value: data.endTime,
842
- }}`);
1220
+ statement.append(SQL ` AND (hasAny(exceptionFingerprints, [${{
1221
+ type: TableColumnType.Text,
1222
+ value: data.exceptionFingerprint,
1223
+ }}])`);
1224
+ if (instanceSessionIds.length > 0) {
1225
+ statement.append(SQL ` OR sessionId IN (${{
1226
+ type: TableColumnType.Text,
1227
+ value: new Includes(instanceSessionIds),
1228
+ }})`);
843
1229
  }
1230
+ statement.append(")");
844
1231
  statement.append(SQL ` GROUP BY projectId, rumApplicationId, sessionId
845
- HAVING hasAny(aggExceptionFingerprints, [${{
1232
+ HAVING (hasAny(aggExceptionFingerprints, [${{
846
1233
  type: TableColumnType.Text,
847
1234
  value: data.exceptionFingerprint,
848
- }}])
849
- ORDER BY aggStartTime DESC
1235
+ }}])`);
1236
+ if (instanceSessionIds.length > 0) {
1237
+ statement.append(SQL ` OR sessionId IN (${{
1238
+ type: TableColumnType.Text,
1239
+ value: new Includes(instanceSessionIds),
1240
+ }})`);
1241
+ }
1242
+ statement.append(")");
1243
+ statement.append(SQL ` ORDER BY aggStartTime DESC
850
1244
  LIMIT ${{
851
1245
  type: TableColumnType.Number,
852
1246
  value: limit,
@@ -877,7 +1271,273 @@ export default class SessionReplayReadService {
877
1271
  };
878
1272
  });
879
1273
  }
880
- static appendListHavingFilters(statement, filters) {
1274
+ /*
1275
+ * Session ids of the pages that threw this exception, from the
1276
+ * exception instance table. The instance's `time` sits inside its
1277
+ * session, so a session that started inside the window threw inside
1278
+ * [startTime, endTime + max session length].
1279
+ *
1280
+ * Best-effort: the side index only ADDS live sessions to the answer, so
1281
+ * a failure here degrades to the finalized-only lookup with a warning
1282
+ * rather than failing the exception page's replay card.
1283
+ *
1284
+ * A caller-pinned sessionId narrows the lookup rather than bypassing it,
1285
+ * so the pin can never assert that a session threw something the
1286
+ * instance table has no record of it throwing.
1287
+ */
1288
+ static async getSessionIdsForExceptionInstances(data) {
1289
+ const statement = SQL `
1290
+ SELECT DISTINCT sessionId
1291
+ FROM ${AnalyticsTableName.ExceptionInstance}
1292
+ WHERE projectId = ${{
1293
+ type: TableColumnType.ObjectID,
1294
+ value: data.projectId,
1295
+ }}
1296
+ AND fingerprint = ${{
1297
+ type: TableColumnType.Text,
1298
+ value: data.exceptionFingerprint,
1299
+ }}
1300
+ AND sessionId != ''
1301
+ AND time >= ${{
1302
+ type: TableColumnType.DateTime64,
1303
+ value: data.startTime,
1304
+ }}
1305
+ AND time <= ${{
1306
+ type: TableColumnType.DateTime64,
1307
+ value: new Date(data.endTime.getTime() + SESSION_REPLAY_MAX_SESSION_MS),
1308
+ }}
1309
+ `;
1310
+ /*
1311
+ * A pinned sessionId narrows this lookup; it does NOT replace it.
1312
+ *
1313
+ * Returning the pinned id unchecked made the caller's statement read
1314
+ * `sessionId = X AND (hasAny(fingerprints, [f]) OR sessionId IN (X))`,
1315
+ * whose second arm is trivially true - so the fingerprint constrained
1316
+ * nothing and the "Watch what the user saw" card would present any
1317
+ * accessible session as having observed this exception, on nothing but
1318
+ * a stale occurrence row. Asking the instance table whether THAT
1319
+ * session threw THIS fingerprint keeps the pin's real purpose (a live
1320
+ * session whose header has no fingerprints yet) while keeping the
1321
+ * claim true. A failure here answers [] and the header's mandatory
1322
+ * hasAny() predicate decides alone - fail closed.
1323
+ */
1324
+ if (data.sessionId) {
1325
+ statement.append(SQL ` AND sessionId = ${{
1326
+ type: TableColumnType.Text,
1327
+ value: data.sessionId,
1328
+ }}`);
1329
+ }
1330
+ statement.append(SQL `
1331
+ ORDER BY sessionId ASC
1332
+ LIMIT ${{
1333
+ type: TableColumnType.Number,
1334
+ value: MAX_EXCEPTION_INSTANCE_SESSION_IDS,
1335
+ }}
1336
+ `);
1337
+ statement.append(READ_QUERY_SETTINGS);
1338
+ try {
1339
+ const dbResult = await ExceptionInstanceService.executeQuery(statement);
1340
+ const response = await dbResult.json();
1341
+ return (response.data || [])
1342
+ .map((row) => {
1343
+ return readString(row, "sessionId");
1344
+ })
1345
+ .filter((sessionId) => {
1346
+ return sessionId.length > 0;
1347
+ });
1348
+ }
1349
+ catch (err) {
1350
+ logger.warn("SessionReplayReadService: could not look up exception instances by session; answering from finalized headers only");
1351
+ logger.warn(err);
1352
+ return [];
1353
+ }
1354
+ }
1355
+ /*
1356
+ * Recording activity for one application over the last 24 hours, for
1357
+ * the health surface. No GROUP BY and no payload: uniqExact over the
1358
+ * sort-key range for the counts, and an ORDER BY startTime DESC LIMIT 1
1359
+ * (read in sort-key order, stops after one granule) for the most recent
1360
+ * start, which is NOT bounded to 24h so "the most recent was 3 days
1361
+ * ago" can be said when today is quiet.
1362
+ *
1363
+ * "Playable" is counted by subtraction: a session is unplayable only
1364
+ * when its FINALIZED row says it holds no chunks or was sealed as
1365
+ * recording-lost. Every other session - live, or finalized with footage
1366
+ * - can be watched. Counted that way because a finalized session still
1367
+ * has its provisional row on disk until a merge runs, and that row
1368
+ * would otherwise count a lost recording as live.
1369
+ *
1370
+ * ClickHouse trouble answers null (the UI says "unknown"), never 0:
1371
+ * "no sessions" and "could not count" are different diagnoses.
1372
+ */
1373
+ static async getApplicationActivitySummary(data) {
1374
+ var _a;
1375
+ const nowUnixMs = (_a = data.nowUnixMs) !== null && _a !== void 0 ? _a : Date.now();
1376
+ const cacheKey = `${data.projectId.toString()}:${data.rumApplicationId.toString()}`;
1377
+ const cached = activitySummaryCache.get(cacheKey);
1378
+ if (cached && cached.expiresAt > nowUnixMs) {
1379
+ return cached.summary;
1380
+ }
1381
+ const summary = await SessionReplayReadService.readApplicationActivitySummary({
1382
+ projectId: data.projectId,
1383
+ rumApplicationId: data.rumApplicationId,
1384
+ nowUnixMs: nowUnixMs,
1385
+ });
1386
+ /*
1387
+ * Coarse LRU: evict the oldest entry when full and the key is new, so
1388
+ * a burst of distinct applications cannot grow the map without bound.
1389
+ */
1390
+ if (activitySummaryCache.size >= MAX_ACTIVITY_SUMMARY_CACHE_ENTRIES &&
1391
+ !activitySummaryCache.has(cacheKey)) {
1392
+ const oldest = activitySummaryCache
1393
+ .keys()
1394
+ .next().value;
1395
+ if (oldest !== undefined) {
1396
+ activitySummaryCache.delete(oldest);
1397
+ }
1398
+ }
1399
+ activitySummaryCache.delete(cacheKey);
1400
+ activitySummaryCache.set(cacheKey, {
1401
+ summary: summary,
1402
+ expiresAt: nowUnixMs + SESSION_REPLAY_ACTIVITY_SUMMARY_CACHE_TTL_MS,
1403
+ });
1404
+ return summary;
1405
+ }
1406
+ static async readApplicationActivitySummary(data) {
1407
+ const countsStatement = SQL `
1408
+ SELECT
1409
+ toFloat64(uniqExact(sessionId)) AS sessionCount,
1410
+ toFloat64(uniqExactIf(sessionId, isFinalized AND (chunkCount = 0 OR sealedReason = ${{
1411
+ type: TableColumnType.Text,
1412
+ value: SessionReplaySealedReason.RecordingLost,
1413
+ }}))) AS unplayableCount
1414
+ FROM ${AnalyticsTableName.RumSession}
1415
+ WHERE projectId = ${{
1416
+ type: TableColumnType.ObjectID,
1417
+ value: data.projectId,
1418
+ }}
1419
+ AND rumApplicationId = ${{
1420
+ type: TableColumnType.ObjectID,
1421
+ value: data.rumApplicationId,
1422
+ }}
1423
+ AND startTime >= ${{
1424
+ type: TableColumnType.DateTime64,
1425
+ value: new Date(data.nowUnixMs - 24 * 60 * 60 * 1000),
1426
+ }}
1427
+ `;
1428
+ countsStatement.append(RETENTION_FILTER);
1429
+ countsStatement.append(READ_QUERY_SETTINGS);
1430
+ const lastStartStatement = SQL `
1431
+ SELECT
1432
+ toFloat64(toUnixTimestamp64Milli(startTime)) AS lastStartUnixMs,
1433
+ /*
1434
+ * The newest session's recorder capabilities, read off the same row
1435
+ * that answers "when did recording last start". Named directly (not
1436
+ * through the argMax alias set) because this statement has no GROUP
1437
+ * BY: it is one row, read in sort-key order, LIMIT 1.
1438
+ */
1439
+ attributes AS aggAttributes
1440
+ FROM ${AnalyticsTableName.RumSession}
1441
+ WHERE projectId = ${{
1442
+ type: TableColumnType.ObjectID,
1443
+ value: data.projectId,
1444
+ }}
1445
+ AND rumApplicationId = ${{
1446
+ type: TableColumnType.ObjectID,
1447
+ value: data.rumApplicationId,
1448
+ }}
1449
+ `;
1450
+ lastStartStatement.append(RETENTION_FILTER);
1451
+ lastStartStatement.append(" ORDER BY startTime DESC LIMIT 1");
1452
+ lastStartStatement.append(READ_QUERY_SETTINGS);
1453
+ try {
1454
+ const [countsResult, lastStartResult] = await Promise.all([
1455
+ RumSessionService.executeQuery(countsStatement),
1456
+ RumSessionService.executeQuery(lastStartStatement),
1457
+ ]);
1458
+ const countsResponse = await countsResult.json();
1459
+ const lastStartResponse = await lastStartResult.json();
1460
+ const countsRow = (countsResponse.data || [])[0];
1461
+ const lastStartRow = (lastStartResponse.data ||
1462
+ [])[0];
1463
+ const sessionCount = countsRow
1464
+ ? readNumber(countsRow, "sessionCount")
1465
+ : 0;
1466
+ const unplayableCount = countsRow
1467
+ ? readNumber(countsRow, "unplayableCount")
1468
+ : 0;
1469
+ const lastStartUnixMs = lastStartRow
1470
+ ? readNumber(lastStartRow, "lastStartUnixMs")
1471
+ : 0;
1472
+ /*
1473
+ * An empty list means "the newest session declared none" (an old
1474
+ * recorder artifact), which is not the same as "we could not tell" -
1475
+ * but the health copy renders both as "not reported yet", and
1476
+ * claiming a recorder has NO capabilities would be a stronger
1477
+ * statement than the row supports. So an empty list answers null and
1478
+ * only a non-empty one is reported.
1479
+ */
1480
+ const recorderCapabilities = lastStartRow
1481
+ ? readRecorderCapabilities(lastStartRow)
1482
+ : [];
1483
+ return {
1484
+ sessionsLast24h: sessionCount,
1485
+ playableSessionsLast24h: Math.max(0, sessionCount - unplayableCount),
1486
+ lastSessionStartedAt: lastStartUnixMs > 0 ? new Date(lastStartUnixMs) : null,
1487
+ recorderCapabilities: recorderCapabilities.length > 0 ? recorderCapabilities : null,
1488
+ };
1489
+ }
1490
+ catch (err) {
1491
+ logger.warn("SessionReplayReadService: could not read the application activity summary");
1492
+ logger.warn(err);
1493
+ return {
1494
+ sessionsLast24h: null,
1495
+ playableSessionsLast24h: null,
1496
+ lastSessionStartedAt: null,
1497
+ recorderCapabilities: null,
1498
+ };
1499
+ }
1500
+ }
1501
+ /* The HAVING/ORDER BY expression for a sort key. */
1502
+ static getSortExpression(sortBy) {
1503
+ switch (sortBy) {
1504
+ case "durationMs":
1505
+ return "aggDurationMs";
1506
+ case "errorCount":
1507
+ return "aggErrorCount";
1508
+ case "frustration":
1509
+ return FRUSTRATION_TOTAL_EXPRESSION;
1510
+ case "startTime":
1511
+ default:
1512
+ return "aggStartTime";
1513
+ }
1514
+ }
1515
+ /* The cursor value of a row under a sort key: what the expression above yields. */
1516
+ static getSortValue(sortBy, item) {
1517
+ switch (sortBy) {
1518
+ case "durationMs":
1519
+ return item.durationMs;
1520
+ case "errorCount":
1521
+ return item.errorCount;
1522
+ case "frustration":
1523
+ return (item.rageClickCount +
1524
+ item.deadClickCount +
1525
+ item.errorClickCount +
1526
+ item.refreshRageCount);
1527
+ case "startTime":
1528
+ default:
1529
+ return item.startTime.getTime();
1530
+ }
1531
+ }
1532
+ /*
1533
+ * Every list predicate, in cost order: booleans and equality over
1534
+ * aliases first, IN lists next, array membership after, and the
1535
+ * substring predicates (tags, urlPrefix, search) LAST. ClickHouse
1536
+ * evaluates HAVING per group after aggregation, so the order does not
1537
+ * change what is scanned, but a cheap predicate that fails first spares
1538
+ * the string work for every group it eliminates.
1539
+ */
1540
+ static appendListHavingFilters(statement, filters, includeIdentifiedUserLabel) {
881
1541
  if (filters.hasError !== undefined) {
882
1542
  statement.append(SQL ` AND aggHasError = ${{
883
1543
  type: TableColumnType.Boolean,
@@ -895,8 +1555,9 @@ export default class SessionReplayReadService {
895
1555
  * honour false, so accepting the value and ignoring it returned the
896
1556
  * whole unfiltered list with a 200 and no indication why.
897
1557
  */
898
- const total = "(aggRageClickCount + aggDeadClickCount + aggErrorClickCount + aggRefreshRageCount)";
899
- statement.append(filters.hasFrustration ? ` AND ${total} > 0` : ` AND ${total} = 0`);
1558
+ statement.append(filters.hasFrustration
1559
+ ? ` AND ${FRUSTRATION_TOTAL_EXPRESSION} > 0`
1560
+ : ` AND ${FRUSTRATION_TOTAL_EXPRESSION} = 0`);
900
1561
  }
901
1562
  if (filters.isFinalized !== undefined) {
902
1563
  statement.append(SQL ` AND aggIsFinalized = ${{
@@ -904,6 +1565,27 @@ export default class SessionReplayReadService {
904
1565
  value: filters.isFinalized,
905
1566
  }}`);
906
1567
  }
1568
+ if (filters.hasIdentifiedUser !== undefined) {
1569
+ /*
1570
+ * The digest column, not the label: it is under the ordinary session
1571
+ * ACL, and "did somebody identify" discloses nothing about who.
1572
+ */
1573
+ statement.append(filters.hasIdentifiedUser
1574
+ ? " AND aggIdentifiedUserKey != ''"
1575
+ : " AND aggIdentifiedUserKey = ''");
1576
+ }
1577
+ if (filters.isPlayable !== undefined) {
1578
+ /*
1579
+ * A live session is playable (its chunks are being written); a
1580
+ * finalized one only when the finalizer counted chunks and did not
1581
+ * seal it as lost.
1582
+ */
1583
+ const playable = `((aggIsFinalized = 0 OR aggChunkCount > 0) AND aggSealedReason != '${SessionReplaySealedReason.RecordingLost}')`;
1584
+ statement.append(filters.isPlayable ? ` AND ${playable}` : ` AND NOT ${playable}`);
1585
+ }
1586
+ if (filters.hasTraces !== undefined) {
1587
+ statement.append(filters.hasTraces ? " AND aggTraceCount > 0" : " AND aggTraceCount = 0");
1588
+ }
907
1589
  if (filters.triggerReasons && filters.triggerReasons.length > 0) {
908
1590
  statement.append(SQL ` AND aggTriggerReason IN (${{
909
1591
  type: TableColumnType.Text,
@@ -942,16 +1624,10 @@ export default class SessionReplayReadService {
942
1624
  }
943
1625
  if (filters.route) {
944
1626
  /*
945
- * `has`, not a Search/LIKE. StatementGenerator's own comment calls
946
- * restoring the exact-match array fast path "the single biggest
947
- * performance fix" - a lowerUTF8 arrayExists has no bloom
948
- * pre-filter and full-scans the table.
949
- *
950
- * The argMax expression is appended as raw SQL rather than
951
- * interpolated into the template: a plain string substituted into
952
- * an SQL`` literal is bound as an Identifier and would be quoted.
1627
+ * `has`, not a Search/LIKE: exact membership is the cheap array
1628
+ * path. Over the argMax alias, never the raw column.
953
1629
  */
954
- statement.append(` AND has(${argMaxColumn("routes")}, `);
1630
+ statement.append(" AND has(aggRoutes, ");
955
1631
  statement.append(SQL `${{
956
1632
  type: TableColumnType.Text,
957
1633
  value: filters.route,
@@ -964,6 +1640,99 @@ export default class SessionReplayReadService {
964
1640
  value: filters.minDurationMs,
965
1641
  }}`);
966
1642
  }
1643
+ if (filters.tags) {
1644
+ /*
1645
+ * Every pair must match. mapContains first so an absent key never
1646
+ * matches the empty string a Map subscript returns for it. Bounded
1647
+ * by the number of tags a session can even carry.
1648
+ */
1649
+ const pairs = Object.entries(filters.tags)
1650
+ .filter(([key, value]) => {
1651
+ return key.length > 0 && typeof value === "string";
1652
+ })
1653
+ .slice(0, SESSION_REPLAY_MAX_TAG_KEYS);
1654
+ for (const [key, value] of pairs) {
1655
+ statement.append(" AND mapContains(aggTags, ");
1656
+ statement.append(SQL `${{
1657
+ type: TableColumnType.Text,
1658
+ value: key,
1659
+ }}) AND aggTags[${{
1660
+ type: TableColumnType.Text,
1661
+ value: key,
1662
+ }}] = ${{
1663
+ type: TableColumnType.Text,
1664
+ value: value,
1665
+ }}`);
1666
+ }
1667
+ }
1668
+ if (filters.urlPrefix) {
1669
+ /*
1670
+ * "sessions that touched /checkout/*": a prefix over every route the
1671
+ * session visited and over the entry URL, which for a pre-migration
1672
+ * session is the only URL the header holds.
1673
+ *
1674
+ * The stored values are scrubbed ABSOLUTE urls (https://host/path),
1675
+ * but the filter a human types is a PATH - the search box routes any
1676
+ * value beginning with "/" here, and the docs promise `url:/checkout`
1677
+ * outright. Matching only the full string meant that documented
1678
+ * search never matched anything, in any project, with no error to
1679
+ * say so. So the path of each route and of the entry URL is matched
1680
+ * as well as the whole URL: an absolute prefix still matches on the
1681
+ * first arm, a path prefix on the second. ClickHouse's path() returns
1682
+ * the path component without host or query, which is exactly the
1683
+ * shape the recorder's route list is scrubbed down to.
1684
+ */
1685
+ const prefixParameter = {
1686
+ type: TableColumnType.Text,
1687
+ value: filters.urlPrefix,
1688
+ };
1689
+ statement.append(" AND (arrayExists(r -> startsWith(r, ");
1690
+ statement.append(SQL `${prefixParameter}`);
1691
+ statement.append(") OR startsWith(path(r), ");
1692
+ statement.append(SQL `${prefixParameter}`);
1693
+ statement.append("), aggRoutes) OR startsWith(aggEntryUrl, ");
1694
+ statement.append(SQL `${prefixParameter}`);
1695
+ statement.append(") OR startsWith(path(aggEntryUrl), ");
1696
+ statement.append(SQL `${prefixParameter}`);
1697
+ statement.append("))");
1698
+ }
1699
+ if (filters.search) {
1700
+ SessionReplayReadService.appendSearchPredicate(statement, filters.search, includeIdentifiedUserLabel);
1701
+ }
1702
+ }
1703
+ /*
1704
+ * Free-text search, last of the predicates because it is the only one
1705
+ * that does substring work per group. The identified user label is
1706
+ * searched ONLY when the caller may read it: without that gate a caller
1707
+ * denied the label could ask "is jane@example.com here" and read every
1708
+ * other field of the answer.
1709
+ */
1710
+ static appendSearchPredicate(statement, search, includeIdentifiedUserLabel) {
1711
+ const term = search
1712
+ .trim()
1713
+ .substring(0, SESSION_REPLAY_LIST_SEARCH_MAX_LENGTH);
1714
+ if (!term) {
1715
+ return;
1716
+ }
1717
+ const textParameter = {
1718
+ type: TableColumnType.Text,
1719
+ value: term,
1720
+ };
1721
+ statement.append(" AND (startsWith(sessionId, ");
1722
+ statement.append(SQL `${textParameter})`);
1723
+ statement.append(" OR positionCaseInsensitiveUTF8(aggEntryUrl, ");
1724
+ statement.append(SQL `${textParameter}) > 0`);
1725
+ statement.append(" OR positionCaseInsensitiveUTF8(aggExitUrl, ");
1726
+ statement.append(SQL `${textParameter}) > 0`);
1727
+ statement.append(" OR arrayExists(r -> positionCaseInsensitiveUTF8(r, ");
1728
+ statement.append(SQL `${textParameter}) > 0, aggRoutes)`);
1729
+ statement.append(` OR has(${argMaxColumn("traceIds")}, `);
1730
+ statement.append(SQL `${textParameter})`);
1731
+ if (includeIdentifiedUserLabel) {
1732
+ statement.append(" OR positionCaseInsensitiveUTF8(aggIdentifiedUserLabel, ");
1733
+ statement.append(SQL `${textParameter}) > 0`);
1734
+ }
1735
+ statement.append(")");
967
1736
  }
968
1737
  }
969
1738
  __decorate([
@@ -983,13 +1752,19 @@ __decorate([
983
1752
  __metadata("design:type", Function),
984
1753
  __metadata("design:paramtypes", [Object]),
985
1754
  __metadata("design:returntype", Promise)
986
- ], SessionReplayReadService, "getManifest", null);
1755
+ ], SessionReplayReadService, "getSessionIdentity", null);
987
1756
  __decorate([
988
1757
  CaptureSpan(),
989
1758
  __metadata("design:type", Function),
990
1759
  __metadata("design:paramtypes", [Object]),
991
1760
  __metadata("design:returntype", Promise)
992
- ], SessionReplayReadService, "getChunkStoredBytes", null);
1761
+ ], SessionReplayReadService, "getExpiredSessionInfo", null);
1762
+ __decorate([
1763
+ CaptureSpan(),
1764
+ __metadata("design:type", Function),
1765
+ __metadata("design:paramtypes", [Object]),
1766
+ __metadata("design:returntype", Promise)
1767
+ ], SessionReplayReadService, "getManifest", null);
993
1768
  __decorate([
994
1769
  CaptureSpan(),
995
1770
  __metadata("design:type", Function),
@@ -1002,4 +1777,10 @@ __decorate([
1002
1777
  __metadata("design:paramtypes", [Object]),
1003
1778
  __metadata("design:returntype", Promise)
1004
1779
  ], SessionReplayReadService, "getSessionsForException", null);
1780
+ __decorate([
1781
+ CaptureSpan(),
1782
+ __metadata("design:type", Function),
1783
+ __metadata("design:paramtypes", [Object]),
1784
+ __metadata("design:returntype", Promise)
1785
+ ], SessionReplayReadService, "getApplicationActivitySummary", null);
1005
1786
  //# sourceMappingURL=SessionReplayReadService.js.map