@oneuptime/common 14.0.2 → 14.0.5

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 (765) hide show
  1. package/Models/DatabaseModels/Alert.ts +55 -0
  2. package/Models/DatabaseModels/AlertFeed.ts +2 -0
  3. package/Models/DatabaseModels/DatabaseServer.ts +1650 -0
  4. package/Models/DatabaseModels/DatabaseServerEndpoint.ts +540 -0
  5. package/Models/DatabaseModels/DatabaseServerFeed.ts +625 -0
  6. package/Models/DatabaseModels/DatabaseServerLabelRule.ts +514 -0
  7. package/Models/DatabaseModels/DatabaseServerOwnerRule.ts +596 -0
  8. package/Models/DatabaseModels/DatabaseServerOwnerTeam.ts +491 -0
  9. package/Models/DatabaseModels/DatabaseServerOwnerUser.ts +490 -0
  10. package/Models/DatabaseModels/Incident.ts +55 -0
  11. package/Models/DatabaseModels/IncidentAlert.ts +540 -0
  12. package/Models/DatabaseModels/IncidentFeed.ts +2 -0
  13. package/Models/DatabaseModels/Index.ts +18 -0
  14. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +26 -0
  15. package/Models/DatabaseModels/Project.ts +60 -0
  16. package/Models/DatabaseModels/RumApplication.ts +52 -1
  17. package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
  18. package/Models/DatabaseModels/TelemetryException.ts +2 -0
  19. package/Models/DatabaseModels/UserProjectSsoConsent.ts +146 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.ts +28 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.ts +89 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.ts +673 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.ts +51 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  25. package/Server/Middleware/MultipartFormData.ts +1 -1
  26. package/Server/Middleware/TelemetryIngest.ts +15 -8
  27. package/Server/Services/AlertReminderRuleService.ts +100 -24
  28. package/Server/Services/DatabaseServerEndpointService.ts +895 -0
  29. package/Server/Services/DatabaseServerFeedService.ts +128 -0
  30. package/Server/Services/DatabaseServerLabelRuleEngineService.ts +340 -0
  31. package/Server/Services/DatabaseServerLabelRuleService.ts +14 -0
  32. package/Server/Services/DatabaseServerOwnerRuleEngineService.ts +425 -0
  33. package/Server/Services/DatabaseServerOwnerRuleService.ts +14 -0
  34. package/Server/Services/DatabaseServerOwnerTeamService.ts +180 -0
  35. package/Server/Services/DatabaseServerOwnerUserService.ts +173 -0
  36. package/Server/Services/DatabaseServerService.ts +4546 -0
  37. package/Server/Services/DatabaseService.ts +14 -8
  38. package/Server/Services/DockerResourceService.ts +43 -2
  39. package/Server/Services/IncidentAlertService.ts +1811 -0
  40. package/Server/Services/IncidentReminderRuleService.ts +103 -23
  41. package/Server/Services/IncidentService.ts +210 -10
  42. package/Server/Services/IncidentStateTimelineService.ts +24 -0
  43. package/Server/Services/Index.ts +18 -0
  44. package/Server/Services/InventoryItemService.ts +113 -5
  45. package/Server/Services/IoTDeviceService.ts +145 -37
  46. package/Server/Services/OpenTelemetryIngestService.ts +19 -0
  47. package/Server/Services/PodmanResourceService.ts +43 -2
  48. package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +107 -23
  49. package/Server/Services/ServiceService.ts +1 -1
  50. package/Server/Services/TelemetryUsageBillingService.ts +29 -2
  51. package/Server/Services/UserProjectSsoConsentService.ts +74 -0
  52. package/Server/Services/UserService.ts +14 -1
  53. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +18 -0
  54. package/Server/Types/Database/QueryHelper.ts +30 -1
  55. package/Server/Utils/AI/Toolbox/ResourceTools.ts +69 -1
  56. package/Server/Utils/Database/AffectedResourceRelations.ts +6 -0
  57. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +188 -6
  58. package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
  59. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +2262 -755
  60. package/Server/Utils/Monitor/MonitorIncident.ts +28 -1
  61. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +268 -6
  62. package/Server/Utils/Monitor/MonitorResource.ts +47 -11
  63. package/Server/Utils/Monitor/MonitorResourceContext.ts +1 -0
  64. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +239 -21
  65. package/Server/Utils/Monitor/PerSeriesResolutionRootCause.ts +43 -0
  66. package/Server/Utils/Monitor/SeriesResourceLabels.ts +291 -0
  67. package/Server/Utils/Monitor/SeriesResourceLinker.ts +111 -12
  68. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
  69. package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +24 -2
  70. package/Server/Utils/StartServer.ts +26 -6
  71. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
  72. package/Server/Utils/Telemetry/DatabaseEndpointDiscovery.ts +688 -0
  73. package/Server/Utils/Telemetry/EntityRegistry.ts +5 -1
  74. package/Server/Utils/Telemetry/LogExceptionExtractor.ts +18 -1
  75. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +175 -12
  76. package/Server/Utils/Telemetry/ResourceFacetResolver.ts +12 -0
  77. package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +606 -36
  78. package/Server/Utils/Telemetry/Telemetry.ts +16 -0
  79. package/Server/Utils/Telemetry/TelemetryEntity.ts +22 -22
  80. package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +16 -10
  81. package/Tests/App/Accounts/SignedInRedirect.test.tsx +241 -0
  82. package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +221 -4
  83. package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +42 -0
  84. package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +100 -0
  85. package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +86 -0
  86. package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +2 -0
  87. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +19 -0
  88. package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +14 -0
  89. package/Tests/App/Dashboard/BulkIncidentLinkActions.test.tsx +869 -0
  90. package/Tests/App/Dashboard/CephMetricTooltips.test.tsx +1777 -0
  91. package/Tests/App/Dashboard/CloudFleetSummary.test.ts +8 -0
  92. package/Tests/App/Dashboard/CloudMetricTooltips.test.tsx +887 -0
  93. package/Tests/App/Dashboard/ContainerHostMetricTooltips.test.tsx +1309 -0
  94. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +26 -1
  95. package/Tests/App/Dashboard/DashboardAppSsoError.test.tsx +501 -0
  96. package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +64 -1
  97. package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +178 -18
  98. package/Tests/App/Dashboard/DashboardMasterPageSsoRedirect.test.tsx +444 -0
  99. package/Tests/App/Dashboard/DashboardNavBarForeignHiddenRule.test.tsx +573 -0
  100. package/Tests/App/Dashboard/DatabaseChartAxes.test.tsx +431 -0
  101. package/Tests/App/Dashboard/DatabaseContainerDetailBadge.test.tsx +249 -0
  102. package/Tests/App/Dashboard/DatabaseDashboardE2EFixes.test.ts +681 -0
  103. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +1801 -0
  104. package/Tests/App/Dashboard/DatabaseFleetSummaryRefresh.test.tsx +280 -0
  105. package/Tests/App/Dashboard/DatabaseFormHelpers.test.tsx +321 -0
  106. package/Tests/App/Dashboard/DatabaseMetricMonitorLink.test.tsx +795 -0
  107. package/Tests/App/Dashboard/DatabaseOverviewHeader.test.tsx +580 -0
  108. package/Tests/App/Dashboard/DatabaseRecommendationsEngineMetrics.test.ts +270 -0
  109. package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +1486 -0
  110. package/Tests/App/Dashboard/DatabaseServerEngineMetricsFilter.test.ts +223 -0
  111. package/Tests/App/Dashboard/DatabaseServerPresentation.test.ts +435 -0
  112. package/Tests/App/Dashboard/DatabaseServerSummary.test.ts +186 -0
  113. package/Tests/App/Dashboard/DatabaseServerTelemetryQueries.test.ts +1553 -0
  114. package/Tests/App/Dashboard/DatabaseTableTruncation.test.tsx +326 -0
  115. package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +512 -0
  116. package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +774 -0
  117. package/Tests/App/Dashboard/DatabaseViewLayout.test.tsx +233 -0
  118. package/Tests/App/Dashboard/DatabaseWorkloadBadge.test.tsx +972 -0
  119. package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +5 -0
  120. package/Tests/App/Dashboard/DiscoveryReviewUnnamedHostHint.test.tsx +1061 -0
  121. package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +39 -0
  122. package/Tests/App/Dashboard/DockerSwarmClustersListTooltips.test.tsx +414 -0
  123. package/Tests/App/Dashboard/DockerSwarmMetricTooltips.test.ts +796 -0
  124. package/Tests/App/Dashboard/DockerSwarmOverviewTooltips.test.tsx +747 -0
  125. package/Tests/App/Dashboard/EventOverlayScope.test.ts +147 -0
  126. package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +1 -0
  127. package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +38 -18
  128. package/Tests/App/Dashboard/HostDetailViewTooltips.test.tsx +725 -0
  129. package/Tests/App/Dashboard/HostListColumnTooltips.test.tsx +472 -0
  130. package/Tests/App/Dashboard/HostMetricTooltips.test.ts +709 -0
  131. package/Tests/App/Dashboard/HostOverviewTooltips.test.tsx +698 -0
  132. package/Tests/App/Dashboard/HostTooltipHarness.ts +124 -0
  133. package/Tests/App/Dashboard/HostsListTooltips.test.tsx +395 -0
  134. package/Tests/App/Dashboard/IncidentAlertLinkDialog.test.tsx +691 -0
  135. package/Tests/App/Dashboard/IncidentAlertLinkHelpers.test.ts +458 -0
  136. package/Tests/App/Dashboard/IncidentAlertLinkPages.test.tsx +828 -0
  137. package/Tests/App/Dashboard/IncidentAlertLinkSideMenus.test.tsx +231 -0
  138. package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +689 -0
  139. package/Tests/App/Dashboard/IoTMetricTooltips.test.tsx +1123 -0
  140. package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +837 -0
  141. package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +699 -0
  142. package/Tests/App/Dashboard/KubernetesContainersTabTooltips.test.tsx +320 -0
  143. package/Tests/App/Dashboard/KubernetesCostTooltips.test.tsx +502 -0
  144. package/Tests/App/Dashboard/KubernetesInsightsTooltips.test.tsx +222 -0
  145. package/Tests/App/Dashboard/KubernetesResourceMetricTooltips.test.ts +561 -0
  146. package/Tests/App/Dashboard/KubernetesResourcePagesTooltips.test.tsx +1168 -0
  147. package/Tests/App/Dashboard/LinkIncidentAlertModal.test.tsx +154 -0
  148. package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +1 -0
  149. package/Tests/App/Dashboard/MetricDescriptionRules.ts +170 -0
  150. package/Tests/App/Dashboard/MetricDescriptionsCatalog.test.ts +206 -0
  151. package/Tests/App/Dashboard/MetricDescriptionsConsistency.test.ts +275 -0
  152. package/Tests/App/Dashboard/MetricsViewerDrillDown.test.tsx +310 -0
  153. package/Tests/App/Dashboard/MetricsViewerEntityScopedRows.test.tsx +495 -0
  154. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +132 -1
  155. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +5 -0
  156. package/Tests/App/Dashboard/NetworkDeviceTooltips.test.tsx +852 -0
  157. package/Tests/App/Dashboard/NetworkDiagnosticsTooltips.test.tsx +556 -0
  158. package/Tests/App/Dashboard/NetworkMetricTooltips.test.ts +1348 -0
  159. package/Tests/App/Dashboard/NetworkSiteTooltips.test.tsx +679 -0
  160. package/Tests/App/Dashboard/ProductOrientation.test.tsx +4 -3
  161. package/Tests/App/Dashboard/ProxmoxMetricTooltips.test.ts +592 -0
  162. package/Tests/App/Dashboard/ProxmoxOverviewTooltips.test.tsx +1002 -0
  163. package/Tests/App/Dashboard/ProxmoxResourcePageTooltips.test.tsx +923 -0
  164. package/Tests/App/Dashboard/RecommendationsLoadedContext.test.tsx +349 -0
  165. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +62 -0
  166. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
  167. package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +14 -0
  168. package/Tests/App/Dashboard/ResourceOverviewTileTooltips.test.tsx +1066 -0
  169. package/Tests/App/Dashboard/RumOverviewPage.test.tsx +1195 -0
  170. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +2 -0
  171. package/Tests/App/Dashboard/ServerlessMetricTooltips.test.tsx +474 -0
  172. package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +1085 -0
  173. package/Tests/App/Dashboard/ServiceMetricTooltips.test.tsx +772 -0
  174. package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +56 -1
  175. package/Tests/App/Dashboard/TelemetryMetricsSignals.test.ts +1207 -0
  176. package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +10 -0
  177. package/Tests/App/Dashboard/TelemetryResourceTabTooltips.test.tsx +437 -0
  178. package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +2 -1
  179. package/Tests/App/Dashboard/VMwareMetricTooltips.test.ts +801 -0
  180. package/Tests/App/Dashboard/VMwareOverviewTooltips.test.tsx +601 -0
  181. package/Tests/App/Dashboard/VMwareResourcePagesTooltips.test.tsx +646 -0
  182. package/Tests/App/Dashboard/VMwareTooltipHarness.ts +145 -0
  183. package/Tests/App/StatusPage/StatusPageHeaderForeignHiddenRule.test.tsx +284 -0
  184. package/Tests/ClassStrings.ts +178 -0
  185. package/Tests/Fixtures/MobilePasskeyUser.json +1 -2
  186. package/Tests/ForeignHiddenRuleGuard.ts +2152 -0
  187. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +2250 -0
  188. package/Tests/Models/DatabaseModels/IncidentAlertModel.test.ts +554 -0
  189. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +24 -5
  190. package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +117 -0
  191. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  192. package/Tests/RenderedMarkup.ts +518 -0
  193. package/Tests/ResponsiveVisibility.test.ts +490 -4
  194. package/Tests/ResponsiveVisibility.ts +505 -52
  195. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  196. package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +541 -0
  197. package/Tests/Server/Infrastructure/Postgres/AddIncidentAlertMigration.test.ts +341 -0
  198. package/Tests/Server/Infrastructure/Postgres/AddSessionReplaySameOriginTracePropagationMigration.test.ts +247 -0
  199. package/Tests/Server/Infrastructure/Postgres/AddUserProjectSsoConsentMigration.test.ts +234 -0
  200. package/Tests/Server/Services/ContainerSnapshotUpsertPostgres.test.ts +319 -0
  201. package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +13 -0
  202. package/Tests/Server/Services/DatabaseServerEndpointService.test.ts +2033 -0
  203. package/Tests/Server/Services/DatabaseServerFeedAndOwnerServices.test.ts +529 -0
  204. package/Tests/Server/Services/DatabaseServerLifecycle.test.ts +3302 -0
  205. package/Tests/Server/Services/DatabaseServerRegistries.test.ts +603 -0
  206. package/Tests/Server/Services/DatabaseServerRuleEngines.test.ts +754 -0
  207. package/Tests/Server/Services/DatabaseServerService.test.ts +3558 -0
  208. package/Tests/Server/Services/DatabaseServerSqlPostgres.test.ts +2045 -0
  209. package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedPostgres.test.ts +362 -0
  210. package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedReply.test.ts +210 -0
  211. package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +18 -0
  212. package/Tests/Server/Services/IncidentAlertPostgres.test.ts +903 -0
  213. package/Tests/Server/Services/IncidentAlertRegistration.test.ts +96 -0
  214. package/Tests/Server/Services/IncidentAlertService.test.ts +2225 -0
  215. package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +2 -0
  216. package/Tests/Server/Services/IncidentAlertStateCascade.test.ts +970 -0
  217. package/Tests/Server/Services/IncidentCreateFromAlerts.test.ts +1284 -0
  218. package/Tests/Server/Services/IncomingCallPolicyEscalationRuleTarget.test.ts +225 -0
  219. package/Tests/Server/Services/InventoryItemDisplayName.test.ts +280 -2
  220. package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +8 -2
  221. package/Tests/Server/Services/IoTDeviceLatestMetricsPostgres.test.ts +689 -0
  222. package/Tests/Server/Services/IoTDeviceService.test.ts +379 -0
  223. package/Tests/Server/Services/LatestMetricsValuesShape.test.ts +360 -0
  224. package/Tests/Server/Services/LlmModelPriceService.test.ts +402 -0
  225. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
  226. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +61 -9
  227. package/Tests/Server/Services/ReminderRuleLookupPostgres.test.ts +2250 -0
  228. package/Tests/Server/Services/ReminderRuleRefreshOpenSubjectsPaging.test.ts +653 -0
  229. package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +68 -20
  230. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
  231. package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +9 -0
  232. package/Tests/Server/Services/UserProjectSsoConsentPostgres.test.ts +153 -0
  233. package/Tests/Server/Services/UserProjectSsoConsentService.test.ts +192 -0
  234. package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +71 -0
  235. package/Tests/Server/Services/UserSignupIdTakeoverPostgres.test.ts +238 -0
  236. package/Tests/Server/Services/WorkspaceNotificationSummaryHelpers.test.ts +592 -0
  237. package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +3 -0
  238. package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +1 -0
  239. package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +11 -0
  240. package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +8 -0
  241. package/Tests/Server/Types/Database/QueryHelperBooleanForCriteriaBackedRule.test.ts +1094 -0
  242. package/Tests/Server/Utils/AI/ResourceTools.test.ts +134 -0
  243. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +41 -0
  244. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +279 -9
  245. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaDisplayContext.test.ts +933 -0
  246. package/Tests/Server/Utils/Monitor/DatabaseMaintenanceSuppression.test.ts +582 -0
  247. package/Tests/Server/Utils/Monitor/DatabaseServerMonitorLinking.test.ts +753 -0
  248. package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +1 -0
  249. package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +1 -0
  250. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +119 -0
  251. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +60 -25
  252. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorAffectedResourceEdgeCases.test.ts +1719 -0
  253. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesAffectedResources.test.ts +1447 -0
  254. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesRatioEmail.test.ts +352 -0
  255. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformMetricUnits.test.ts +717 -0
  256. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformRawScan.test.ts +2125 -0
  257. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformSeriesAffectedResources.test.ts +1288 -0
  258. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
  259. package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +1 -0
  260. package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +1 -0
  261. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +88 -0
  262. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +205 -0
  263. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +62 -0
  264. package/Tests/Server/Utils/Monitor/MonitorResourceDatabaseMaintenance.test.ts +803 -0
  265. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +133 -3
  266. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
  267. package/Tests/Server/Utils/Monitor/PerSeriesRecoveryResolution.test.ts +472 -1
  268. package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
  269. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +236 -2
  270. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +70 -0
  271. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +103 -0
  272. package/Tests/Server/Utils/StartServerProtobufContentType.test.ts +54 -0
  273. package/Tests/Server/Utils/Telemetry/DatabaseEndpointDiscovery.test.ts +1895 -0
  274. package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +7 -0
  275. package/Tests/Server/Utils/Telemetry/LogExceptionExtractorSeverityGate.test.ts +90 -0
  276. package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +570 -0
  277. package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +97 -2
  278. package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +1337 -0
  279. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +295 -0
  280. package/Tests/Types/AI/AIResourceContext.test.ts +30 -0
  281. package/Tests/Types/DatabaseServer/DatabaseContainerClassifier.test.ts +3644 -0
  282. package/Tests/Types/DatabaseServer/DatabaseContainerCommand.test.ts +340 -0
  283. package/Tests/Types/DatabaseServer/DatabaseContainerCommandCorpus.ts +826 -0
  284. package/Tests/Types/DatabaseServer/DatabaseContainerCommandPostgres.test.ts +150 -0
  285. package/Tests/Types/DatabaseServer/DatabaseEndpoint.test.ts +2657 -0
  286. package/Tests/Types/DatabaseServer/DatabaseServerDiscoverySource.test.ts +64 -0
  287. package/Tests/Types/DatabaseServer/DatabaseServerEntityKeys.test.ts +952 -0
  288. package/Tests/Types/DatabaseServer/DatabaseServerMetricCatalog.test.ts +1161 -0
  289. package/Tests/Types/DatabaseServer/DatabaseSystem.test.ts +1514 -0
  290. package/Tests/Types/DatabaseServer/DatabaseTelemetryResolver.test.ts +1558 -0
  291. package/Tests/Types/Monitor/CephAlertTemplates.test.ts +255 -6
  292. package/Tests/Types/Monitor/DatabaseAlertTemplates.test.ts +2254 -0
  293. package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +298 -0
  294. package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +271 -0
  295. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +253 -9
  296. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +13 -5
  297. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +4 -2
  298. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +111 -2
  299. package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +61 -0
  300. package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +114 -0
  301. package/Tests/Types/Monitor/Utils/KubernetesAgentEmittedMetrics.ts +181 -0
  302. package/Tests/Types/NetworkDevice/DiscoveredHostNamingStatus.test.ts +401 -0
  303. package/Tests/Types/Rum/WebVitals.test.ts +173 -0
  304. package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +4 -1
  305. package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +24 -2
  306. package/Tests/UI/Components/Card.test.tsx +93 -2
  307. package/Tests/UI/Components/FeedOptions.test.ts +6 -0
  308. package/Tests/UI/Components/FeedOptionsButton.test.tsx +8 -1
  309. package/Tests/UI/Components/FieldLabelInfoCardTooltip.test.tsx +413 -0
  310. package/Tests/UI/Components/ForeignHiddenRuleResilience.test.tsx +1147 -0
  311. package/Tests/UI/Components/HeaderRightRail.test.tsx +41 -1
  312. package/Tests/UI/Components/InfoTooltip.test.tsx +242 -0
  313. package/Tests/UI/Components/LogsEntityNames.test.ts +16 -1
  314. package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +7 -3
  315. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +207 -3
  316. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDeleteVerb.test.tsx +367 -0
  317. package/Tests/UI/Components/ModelTable/BaseModelTableCreateButtonTitle.test.tsx +275 -0
  318. package/Tests/UI/Components/ResourceFacetConfigs.test.ts +2 -1
  319. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  320. package/Tests/UI/Components/SrOnlyForeignRule.test.tsx +994 -0
  321. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +34 -1
  322. package/Tests/UI/Components/TableHeaderTooltip.test.tsx +662 -0
  323. package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +4 -1
  324. package/Tests/UI/ForeignHiddenRuleGuard.test.ts +1951 -0
  325. package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +166 -9
  326. package/Tests/UI/Rum/RecordingHealthTooltips.test.tsx +447 -0
  327. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +164 -0
  328. package/Tests/UI/Rum/ReplayFrameCapture.test.ts +6750 -0
  329. package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +19 -1
  330. package/Tests/UI/Rum/ReplayRail.test.tsx +723 -12
  331. package/Tests/UI/Rum/ReplayRailDetail.test.tsx +86 -0
  332. package/Tests/UI/Rum/ReplayScreenshot.test.ts +2124 -0
  333. package/Tests/UI/Rum/ReplayScreenshotActions.test.tsx +3288 -0
  334. package/Tests/UI/Rum/ReplayStage.test.tsx +62 -0
  335. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +983 -2
  336. package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +19 -1
  337. package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +149 -0
  338. package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +107 -6
  339. package/Tests/UI/Rum/SessionReplayUsersTableTooltips.test.tsx +330 -0
  340. package/Tests/UI/Rum/UserFlowTooltips.test.tsx +886 -0
  341. package/Tests/UI/TailwindPlayCdnForeignHiddenRule.test.ts +1005 -0
  342. package/Tests/UI/ThemeGroupHoverReveal.test.ts +847 -0
  343. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +80 -0
  344. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +23 -0
  345. package/Tests/UI/Utils/ModelAPISsoRedirect.test.ts +127 -0
  346. package/Tests/UI/Utils/Navigation.test.ts +102 -0
  347. package/Tests/UI/Utils/PermissionGate.test.ts +76 -0
  348. package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +23 -0
  349. package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +696 -0
  350. package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
  351. package/Tests/Utils/MetricUnitUtil.test.ts +227 -2
  352. package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +288 -2
  353. package/Tests/Utils/Monitor/PlatformResourceIdentityAndUnits.test.ts +1559 -0
  354. package/Tests/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.test.ts +2546 -0
  355. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +315 -0
  356. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +336 -1
  357. package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +244 -0
  358. package/Tests/Utils/Rum/SessionTraceState.test.ts +239 -0
  359. package/Tests/Utils/ValueFormatter.test.ts +50 -0
  360. package/Tests/tsconfig.json +16 -0
  361. package/Types/AI/AIResourceContext.ts +7 -0
  362. package/Types/Dashboard/DashboardTemplates.ts +2 -1
  363. package/Types/DatabaseServer/DatabaseConnectionSpan.ts +77 -0
  364. package/Types/DatabaseServer/DatabaseContainerClassifier.ts +2068 -0
  365. package/Types/DatabaseServer/DatabaseContainerCommand.ts +801 -0
  366. package/Types/DatabaseServer/DatabaseEndpoint.ts +1943 -0
  367. package/Types/DatabaseServer/DatabaseServerDiscoverySource.ts +68 -0
  368. package/Types/DatabaseServer/DatabaseServerMetricCatalog.ts +966 -0
  369. package/Types/DatabaseServer/DatabaseSystem.ts +2124 -0
  370. package/Types/DatabaseServer/DatabaseTelemetryResolver.ts +555 -0
  371. package/Types/Email/EmailTemplateType.ts +1 -0
  372. package/Types/Incident/IncidentAlertLink.ts +38 -0
  373. package/Types/Monitor/CephAlertTemplates.ts +18 -0
  374. package/Types/Monitor/DatabaseAlertTemplates.ts +2020 -0
  375. package/Types/Monitor/KubernetesAlertTemplates.ts +64 -24
  376. package/Types/Monitor/KubernetesMetricCatalog.ts +118 -19
  377. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +14 -0
  378. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +93 -10
  379. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +109 -8
  380. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +36 -7
  381. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +43 -2
  382. package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +41 -6
  383. package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +26 -0
  384. package/Types/NetworkDevice/DiscoveredHostNamingStatus.ts +147 -0
  385. package/Types/Permission.ts +315 -0
  386. package/Types/Probe/ProbeApiIngestResponse.ts +8 -0
  387. package/Types/Rules/RuleCriteriaFieldRegistry.ts +10 -0
  388. package/Types/Rules/RuleRun.ts +12 -0
  389. package/Types/Rum/SessionReplay.ts +25 -6
  390. package/Types/Rum/WebVitals.ts +52 -0
  391. package/Types/Telemetry/EntityType.ts +23 -0
  392. package/Types/Telemetry/ResourceFacetCatalog.ts +14 -0
  393. package/Types/Telemetry/ServiceType.ts +8 -0
  394. package/UI/Components/Banner/Banner.tsx +1 -1
  395. package/UI/Components/Card/Card.tsx +1 -1
  396. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +2 -2
  397. package/UI/Components/Charts/Line/LineChart.tsx +7 -0
  398. package/UI/Components/CommandPalette/CommandPalette.tsx +1 -1
  399. package/UI/Components/Date/StartAndEndDate.tsx +5 -5
  400. package/UI/Components/Detail/FieldLabel.tsx +8 -0
  401. package/UI/Components/Diagram/HorizontalStepChain.tsx +1 -1
  402. package/UI/Components/Feed/FeedOptionsButton.tsx +1 -1
  403. package/UI/Components/Forms/BasicForm.tsx +1 -1
  404. package/UI/Components/Header/Header.tsx +1 -1
  405. package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -1
  406. package/UI/Components/HeaderAlert/HeaderAlert.tsx +1 -1
  407. package/UI/Components/InfoCard/InfoCard.tsx +47 -1
  408. package/UI/Components/LogsViewer/components/FacetValueRow.tsx +1 -1
  409. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +1 -1
  410. package/UI/Components/Modal/ModalFooter.tsx +1 -1
  411. package/UI/Components/ModelDetail/CardModelDetail.tsx +2 -2
  412. package/UI/Components/ModelTable/BaseModelTable.tsx +99 -21
  413. package/UI/Components/ModelTable/Column.ts +5 -0
  414. package/UI/Components/Navbar/NavBar.tsx +9 -2
  415. package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -2
  416. package/UI/Components/Page/Page.tsx +1 -1
  417. package/UI/Components/Pagination/Pagination.tsx +3 -3
  418. package/UI/Components/ProgressButtons/ProgressButtonItem.tsx +1 -1
  419. package/UI/Components/SideMenu/SideMenu.tsx +4 -1
  420. package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +4 -2
  421. package/UI/Components/StatusPage/ResourceList.tsx +6 -6
  422. package/UI/Components/Table/TableHeader.tsx +47 -2
  423. package/UI/Components/Table/Types/Column.ts +7 -0
  424. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +1 -1
  425. package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +1 -1
  426. package/UI/Components/Tooltip/InfoTooltip.tsx +78 -0
  427. package/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.tsx +1 -1
  428. package/UI/Components/Workflow/ComponentsModal.tsx +2 -2
  429. package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
  430. package/UI/Styles/Theme.css +8 -1
  431. package/UI/Utils/Navigation.ts +89 -42
  432. package/UI/Utils/PermissionGate.ts +11 -2
  433. package/UI/Utils/Telemetry/TelemetryEntityNames.ts +7 -0
  434. package/UI/Utils/TelemetryService.ts +4 -3
  435. package/Utils/Incident/IncidentFromAlerts.ts +516 -0
  436. package/Utils/LabelRuleImportExport.ts +2 -0
  437. package/Utils/MetricUnitUtil.ts +103 -11
  438. package/Utils/Monitor/MetricValueFormatter.ts +66 -13
  439. package/Utils/Monitor/PlatformMetricUnitUtil.ts +215 -0
  440. package/Utils/Monitor/PlatformResourceIdentity.ts +514 -0
  441. package/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.ts +425 -0
  442. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +32 -0
  443. package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +73 -0
  444. package/Utils/Rum/SessionTraceState.ts +212 -0
  445. package/Utils/Telemetry/DatabaseServerEntityKeys.ts +275 -0
  446. package/Utils/Telemetry/EntityKey.ts +176 -0
  447. package/Utils/ValueFormatter.ts +16 -0
  448. package/build/dist/Models/DatabaseModels/Alert.js +54 -0
  449. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  450. package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -0
  451. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  452. package/build/dist/Models/DatabaseModels/DatabaseServer.js +1683 -0
  453. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -0
  454. package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js +559 -0
  455. package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js.map +1 -0
  456. package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js +648 -0
  457. package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js.map +1 -0
  458. package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js +522 -0
  459. package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js.map +1 -0
  460. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js +603 -0
  461. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js.map +1 -0
  462. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js +506 -0
  463. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js.map +1 -0
  464. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js +505 -0
  465. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js.map +1 -0
  466. package/build/dist/Models/DatabaseModels/Incident.js +54 -0
  467. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  468. package/build/dist/Models/DatabaseModels/IncidentAlert.js +553 -0
  469. package/build/dist/Models/DatabaseModels/IncidentAlert.js.map +1 -0
  470. package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -0
  471. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  472. package/build/dist/Models/DatabaseModels/Index.js +18 -0
  473. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  474. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  475. package/build/dist/Models/DatabaseModels/Project.js +62 -0
  476. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  477. package/build/dist/Models/DatabaseModels/RumApplication.js +53 -1
  478. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  479. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
  480. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  481. package/build/dist/Models/DatabaseModels/TelemetryException.js +2 -0
  482. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  483. package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js +162 -0
  484. package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js.map +1 -0
  485. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js +20 -0
  486. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js.map +1 -0
  487. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js +42 -0
  488. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js.map +1 -0
  489. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js +240 -0
  490. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js.map +1 -0
  491. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js +26 -0
  492. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js.map +1 -0
  493. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  494. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  495. package/build/dist/Server/Middleware/MultipartFormData.js +1 -1
  496. package/build/dist/Server/Middleware/TelemetryIngest.js +15 -8
  497. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  498. package/build/dist/Server/Services/AlertReminderRuleService.js +72 -23
  499. package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
  500. package/build/dist/Server/Services/DatabaseServerEndpointService.js +694 -0
  501. package/build/dist/Server/Services/DatabaseServerEndpointService.js.map +1 -0
  502. package/build/dist/Server/Services/DatabaseServerFeedService.js +110 -0
  503. package/build/dist/Server/Services/DatabaseServerFeedService.js.map +1 -0
  504. package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js +272 -0
  505. package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js.map +1 -0
  506. package/build/dist/Server/Services/DatabaseServerLabelRuleService.js +13 -0
  507. package/build/dist/Server/Services/DatabaseServerLabelRuleService.js.map +1 -0
  508. package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js +340 -0
  509. package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js.map +1 -0
  510. package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js +13 -0
  511. package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js.map +1 -0
  512. package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js +160 -0
  513. package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js.map +1 -0
  514. package/build/dist/Server/Services/DatabaseServerOwnerUserService.js +153 -0
  515. package/build/dist/Server/Services/DatabaseServerOwnerUserService.js.map +1 -0
  516. package/build/dist/Server/Services/DatabaseServerService.js +3272 -0
  517. package/build/dist/Server/Services/DatabaseServerService.js.map +1 -0
  518. package/build/dist/Server/Services/DatabaseService.js +8 -4
  519. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  520. package/build/dist/Server/Services/DockerResourceService.js +30 -3
  521. package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
  522. package/build/dist/Server/Services/IncidentAlertService.js +1370 -0
  523. package/build/dist/Server/Services/IncidentAlertService.js.map +1 -0
  524. package/build/dist/Server/Services/IncidentReminderRuleService.js +73 -23
  525. package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
  526. package/build/dist/Server/Services/IncidentService.js +164 -12
  527. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  528. package/build/dist/Server/Services/IncidentStateTimelineService.js +21 -0
  529. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  530. package/build/dist/Server/Services/Index.js +18 -0
  531. package/build/dist/Server/Services/Index.js.map +1 -1
  532. package/build/dist/Server/Services/InventoryItemService.js +88 -5
  533. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  534. package/build/dist/Server/Services/IoTDeviceService.js +111 -24
  535. package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
  536. package/build/dist/Server/Services/OpenTelemetryIngestService.js +24 -9
  537. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  538. package/build/dist/Server/Services/PodmanResourceService.js +30 -3
  539. package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
  540. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +75 -23
  541. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
  542. package/build/dist/Server/Services/ServiceService.js +1 -1
  543. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  544. package/build/dist/Server/Services/TelemetryUsageBillingService.js +23 -2
  545. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  546. package/build/dist/Server/Services/UserProjectSsoConsentService.js +79 -0
  547. package/build/dist/Server/Services/UserProjectSsoConsentService.js.map +1 -0
  548. package/build/dist/Server/Services/UserService.js +13 -1
  549. package/build/dist/Server/Services/UserService.js.map +1 -1
  550. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +18 -0
  551. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  552. package/build/dist/Server/Types/Database/QueryHelper.js +26 -1
  553. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  554. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +46 -0
  555. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
  556. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +6 -0
  557. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -1
  558. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +134 -13
  559. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
  560. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +22 -6
  561. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  562. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +1489 -524
  563. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  564. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
  565. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  566. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +196 -6
  567. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  568. package/build/dist/Server/Utils/Monitor/MonitorResource.js +36 -9
  569. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  570. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +1 -0
  571. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
  572. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +175 -17
  573. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
  574. package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js +29 -0
  575. package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js.map +1 -0
  576. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +211 -0
  577. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  578. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +82 -10
  579. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  580. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
  581. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  582. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +8 -0
  583. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
  584. package/build/dist/Server/Utils/StartServer.js +20 -4
  585. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  586. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
  587. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
  588. package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js +442 -0
  589. package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js.map +1 -0
  590. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -1
  591. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  592. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +15 -1
  593. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
  594. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +121 -5
  595. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
  596. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +12 -0
  597. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
  598. package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +438 -36
  599. package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -1
  600. package/build/dist/Server/Utils/Telemetry/Telemetry.js +12 -0
  601. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  602. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +17 -18
  603. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  604. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +16 -10
  605. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -1
  606. package/build/dist/Types/AI/AIResourceContext.js +7 -0
  607. package/build/dist/Types/AI/AIResourceContext.js.map +1 -1
  608. package/build/dist/Types/Dashboard/DashboardTemplates.js +2 -1
  609. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  610. package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js +71 -0
  611. package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js.map +1 -0
  612. package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js +1462 -0
  613. package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js.map +1 -0
  614. package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js +691 -0
  615. package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js.map +1 -0
  616. package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js +1407 -0
  617. package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js.map +1 -0
  618. package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js +60 -0
  619. package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js.map +1 -0
  620. package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js +804 -0
  621. package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js.map +1 -0
  622. package/build/dist/Types/DatabaseServer/DatabaseSystem.js +1860 -0
  623. package/build/dist/Types/DatabaseServer/DatabaseSystem.js.map +1 -0
  624. package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js +406 -0
  625. package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js.map +1 -0
  626. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  627. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  628. package/build/dist/Types/Incident/IncidentAlertLink.js +34 -0
  629. package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -0
  630. package/build/dist/Types/Monitor/CephAlertTemplates.js +18 -0
  631. package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
  632. package/build/dist/Types/Monitor/DatabaseAlertTemplates.js +1518 -0
  633. package/build/dist/Types/Monitor/DatabaseAlertTemplates.js.map +1 -0
  634. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +57 -24
  635. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  636. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +104 -18
  637. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
  638. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +80 -3
  639. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  640. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +10 -3
  641. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  642. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +29 -0
  643. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  644. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +21 -6
  645. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -1
  646. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +25 -0
  647. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
  648. package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js +136 -0
  649. package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js.map +1 -0
  650. package/build/dist/Types/Permission.js +276 -0
  651. package/build/dist/Types/Permission.js.map +1 -1
  652. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +10 -0
  653. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  654. package/build/dist/Types/Rules/RuleRun.js +4 -0
  655. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  656. package/build/dist/Types/Rum/WebVitals.js +25 -0
  657. package/build/dist/Types/Rum/WebVitals.js.map +1 -1
  658. package/build/dist/Types/Telemetry/EntityType.js +23 -0
  659. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  660. package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +14 -0
  661. package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -1
  662. package/build/dist/Types/Telemetry/ServiceType.js +8 -0
  663. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  664. package/build/dist/UI/Components/Banner/Banner.js +1 -1
  665. package/build/dist/UI/Components/Banner/Banner.js.map +1 -1
  666. package/build/dist/UI/Components/Card/Card.js +1 -1
  667. package/build/dist/UI/Components/Card/Card.js.map +1 -1
  668. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
  669. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  670. package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
  671. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  672. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +1 -1
  673. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  674. package/build/dist/UI/Components/Date/StartAndEndDate.js +5 -5
  675. package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
  676. package/build/dist/UI/Components/Detail/FieldLabel.js +2 -0
  677. package/build/dist/UI/Components/Detail/FieldLabel.js.map +1 -1
  678. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +1 -1
  679. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -1
  680. package/build/dist/UI/Components/Feed/FeedOptionsButton.js +1 -1
  681. package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -1
  682. package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
  683. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  684. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
  685. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  686. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +1 -1
  687. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
  688. package/build/dist/UI/Components/InfoCard/InfoCard.js +22 -1
  689. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  690. package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +1 -1
  691. package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
  692. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
  693. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  694. package/build/dist/UI/Components/Modal/ModalFooter.js +1 -1
  695. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  696. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +2 -2
  697. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  698. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +70 -18
  699. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  700. package/build/dist/UI/Components/Navbar/NavBar.js +9 -2
  701. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  702. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
  703. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  704. package/build/dist/UI/Components/Page/Page.js +1 -1
  705. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  706. package/build/dist/UI/Components/Pagination/Pagination.js +3 -3
  707. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  708. package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js +1 -1
  709. package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js.map +1 -1
  710. package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -1
  711. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  712. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +3 -1
  713. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -1
  714. package/build/dist/UI/Components/StatusPage/ResourceList.js +6 -6
  715. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  716. package/build/dist/UI/Components/Table/TableHeader.js +18 -2
  717. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  718. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
  719. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  720. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +1 -1
  721. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
  722. package/build/dist/UI/Components/Tooltip/InfoTooltip.js +28 -0
  723. package/build/dist/UI/Components/Tooltip/InfoTooltip.js.map +1 -0
  724. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js +1 -1
  725. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js.map +1 -1
  726. package/build/dist/UI/Components/Workflow/ComponentsModal.js +2 -2
  727. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  728. package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
  729. package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
  730. package/build/dist/UI/Utils/Navigation.js +66 -33
  731. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  732. package/build/dist/UI/Utils/PermissionGate.js +4 -2
  733. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  734. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +7 -0
  735. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
  736. package/build/dist/UI/Utils/TelemetryService.js +3 -2
  737. package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
  738. package/build/dist/Utils/Incident/IncidentFromAlerts.js +306 -0
  739. package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -0
  740. package/build/dist/Utils/LabelRuleImportExport.js +2 -0
  741. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  742. package/build/dist/Utils/MetricUnitUtil.js +77 -13
  743. package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
  744. package/build/dist/Utils/Monitor/MetricValueFormatter.js +58 -13
  745. package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -1
  746. package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js +161 -0
  747. package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js.map +1 -0
  748. package/build/dist/Utils/Monitor/PlatformResourceIdentity.js +323 -0
  749. package/build/dist/Utils/Monitor/PlatformResourceIdentity.js.map +1 -0
  750. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js +270 -0
  751. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js.map +1 -0
  752. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +23 -0
  753. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
  754. package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +61 -0
  755. package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -1
  756. package/build/dist/Utils/Rum/SessionTraceState.js +154 -0
  757. package/build/dist/Utils/Rum/SessionTraceState.js.map +1 -0
  758. package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js +178 -0
  759. package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js.map +1 -0
  760. package/build/dist/Utils/Telemetry/EntityKey.js +133 -0
  761. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  762. package/build/dist/Utils/ValueFormatter.js +15 -0
  763. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  764. package/package.json +1 -1
  765. package/tsconfig.tests.json +7 -5
@@ -0,0 +1,1370 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import QueryHelper from "../Types/Database/QueryHelper";
11
+ import ModelPermission from "../Types/Database/Permissions/Index";
12
+ import DatabaseService from "./DatabaseService";
13
+ import AlertFeedService from "./AlertFeedService";
14
+ import AlertOwnerTeamService from "./AlertOwnerTeamService";
15
+ import AlertOwnerUserService from "./AlertOwnerUserService";
16
+ import AlertService from "./AlertService";
17
+ import AlertStateService from "./AlertStateService";
18
+ import IncidentFeedService from "./IncidentFeedService";
19
+ import IncidentService from "./IncidentService";
20
+ import IncidentStateService from "./IncidentStateService";
21
+ import ProjectService from "./ProjectService";
22
+ import { IsBillingEnabled } from "../EnvironmentConfig";
23
+ import { applyAlertRelatedRecordPrivacyFilter } from "../Utils/Alert/AlertPrivacyFilter";
24
+ import { applyIncidentRelatedRecordPrivacyFilter } from "../Utils/Incident/IncidentPrivacyFilter";
25
+ import PostgresErrorTranslator from "../Utils/Database/PostgresErrorTranslator";
26
+ import ProjectScopedReferenceValidator from "../Utils/Database/ProjectScopedReferenceValidator";
27
+ import RelationIdUtil from "../Utils/Database/RelationIdUtil";
28
+ import logger from "../Utils/Logger";
29
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
30
+ import Model from "../../Models/DatabaseModels/IncidentAlert";
31
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
32
+ import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
33
+ import { Gray500, Yellow500 } from "../../Types/BrandColors";
34
+ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
35
+ import BadDataException from "../../Types/Exception/BadDataException";
36
+ import ForbiddenException from "../../Types/Exception/ForbiddenException";
37
+ import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
38
+ import NotFoundException from "../../Types/Exception/NotFoundException";
39
+ import { INCIDENT_ALERT_ALREADY_LINKED_MESSAGE, INCIDENT_ALERT_IDS_TO_LINK_KEY, MAX_ALERTS_PER_INCIDENT_LINK_ACTION, } from "../../Types/Incident/IncidentAlertLink";
40
+ import ObjectID from "../../Types/ObjectID";
41
+ /*
42
+ * The decision half of the linked-alert state sync, shared by the cascade
43
+ * (an incident changes state) and the link-time sync (an alert is linked to
44
+ * an incident that is already acknowledged or resolved).
45
+ *
46
+ * States are compared by `order`, never by the isAcknowledgedState /
47
+ * isResolvedState flags: projects add custom states (say "Monitoring") between
48
+ * Acknowledged and Resolved, and an incident sitting in one of those has
49
+ * still been acknowledged. An incident project without an Acknowledged (or
50
+ * Resolved) state simply never triggers that half.
51
+ */
52
+ export function getLinkedAlertStateTargets(data) {
53
+ const reachedAcknowledged = data.acknowledgedIncidentStateOrder !== undefined &&
54
+ data.incidentStateOrder >= data.acknowledgedIncidentStateOrder;
55
+ const reachedResolved = data.resolvedIncidentStateOrder !== undefined &&
56
+ data.incidentStateOrder >= data.resolvedIncidentStateOrder;
57
+ return {
58
+ acknowledge: data.acknowledgeSwitch && reachedAcknowledged,
59
+ resolve: data.resolveSwitch && reachedResolved,
60
+ incidentReachedResolved: reachedResolved,
61
+ };
62
+ }
63
+ /*
64
+ * The alert state one linked alert should move to, or null to leave it alone.
65
+ *
66
+ * Resolve wins when it applies and the alert is not held back by another
67
+ * linked incident that is still open; acknowledge is the fallback, so an
68
+ * alert that cannot be resolved yet is at least acknowledged (which is what
69
+ * stops its paging). An alert is never moved backwards and never "moved" to
70
+ * where it already is: anything at or past the target is left untouched.
71
+ */
72
+ export function chooseLinkedAlertTargetState(data) {
73
+ var _a, _b;
74
+ const resolvedOrder = (_a = data.resolvedAlertState) === null || _a === void 0 ? void 0 : _a.order;
75
+ if (data.resolvedAlertState &&
76
+ resolvedOrder !== undefined &&
77
+ !data.isBlockedFromResolve &&
78
+ data.alertStateOrder < resolvedOrder) {
79
+ return data.resolvedAlertState;
80
+ }
81
+ const acknowledgedOrder = (_b = data.acknowledgedAlertState) === null || _b === void 0 ? void 0 : _b.order;
82
+ if (data.acknowledgedAlertState &&
83
+ acknowledgedOrder !== undefined &&
84
+ data.alertStateOrder < acknowledgedOrder) {
85
+ return data.acknowledgedAlertState;
86
+ }
87
+ return null;
88
+ }
89
+ /*
90
+ * miscDataProps key on an IncidentAlert create: the link is one of the links
91
+ * written while an incident is being declared from alerts. The incident then
92
+ * gets one "Declared from N alerts" entry (see
93
+ * createDeclaredFromAlertsFeedItem) instead of an "Alert Linked" entry - and
94
+ * a Slack / Microsoft Teams post - per alert. Honoured for root callers only:
95
+ * miscDataProps is part of the public create API, and an API client must not
96
+ * be able to link an alert without the incident's audit entry.
97
+ */
98
+ export const INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY = "declaredWithIncident";
99
+ /*
100
+ * "**[Alert #3](link)**: <title>", or "**[Alert #3](link)** (private alert)"
101
+ * for a private alert: its number and link are kept so the entry still says
102
+ * what happened, but its title is never written where people who cannot see
103
+ * the alert read it (the incident's feed and Slack / Microsoft Teams posts).
104
+ */
105
+ function describeLinkedRecord(data) {
106
+ const subject = `**[${data.label}](${data.link})**`;
107
+ if (data.isPrivate) {
108
+ return {
109
+ subject: `${subject} (private ${data.privateNoun})`,
110
+ titleSuffix: "",
111
+ };
112
+ }
113
+ return { subject: subject, titleSuffix: `: ${data.title || "No title"}` };
114
+ }
115
+ /*
116
+ * The one incident feed entry for an incident declared from alerts, listing
117
+ * the alerts in the order given. Private alerts are listed without their
118
+ * titles.
119
+ */
120
+ export function getDeclaredFromAlertsMarkdown(alerts) {
121
+ const lines = alerts.map((alert) => {
122
+ const described = describeLinkedRecord({
123
+ label: alert.label,
124
+ link: alert.link,
125
+ title: alert.title,
126
+ isPrivate: alert.isPrivate,
127
+ privateNoun: "alert",
128
+ });
129
+ return `- ${described.subject}${described.titleSuffix}`;
130
+ });
131
+ const noun = alerts.length === 1 ? "alert" : "alerts";
132
+ return `🔗 Declared from ${alerts.length} ${noun}:\n\n${lines.join("\n")}`;
133
+ }
134
+ function normalizeId(id) {
135
+ return id.toString().trim().toLowerCase();
136
+ }
137
+ // Distinct ids, in order, with the missing ones left out.
138
+ function uniqueIds(ids) {
139
+ const seen = new Set();
140
+ const result = [];
141
+ for (const id of ids) {
142
+ if (!id) {
143
+ continue;
144
+ }
145
+ const key = normalizeId(id);
146
+ if (!key || seen.has(key)) {
147
+ continue;
148
+ }
149
+ seen.add(key);
150
+ result.push(new ObjectID(key));
151
+ }
152
+ return result;
153
+ }
154
+ function formatNumber(numberWithPrefix, number) {
155
+ if (numberWithPrefix) {
156
+ return numberWithPrefix;
157
+ }
158
+ if (number !== undefined && number !== null) {
159
+ return `#${number}`;
160
+ }
161
+ return "";
162
+ }
163
+ function withNumber(label, number) {
164
+ return number ? `${label} ${number}` : label;
165
+ }
166
+ const NOT_VISIBLE_ALERTS_MESSAGE = "One or more of the selected alerts do not exist in this project, or you do not have access to them.";
167
+ export class Service extends DatabaseService {
168
+ constructor() {
169
+ super(Model);
170
+ if (IsBillingEnabled) {
171
+ this.hardDeleteItemsOlderThanInDays("createdAt", 3 * 365); // 3 years
172
+ }
173
+ }
174
+ /*
175
+ * A link row reveals both of its ends, so it is only visible to a user who
176
+ * can see the private incident AND the private alert. The two filters write
177
+ * different keys (incidentId / alertId) and compose. Relation joins
178
+ * (`select: { alert: { title } }`) do not run AlertService.onBeforeFind,
179
+ * so these are the only thing keeping a private alert's title out of an
180
+ * incident's "Linked Alerts" list, and the other way round.
181
+ */
182
+ applyPrivacyFilters(query, props) {
183
+ return applyAlertRelatedRecordPrivacyFilter(applyIncidentRelatedRecordPrivacyFilter(query, props), props);
184
+ }
185
+ async onBeforeFind(findBy) {
186
+ findBy.query = this.applyPrivacyFilters(findBy.query, findBy.props);
187
+ return { findBy, carryForward: null };
188
+ }
189
+ /*
190
+ * A pair that is already linked answers with the same message however the
191
+ * duplicate is caught. @UniqueColumnsTogether catches it before the insert
192
+ * with INCIDENT_ALERT_ALREADY_LINKED_MESSAGE; when two requests race past
193
+ * that check, the unique index rejects the second insert, and the generic
194
+ * translation ("A Incident Alert with the same Incident Id, Alert Id,
195
+ * Project Id already exists...") would reach the dashboard, which counts a
196
+ * link as done only by this message. The exception stays tagged as a unique
197
+ * violation, so linkAlertsToIncident still counts it as already linked.
198
+ *
199
+ * IncidentAlert has no other unique index. A unique violation reported
200
+ * against another table (nothing on the create path writes one today) keeps
201
+ * the generic translation. Synchronous and `never`-returning, like the
202
+ * method it overrides.
203
+ */
204
+ getException(error) {
205
+ if (PostgresErrorTranslator.isUniqueViolation(error) &&
206
+ this.isOwnTableOrUnknown(error)) {
207
+ throw PostgresErrorTranslator.createUniqueViolationException(INCIDENT_ALERT_ALREADY_LINKED_MESSAGE);
208
+ }
209
+ return super.getException(error);
210
+ }
211
+ /*
212
+ * True when a Postgres error names this table, or names none (an exception
213
+ * that was already translated carries no driver details).
214
+ */
215
+ isOwnTableOrUnknown(error) {
216
+ const direct = error;
217
+ const driverError = error.driverError;
218
+ const table = typeof direct.table === "string" ? direct.table : driverError === null || driverError === void 0 ? void 0 : driverError.table;
219
+ if (typeof table !== "string" || table.length === 0) {
220
+ return true;
221
+ }
222
+ return table === this.getModel().tableName;
223
+ }
224
+ async countBy(countBy) {
225
+ countBy.query = this.applyPrivacyFilters(countBy.query, countBy.props);
226
+ return super.countBy(countBy);
227
+ }
228
+ async onBeforeUpdate(updateBy) {
229
+ updateBy.query = this.applyPrivacyFilters(updateBy.query, updateBy.props);
230
+ return { updateBy, carryForward: null };
231
+ }
232
+ /*
233
+ * Both ends must exist in the link's project, and a user may only link what
234
+ * they can see. The foreign keys only require the rows to exist somewhere,
235
+ * and @CanAccessIfCanReadOn is not applied on create, so without this a
236
+ * member could link another project's alert, or a private incident they
237
+ * cannot open. The duplicate check is left to @UniqueColumnsTogether and the
238
+ * unique index, which are race free.
239
+ *
240
+ * This hook runs before DatabaseService checks the caller's create
241
+ * permission, so every refusal is worded so it reveals nothing about
242
+ * records the caller cannot see.
243
+ */
244
+ async onBeforeCreate(createBy) {
245
+ const data = createBy.data;
246
+ // A reference arrives as `incidentId` or as `incident: { _id }`.
247
+ const incidentId = RelationIdUtil.readConsistent(data, ["incidentId", "incident"], "incident");
248
+ const alertId = RelationIdUtil.readConsistent(data, ["alertId", "alert"], "alert");
249
+ if (!incidentId) {
250
+ throw new BadDataException("Please select the incident to link the alert to.");
251
+ }
252
+ if (!alertId) {
253
+ throw new BadDataException("Please select the alert to link.");
254
+ }
255
+ const projectId = createBy.props.tenantId ||
256
+ RelationIdUtil.readConsistent(data, ["projectId", "project"], "project");
257
+ if (!projectId) {
258
+ throw new BadDataException("projectId is required to link an alert to an incident.");
259
+ }
260
+ createBy.data.projectId = projectId;
261
+ createBy.data.incidentId = incidentId;
262
+ createBy.data.alertId = alertId;
263
+ if (!createBy.props.isRoot) {
264
+ /*
265
+ * Read both ends as the caller, so privacy, label and owner scoping
266
+ * apply exactly as they do on the incident and alert pages. A caller
267
+ * without read access at all gets the same answer as one asking for
268
+ * a record that does not exist.
269
+ */
270
+ const incident = await this.findVisible(() => {
271
+ return IncidentService.findOneById({
272
+ id: incidentId,
273
+ select: { _id: true, projectId: true },
274
+ props: createBy.props,
275
+ });
276
+ });
277
+ if (!incident ||
278
+ normalizeId(incident.projectId || "") !== normalizeId(projectId)) {
279
+ throw new BadDataException("The incident to link does not exist in this project, or you do not have access to it.");
280
+ }
281
+ const alert = await this.findVisible(() => {
282
+ return AlertService.findOneById({
283
+ id: alertId,
284
+ select: { _id: true, projectId: true },
285
+ props: createBy.props,
286
+ });
287
+ });
288
+ if (!alert ||
289
+ normalizeId(alert.projectId || "") !== normalizeId(projectId)) {
290
+ throw new BadDataException("The alert to link does not exist in this project, or you do not have access to it.");
291
+ }
292
+ /*
293
+ * "Linked by" is whoever made the request. sanitizeCreateOrUpdate
294
+ * stamps it for a user; an API key has no user, and must not be able
295
+ * to name somebody else as the one who linked the alert.
296
+ */
297
+ if (createBy.props.userId) {
298
+ createBy.data.createdByUserId = createBy.props.userId;
299
+ }
300
+ else {
301
+ delete createBy.data.createdByUserId;
302
+ }
303
+ delete createBy.data.createdByUser;
304
+ }
305
+ await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
306
+ projectId: projectId,
307
+ subject: "incident alert link",
308
+ references: [
309
+ {
310
+ modelName: "Incident",
311
+ id: incidentId,
312
+ service: IncidentService,
313
+ },
314
+ {
315
+ modelName: "Alert",
316
+ id: alertId,
317
+ service: AlertService,
318
+ },
319
+ ],
320
+ });
321
+ return { createBy, carryForward: null };
322
+ }
323
+ /*
324
+ * Runs a read made with the caller's props. A refusal from the permission
325
+ * layer (no read access to the table, a label the caller cannot see) is
326
+ * reported exactly like a record that does not exist, so the answer never
327
+ * reveals which it was. Anything else - a lapsed session, an unpaid
328
+ * project, the database being unavailable - is not about the record and is
329
+ * passed on as it is.
330
+ */
331
+ async findVisible(read) {
332
+ try {
333
+ return await read();
334
+ }
335
+ catch (error) {
336
+ if (error instanceof NotAuthorizedException ||
337
+ error instanceof ForbiddenException ||
338
+ error instanceof NotFoundException ||
339
+ error instanceof BadDataException) {
340
+ logger.debug(`IncidentAlertService: a record to link is not readable by the caller: ${error.message}`);
341
+ return null;
342
+ }
343
+ throw error;
344
+ }
345
+ }
346
+ async onCreateSuccess(onCreate, createdItem) {
347
+ var _a, _b;
348
+ const projectId = createdItem.projectId;
349
+ const incidentId = createdItem.incidentId;
350
+ const alertId = createdItem.alertId;
351
+ if (!projectId || !incidentId || !alertId) {
352
+ return createdItem;
353
+ }
354
+ const actorUserId = createdItem.createdByUserId || onCreate.createBy.props.userId;
355
+ /*
356
+ * A link written while its incident is being declared from alerts leaves
357
+ * the incident's side to that incident's single "Declared from N alerts"
358
+ * entry. Root only - see INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY.
359
+ */
360
+ const isDeclaredWithIncident = onCreate.createBy.props.isRoot === true &&
361
+ ((_a = onCreate.createBy.miscDataProps) === null || _a === void 0 ? void 0 : _a[INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY]) === true;
362
+ try {
363
+ await this.createLinkFeedItems({
364
+ link: {
365
+ id: ((_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString()) || "",
366
+ projectId: projectId,
367
+ incidentId: incidentId,
368
+ alertId: alertId,
369
+ },
370
+ isLinked: true,
371
+ actorUserId: actorUserId,
372
+ writeIncidentEntry: !isDeclaredWithIncident,
373
+ });
374
+ }
375
+ catch (error) {
376
+ logger.error(`IncidentAlertService.onCreateSuccess could not write the link feed items: ${error}`, {
377
+ projectId: projectId.toString(),
378
+ incidentId: incidentId.toString(),
379
+ alertId: alertId.toString(),
380
+ });
381
+ }
382
+ /*
383
+ * Linking an alert to an incident that is already acknowledged or
384
+ * resolved brings the alert along, when the project asks for it.
385
+ * Fire-and-forget: it never fails, or slows down, the link.
386
+ */
387
+ this.syncAlertWithLinkedIncidentState({
388
+ projectId: projectId,
389
+ incidentId: incidentId,
390
+ alertId: alertId,
391
+ }).catch((error) => {
392
+ logger.error(`IncidentAlertService could not sync a newly linked alert with its incident: ${error}`, {
393
+ projectId: projectId.toString(),
394
+ incidentId: incidentId.toString(),
395
+ alertId: alertId.toString(),
396
+ });
397
+ });
398
+ return createdItem;
399
+ }
400
+ /*
401
+ * Carries the rows about to be deleted to onDeleteSuccess, which reports
402
+ * only the ones that were actually deleted: the permission check that runs
403
+ * after this hook can still narrow the delete. The read is not capped at
404
+ * the delete's own limit because that limit applies to the narrowed query,
405
+ * whose rows need not be among the first rows of this one.
406
+ */
407
+ async onBeforeDelete(deleteBy) {
408
+ deleteBy.query = this.applyPrivacyFilters(deleteBy.query, deleteBy.props);
409
+ const carriedQuery = Object.assign({}, deleteBy.query);
410
+ if (deleteBy.props.tenantId && !carriedQuery.projectId) {
411
+ carriedQuery.projectId = deleteBy.props.tenantId;
412
+ }
413
+ const linksToDelete = await this.findBy({
414
+ query: carriedQuery,
415
+ select: {
416
+ _id: true,
417
+ incidentId: true,
418
+ alertId: true,
419
+ projectId: true,
420
+ },
421
+ limit: LIMIT_PER_PROJECT,
422
+ skip: 0,
423
+ props: {
424
+ isRoot: true,
425
+ },
426
+ });
427
+ const carried = [];
428
+ for (const link of linksToDelete) {
429
+ if (!link._id || !link.incidentId || !link.alertId || !link.projectId) {
430
+ continue;
431
+ }
432
+ carried.push({
433
+ id: link._id.toString(),
434
+ incidentId: link.incidentId,
435
+ alertId: link.alertId,
436
+ projectId: link.projectId,
437
+ });
438
+ }
439
+ return { deleteBy, carryForward: carried };
440
+ }
441
+ async onDeleteSuccess(onDelete, itemIdsBeforeDelete) {
442
+ var _a;
443
+ const carried = Array.isArray(onDelete.carryForward)
444
+ ? onDelete.carryForward
445
+ : [];
446
+ const deletedIds = new Set((itemIdsBeforeDelete || []).map((id) => {
447
+ return normalizeId(id);
448
+ }));
449
+ const actorUserId = ((_a = onDelete.deleteBy.deletedByUser) === null || _a === void 0 ? void 0 : _a.id) || onDelete.deleteBy.props.userId;
450
+ for (const link of carried) {
451
+ if (!deletedIds.has(normalizeId(link.id))) {
452
+ continue;
453
+ }
454
+ try {
455
+ await this.createLinkFeedItems({
456
+ link: link,
457
+ isLinked: false,
458
+ actorUserId: actorUserId,
459
+ writeIncidentEntry: true,
460
+ });
461
+ }
462
+ catch (error) {
463
+ logger.error(`IncidentAlertService.onDeleteSuccess could not write the unlink feed items: ${error}`, {
464
+ projectId: link.projectId.toString(),
465
+ incidentId: link.incidentId.toString(),
466
+ alertId: link.alertId.toString(),
467
+ });
468
+ }
469
+ }
470
+ return onDelete;
471
+ }
472
+ /*
473
+ * One entry on each side. Only the incident's entry is posted to Slack /
474
+ * Microsoft Teams: the incident's channels are where responders follow the
475
+ * incident, and posting the alert's entry as well would announce every link
476
+ * twice.
477
+ *
478
+ * Each entry is read by its own side's audience: the incident's feed and
479
+ * channels by whoever can see the incident, the alert's feed by whoever
480
+ * can see the alert. So a private end's title never goes into the other
481
+ * side's entry - not even when both ends are private, because two private
482
+ * records can have different owners. Its number and link are kept (opening
483
+ * the link is subject to the record's own privacy), which is what
484
+ * applyPrivacyFilters promises for the link rows themselves.
485
+ */
486
+ async createLinkFeedItems(data) {
487
+ const { link, isLinked, actorUserId } = data;
488
+ const incident = await IncidentService.findOneById({
489
+ id: link.incidentId,
490
+ select: {
491
+ incidentNumber: true,
492
+ incidentNumberWithPrefix: true,
493
+ title: true,
494
+ isPrivate: true,
495
+ },
496
+ props: {
497
+ isRoot: true,
498
+ },
499
+ });
500
+ const alert = await AlertService.findOneById({
501
+ id: link.alertId,
502
+ select: {
503
+ alertNumber: true,
504
+ alertNumberWithPrefix: true,
505
+ title: true,
506
+ isPrivate: true,
507
+ },
508
+ props: {
509
+ isRoot: true,
510
+ },
511
+ });
512
+ const incidentLabel = withNumber("Incident", formatNumber(incident === null || incident === void 0 ? void 0 : incident.incidentNumberWithPrefix, incident === null || incident === void 0 ? void 0 : incident.incidentNumber));
513
+ const alertLabel = withNumber("Alert", formatNumber(alert === null || alert === void 0 ? void 0 : alert.alertNumberWithPrefix, alert === null || alert === void 0 ? void 0 : alert.alertNumber));
514
+ const incidentLink = (await IncidentService.getIncidentLinkInDashboard(link.projectId, link.incidentId)).toString();
515
+ const alertLink = (await AlertService.getAlertLinkInDashboard(link.projectId, link.alertId)).toString();
516
+ const alertMention = describeLinkedRecord({
517
+ label: alertLabel,
518
+ link: alertLink,
519
+ title: alert === null || alert === void 0 ? void 0 : alert.title,
520
+ isPrivate: (alert === null || alert === void 0 ? void 0 : alert.isPrivate) === true,
521
+ privateNoun: "alert",
522
+ });
523
+ const incidentMention = describeLinkedRecord({
524
+ label: incidentLabel,
525
+ link: incidentLink,
526
+ title: incident === null || incident === void 0 ? void 0 : incident.title,
527
+ isPrivate: (incident === null || incident === void 0 ? void 0 : incident.isPrivate) === true,
528
+ privateNoun: "incident",
529
+ });
530
+ const incidentSubject = `**[${incidentLabel}](${incidentLink})**`;
531
+ if (data.writeIncidentEntry) {
532
+ await IncidentFeedService.createIncidentFeedItem({
533
+ incidentId: link.incidentId,
534
+ projectId: link.projectId,
535
+ incidentFeedEventType: isLinked
536
+ ? IncidentFeedEventType.AlertLinked
537
+ : IncidentFeedEventType.AlertUnlinked,
538
+ displayColor: isLinked ? Yellow500 : Gray500,
539
+ feedInfoInMarkdown: isLinked
540
+ ? `🔗 Linked ${alertMention.subject} to ${incidentSubject}${alertMention.titleSuffix}`
541
+ : `Unlinked ${alertMention.subject} from ${incidentSubject}${alertMention.titleSuffix}`,
542
+ userId: actorUserId,
543
+ workspaceNotification: {
544
+ sendWorkspaceNotification: true,
545
+ notifyUserId: actorUserId,
546
+ },
547
+ });
548
+ }
549
+ await AlertFeedService.createAlertFeedItem({
550
+ alertId: link.alertId,
551
+ projectId: link.projectId,
552
+ alertFeedEventType: isLinked
553
+ ? AlertFeedEventType.LinkedToIncident
554
+ : AlertFeedEventType.UnlinkedFromIncident,
555
+ displayColor: isLinked ? Yellow500 : Gray500,
556
+ feedInfoInMarkdown: isLinked
557
+ ? `🔗 Linked to ${incidentMention.subject}${incidentMention.titleSuffix}`
558
+ : `Unlinked from ${incidentMention.subject}${incidentMention.titleSuffix}`,
559
+ userId: actorUserId,
560
+ });
561
+ }
562
+ /*
563
+ * The single incident feed entry for an incident declared from alerts,
564
+ * posted to its Slack / Microsoft Teams channels. The links themselves are
565
+ * written without incident-side entries (INCIDENT_ALERT_DECLARED_WITH_
566
+ * INCIDENT_KEY), so the incident's channels get one message instead of one
567
+ * per alert. IncidentService calls this from its create chain once the
568
+ * "Incident Created" entry is out, which is also when the incident's own
569
+ * channels exist. Nothing is written when none of the alerts can be found.
570
+ */
571
+ async createDeclaredFromAlertsFeedItem(data) {
572
+ const markdown = await this.buildDeclaredFromAlertsMarkdown({
573
+ projectId: data.projectId,
574
+ alertIds: data.alertIds,
575
+ });
576
+ if (!markdown) {
577
+ return;
578
+ }
579
+ await IncidentFeedService.createIncidentFeedItem({
580
+ incidentId: data.incidentId,
581
+ projectId: data.projectId,
582
+ incidentFeedEventType: IncidentFeedEventType.AlertLinked,
583
+ displayColor: Yellow500,
584
+ feedInfoInMarkdown: markdown,
585
+ userId: data.actorUserId,
586
+ workspaceNotification: {
587
+ sendWorkspaceNotification: true,
588
+ notifyUserId: data.actorUserId,
589
+ },
590
+ });
591
+ }
592
+ /*
593
+ * The markdown for createDeclaredFromAlertsFeedItem: the project's alerts
594
+ * among `alertIds`, in that order, each with its number and dashboard
595
+ * link, and its title unless it is private. Read as root; null when none of
596
+ * the alerts exists (any more).
597
+ */
598
+ async buildDeclaredFromAlertsMarkdown(data) {
599
+ if (data.alertIds.length === 0) {
600
+ return null;
601
+ }
602
+ const alerts = await AlertService.findBy({
603
+ query: {
604
+ _id: QueryHelper.any(data.alertIds),
605
+ projectId: data.projectId,
606
+ },
607
+ select: {
608
+ _id: true,
609
+ alertNumber: true,
610
+ alertNumberWithPrefix: true,
611
+ title: true,
612
+ isPrivate: true,
613
+ },
614
+ limit: LIMIT_PER_PROJECT,
615
+ skip: 0,
616
+ props: {
617
+ isRoot: true,
618
+ },
619
+ });
620
+ const alertById = new Map();
621
+ for (const alert of alerts) {
622
+ if (alert._id) {
623
+ alertById.set(normalizeId(alert._id), alert);
624
+ }
625
+ }
626
+ const mentions = [];
627
+ const seen = new Set();
628
+ for (const alertId of data.alertIds) {
629
+ const key = normalizeId(alertId);
630
+ const alert = alertById.get(key);
631
+ if (!alert || seen.has(key)) {
632
+ continue;
633
+ }
634
+ seen.add(key);
635
+ mentions.push({
636
+ label: withNumber("Alert", formatNumber(alert.alertNumberWithPrefix, alert.alertNumber)),
637
+ link: (await AlertService.getAlertLinkInDashboard(data.projectId, new ObjectID(key))).toString(),
638
+ title: alert.title,
639
+ isPrivate: alert.isPrivate === true,
640
+ });
641
+ }
642
+ if (mentions.length === 0) {
643
+ return null;
644
+ }
645
+ return getDeclaredFromAlertsMarkdown(mentions);
646
+ }
647
+ /*
648
+ * Declaring a PRIVATE incident from alerts: the people who work those
649
+ * alerts become its owners too. A private incident is visible only to its
650
+ * owners (and project admins), and a private alert only to its owners, so
651
+ * without this the owners of the private alert an incident was declared
652
+ * from - the only non-admins who could see that alert - could not see the
653
+ * incident. The declaring user is already made an owner by
654
+ * DatabaseService.autoOwnerOnCreate. Owners are added as root, without
655
+ * notifying them (they were notified about their alerts), and owners the
656
+ * incident already has are skipped.
657
+ */
658
+ async copyAlertOwnersToIncident(data) {
659
+ if (data.alertIds.length === 0) {
660
+ return { userIds: [], teamIds: [] };
661
+ }
662
+ const ownerUsers = await AlertOwnerUserService.findBy({
663
+ query: {
664
+ alertId: QueryHelper.any(data.alertIds),
665
+ projectId: data.projectId,
666
+ },
667
+ select: {
668
+ userId: true,
669
+ },
670
+ limit: LIMIT_PER_PROJECT,
671
+ skip: 0,
672
+ props: {
673
+ isRoot: true,
674
+ },
675
+ });
676
+ const ownerTeams = await AlertOwnerTeamService.findBy({
677
+ query: {
678
+ alertId: QueryHelper.any(data.alertIds),
679
+ projectId: data.projectId,
680
+ },
681
+ select: {
682
+ teamId: true,
683
+ },
684
+ limit: LIMIT_PER_PROJECT,
685
+ skip: 0,
686
+ props: {
687
+ isRoot: true,
688
+ },
689
+ });
690
+ const userIds = uniqueIds(ownerUsers.map((owner) => {
691
+ return owner.userId;
692
+ }));
693
+ const teamIds = uniqueIds(ownerTeams.map((owner) => {
694
+ return owner.teamId;
695
+ }));
696
+ if (userIds.length === 0 && teamIds.length === 0) {
697
+ return { userIds, teamIds };
698
+ }
699
+ await IncidentService.addOwners(data.projectId, data.incidentId, userIds, teamIds, false, {
700
+ isRoot: true,
701
+ });
702
+ return { userIds, teamIds };
703
+ }
704
+ /*
705
+ * Declaring an incident from alerts (miscDataProps.alertIdsToLink on an
706
+ * Incident create). Runs in IncidentService.onBeforeCreate, BEFORE the
707
+ * incident number is taken and before anything is written, so a bad id
708
+ * neither burns an incident number nor leaves an incident behind with
709
+ * half of its alerts. Returns the ids deduplicated and normalised, ready
710
+ * for linkAlertsToIncident once the incident exists.
711
+ */
712
+ async validateAlertIdsForNewIncident(data) {
713
+ if (!Array.isArray(data.alertIds)) {
714
+ throw new BadDataException(`${INCIDENT_ALERT_IDS_TO_LINK_KEY} must be an array of alert ids.`);
715
+ }
716
+ const alertIds = [];
717
+ const seen = new Set();
718
+ for (const value of data.alertIds) {
719
+ let id = null;
720
+ if (typeof value === "string") {
721
+ id = value.trim();
722
+ }
723
+ else if (value instanceof ObjectID) {
724
+ id = value.toString().trim();
725
+ }
726
+ if (!id || !ObjectID.isValidUUID(id)) {
727
+ throw new BadDataException(`${INCIDENT_ALERT_IDS_TO_LINK_KEY} must only contain alert ids.`);
728
+ }
729
+ const key = normalizeId(id);
730
+ if (seen.has(key)) {
731
+ continue;
732
+ }
733
+ seen.add(key);
734
+ alertIds.push(new ObjectID(key));
735
+ }
736
+ if (alertIds.length === 0) {
737
+ throw new BadDataException("Please select at least one alert to link to the incident.");
738
+ }
739
+ if (alertIds.length > MAX_ALERTS_PER_INCIDENT_LINK_ACTION) {
740
+ throw new BadDataException(`You can link at most ${MAX_ALERTS_PER_INCIDENT_LINK_ACTION} alerts to an incident at a time. ${alertIds.length} were selected.`);
741
+ }
742
+ if (!data.projectId) {
743
+ throw new BadDataException("projectId is required to link alerts to an incident.");
744
+ }
745
+ const projectId = data.projectId;
746
+ if (!data.props.isRoot) {
747
+ /*
748
+ * The links are written as root once the incident exists (see
749
+ * IncidentService.onCreateSuccess), so this is where the caller's own
750
+ * right to link alerts is checked.
751
+ */
752
+ const probe = new Model();
753
+ probe.projectId = projectId;
754
+ probe.incidentId = ObjectID.generate();
755
+ probe.alertId = alertIds[0];
756
+ try {
757
+ ModelPermission.checkCreatePermissions(Model, probe, data.props);
758
+ }
759
+ catch (error) {
760
+ // A lapsed session or an unpaid project keeps its own answer.
761
+ if (error instanceof NotAuthorizedException ||
762
+ error instanceof BadDataException) {
763
+ throw new BadDataException("You do not have permission to link alerts to incidents in this project.");
764
+ }
765
+ throw error;
766
+ }
767
+ }
768
+ /*
769
+ * A user reads the alerts as themselves, so an alert they cannot open
770
+ * (a private alert, a label they are not allowed to see) cannot be
771
+ * pulled into their incident.
772
+ */
773
+ const alerts = await this.findVisible(() => {
774
+ return AlertService.findBy({
775
+ query: {
776
+ _id: QueryHelper.any(alertIds),
777
+ projectId: projectId,
778
+ },
779
+ select: {
780
+ _id: true,
781
+ },
782
+ limit: LIMIT_PER_PROJECT,
783
+ skip: 0,
784
+ props: data.props.isRoot ? { isRoot: true } : data.props,
785
+ });
786
+ });
787
+ const foundIds = new Set((alerts || []).map((alert) => {
788
+ return normalizeId(alert._id || "");
789
+ }));
790
+ const missing = alertIds.filter((id) => {
791
+ return !foundIds.has(normalizeId(id));
792
+ });
793
+ if (missing.length > 0) {
794
+ throw new BadDataException(NOT_VISIBLE_ALERTS_MESSAGE);
795
+ }
796
+ return alertIds;
797
+ }
798
+ /*
799
+ * Links each alert to the incident, one at a time. An alert that is already
800
+ * linked counts as done, not as a failure; any other failure is reported per
801
+ * alert and never stops the rest.
802
+ *
803
+ * `declaredWithIncident` marks links written while the incident is being
804
+ * declared from these alerts: they get no incident-side feed entry of their
805
+ * own (see INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY, root callers only).
806
+ */
807
+ async linkAlertsToIncident(data) {
808
+ const result = {
809
+ linkedAlertIds: [],
810
+ alreadyLinkedAlertIds: [],
811
+ failed: [],
812
+ };
813
+ for (const alertId of data.alertIds) {
814
+ const link = new Model();
815
+ link.projectId = data.projectId;
816
+ link.incidentId = data.incidentId;
817
+ link.alertId = alertId;
818
+ if (data.createdByUserId) {
819
+ link.createdByUserId = data.createdByUserId;
820
+ }
821
+ try {
822
+ await this.create(Object.assign({ data: link, props: data.props }, (data.declaredWithIncident
823
+ ? {
824
+ miscDataProps: {
825
+ [INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY]: true,
826
+ },
827
+ }
828
+ : {})));
829
+ result.linkedAlertIds.push(alertId);
830
+ }
831
+ catch (error) {
832
+ if (PostgresErrorTranslator.isUniqueViolation(error)) {
833
+ result.alreadyLinkedAlertIds.push(alertId);
834
+ continue;
835
+ }
836
+ const message = error instanceof Error ? error.message : String(error);
837
+ result.failed.push({ alertId: alertId, message: message });
838
+ logger.error(`IncidentAlertService could not link alert ${alertId.toString()} to incident ${data.incidentId.toString()}: ${message}`, {
839
+ projectId: data.projectId.toString(),
840
+ incidentId: data.incidentId.toString(),
841
+ alertId: alertId.toString(),
842
+ });
843
+ }
844
+ }
845
+ return result;
846
+ }
847
+ /*
848
+ * An incident changed state: bring its linked alerts along, when the
849
+ * project has opted in. Called fire-and-forget from
850
+ * IncidentStateTimelineService.onCreateSuccess for the incident's CURRENT
851
+ * state only. Never throws; every failure is logged, and one alert failing
852
+ * does not stop the others.
853
+ */
854
+ async cascadeIncidentStateToLinkedAlerts(data) {
855
+ try {
856
+ const switches = await this.getLinkedAlertSwitches(data.projectId);
857
+ if (!switches) {
858
+ return;
859
+ }
860
+ const plan = await this.buildLinkedAlertStatePlan({
861
+ projectId: data.projectId,
862
+ incidentStateId: data.incidentStateId,
863
+ switches: switches,
864
+ });
865
+ if (!plan) {
866
+ return;
867
+ }
868
+ const links = await this.findBy({
869
+ query: {
870
+ incidentId: data.incidentId,
871
+ projectId: data.projectId,
872
+ },
873
+ select: {
874
+ alertId: true,
875
+ },
876
+ limit: LIMIT_PER_PROJECT,
877
+ skip: 0,
878
+ props: {
879
+ isRoot: true,
880
+ },
881
+ });
882
+ const alertIds = [];
883
+ for (const link of links) {
884
+ if (link.alertId) {
885
+ alertIds.push(link.alertId);
886
+ }
887
+ }
888
+ if (alertIds.length === 0) {
889
+ return;
890
+ }
891
+ const incident = await IncidentService.findOneById({
892
+ id: data.incidentId,
893
+ select: {
894
+ incidentNumber: true,
895
+ incidentNumberWithPrefix: true,
896
+ },
897
+ props: {
898
+ isRoot: true,
899
+ },
900
+ });
901
+ if (!incident) {
902
+ return;
903
+ }
904
+ await this.applyLinkedAlertStatePlan({
905
+ plan: plan,
906
+ projectId: data.projectId,
907
+ incidentId: data.incidentId,
908
+ incidentNumber: formatNumber(incident.incidentNumberWithPrefix, incident.incidentNumber),
909
+ alertIds: alertIds,
910
+ });
911
+ }
912
+ catch (error) {
913
+ logger.error(`IncidentAlertService could not carry an incident state change over to its linked alerts: ${error}`, {
914
+ projectId: data.projectId.toString(),
915
+ incidentId: data.incidentId.toString(),
916
+ });
917
+ }
918
+ }
919
+ /*
920
+ * The link-time half: an alert was just linked to an incident that may
921
+ * already be acknowledged or resolved. Same rules as the cascade, applied to
922
+ * the one alert. A newly declared incident is in its created state, so
923
+ * this is a no-op for "declare incident from alerts". Never throws.
924
+ */
925
+ async syncAlertWithLinkedIncidentState(data) {
926
+ try {
927
+ const switches = await this.getLinkedAlertSwitches(data.projectId);
928
+ if (!switches) {
929
+ return;
930
+ }
931
+ const incident = await IncidentService.findOneById({
932
+ id: data.incidentId,
933
+ select: {
934
+ currentIncidentStateId: true,
935
+ incidentNumber: true,
936
+ incidentNumberWithPrefix: true,
937
+ },
938
+ props: {
939
+ isRoot: true,
940
+ },
941
+ });
942
+ if (!incident || !incident.currentIncidentStateId) {
943
+ return;
944
+ }
945
+ const plan = await this.buildLinkedAlertStatePlan({
946
+ projectId: data.projectId,
947
+ incidentStateId: incident.currentIncidentStateId,
948
+ switches: switches,
949
+ });
950
+ if (!plan) {
951
+ return;
952
+ }
953
+ await this.applyLinkedAlertStatePlan({
954
+ plan: plan,
955
+ projectId: data.projectId,
956
+ incidentId: data.incidentId,
957
+ incidentNumber: formatNumber(incident.incidentNumberWithPrefix, incident.incidentNumber),
958
+ alertIds: [data.alertId],
959
+ });
960
+ }
961
+ catch (error) {
962
+ logger.error(`IncidentAlertService could not sync a linked alert with its incident's state: ${error}`, {
963
+ projectId: data.projectId.toString(),
964
+ incidentId: data.incidentId.toString(),
965
+ alertId: data.alertId.toString(),
966
+ });
967
+ }
968
+ }
969
+ // Null when both project switches are off (the default).
970
+ async getLinkedAlertSwitches(projectId) {
971
+ const project = await ProjectService.findOneById({
972
+ id: projectId,
973
+ select: {
974
+ acknowledgeLinkedAlertsWhenIncidentAcknowledged: true,
975
+ resolveLinkedAlertsWhenIncidentResolved: true,
976
+ },
977
+ props: {
978
+ isRoot: true,
979
+ },
980
+ });
981
+ const switches = {
982
+ acknowledge: (project === null || project === void 0 ? void 0 : project.acknowledgeLinkedAlertsWhenIncidentAcknowledged) === true,
983
+ resolve: (project === null || project === void 0 ? void 0 : project.resolveLinkedAlertsWhenIncidentResolved) === true,
984
+ };
985
+ if (!switches.acknowledge && !switches.resolve) {
986
+ return null;
987
+ }
988
+ return switches;
989
+ }
990
+ // Null when the incident's state calls for nothing.
991
+ async buildLinkedAlertStatePlan(data) {
992
+ const logAttributes = {
993
+ projectId: data.projectId.toString(),
994
+ };
995
+ const incidentStates = await IncidentStateService.getAllIncidentStates({
996
+ projectId: data.projectId,
997
+ props: {
998
+ isRoot: true,
999
+ },
1000
+ });
1001
+ const incidentStateOrderById = new Map();
1002
+ for (const state of incidentStates) {
1003
+ if (state._id && state.order !== undefined && state.order !== null) {
1004
+ incidentStateOrderById.set(normalizeId(state._id), state.order);
1005
+ }
1006
+ }
1007
+ const incidentStateOrder = incidentStateOrderById.get(normalizeId(data.incidentStateId));
1008
+ if (incidentStateOrder === undefined) {
1009
+ logger.error(`IncidentAlertService: incident state ${data.incidentStateId.toString()} was not found in its project, linked alerts were left as they are.`, logAttributes);
1010
+ return null;
1011
+ }
1012
+ const acknowledgedIncidentState = incidentStates.find((state) => {
1013
+ return state.isAcknowledgedState;
1014
+ });
1015
+ const resolvedIncidentState = incidentStates.find((state) => {
1016
+ return state.isResolvedState;
1017
+ });
1018
+ const targets = getLinkedAlertStateTargets({
1019
+ incidentStateOrder: incidentStateOrder,
1020
+ acknowledgedIncidentStateOrder: acknowledgedIncidentState === null || acknowledgedIncidentState === void 0 ? void 0 : acknowledgedIncidentState.order,
1021
+ resolvedIncidentStateOrder: resolvedIncidentState === null || resolvedIncidentState === void 0 ? void 0 : resolvedIncidentState.order,
1022
+ acknowledgeSwitch: data.switches.acknowledge,
1023
+ resolveSwitch: data.switches.resolve,
1024
+ });
1025
+ if (!targets.acknowledge && !targets.resolve) {
1026
+ return null;
1027
+ }
1028
+ const alertStates = await AlertStateService.getAllAlertStates({
1029
+ projectId: data.projectId,
1030
+ props: {
1031
+ isRoot: true,
1032
+ },
1033
+ });
1034
+ const alertStateOrderById = new Map();
1035
+ for (const state of alertStates) {
1036
+ if (state._id && state.order !== undefined && state.order !== null) {
1037
+ alertStateOrderById.set(normalizeId(state._id), state.order);
1038
+ }
1039
+ }
1040
+ let acknowledgedAlertState = undefined;
1041
+ let resolvedAlertState = undefined;
1042
+ if (targets.acknowledge) {
1043
+ acknowledgedAlertState = alertStates.find((state) => {
1044
+ return state.isAcknowledgedState;
1045
+ });
1046
+ if (!acknowledgedAlertState) {
1047
+ logger.error("IncidentAlertService: the project has no Acknowledged alert state, so linked alerts could not be acknowledged.", logAttributes);
1048
+ }
1049
+ }
1050
+ if (targets.resolve) {
1051
+ resolvedAlertState = alertStates.find((state) => {
1052
+ return state.isResolvedState;
1053
+ });
1054
+ if (!resolvedAlertState) {
1055
+ logger.error("IncidentAlertService: the project has no Resolved alert state, so linked alerts could not be resolved.", logAttributes);
1056
+ }
1057
+ }
1058
+ if (!acknowledgedAlertState && !resolvedAlertState) {
1059
+ return null;
1060
+ }
1061
+ return {
1062
+ acknowledgedAlertState: acknowledgedAlertState,
1063
+ resolvedAlertState: resolvedAlertState,
1064
+ incidentReachedResolved: targets.incidentReachedResolved,
1065
+ resolvedIncidentStateOrder: resolvedIncidentState === null || resolvedIncidentState === void 0 ? void 0 : resolvedIncidentState.order,
1066
+ alertStateOrderById: alertStateOrderById,
1067
+ incidentStateOrderById: incidentStateOrderById,
1068
+ };
1069
+ }
1070
+ async applyLinkedAlertStatePlan(data) {
1071
+ var _a;
1072
+ const { plan, projectId, incidentId } = data;
1073
+ const alerts = await AlertService.findBy({
1074
+ query: {
1075
+ _id: QueryHelper.any(data.alertIds),
1076
+ projectId: projectId,
1077
+ },
1078
+ select: {
1079
+ _id: true,
1080
+ currentAlertStateId: true,
1081
+ },
1082
+ limit: LIMIT_PER_PROJECT,
1083
+ skip: 0,
1084
+ props: {
1085
+ isRoot: true,
1086
+ },
1087
+ });
1088
+ const blockedFromResolve = plan.resolvedAlertState
1089
+ ? await this.getAlertsHeldOpenByAnotherIncident({
1090
+ plan: plan,
1091
+ projectId: projectId,
1092
+ incidentId: incidentId,
1093
+ alerts: alerts,
1094
+ })
1095
+ : new Set();
1096
+ const incidentLabel = withNumber("Incident", data.incidentNumber);
1097
+ for (const alert of alerts) {
1098
+ const alertId = ((_a = alert._id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
1099
+ const alertStateOrder = alert.currentAlertStateId
1100
+ ? plan.alertStateOrderById.get(normalizeId(alert.currentAlertStateId))
1101
+ : undefined;
1102
+ if (!alertId || alertStateOrder === undefined) {
1103
+ logger.error(`IncidentAlertService: the current state of linked alert ${alertId} is unknown, so it was left as it is.`, {
1104
+ projectId: projectId.toString(),
1105
+ incidentId: incidentId.toString(),
1106
+ alertId: alertId,
1107
+ });
1108
+ continue;
1109
+ }
1110
+ const target = chooseLinkedAlertTargetState({
1111
+ alertStateOrder: alertStateOrder,
1112
+ acknowledgedAlertState: plan.acknowledgedAlertState,
1113
+ resolvedAlertState: plan.resolvedAlertState,
1114
+ isBlockedFromResolve: blockedFromResolve.has(normalizeId(alertId)),
1115
+ });
1116
+ if (!target || !target._id) {
1117
+ continue;
1118
+ }
1119
+ const isResolving = target === plan.resolvedAlertState;
1120
+ const rootCause = isResolving
1121
+ ? `Resolved because linked ${incidentLabel} was resolved.`
1122
+ : `Acknowledged because linked ${incidentLabel} was ${plan.incidentReachedResolved ? "resolved" : "acknowledged"}.`;
1123
+ try {
1124
+ await AlertService.changeAlertState({
1125
+ projectId: projectId,
1126
+ alertId: new ObjectID(alertId),
1127
+ alertStateId: new ObjectID(target._id.toString()),
1128
+ notifyOwners: false,
1129
+ rootCause: rootCause,
1130
+ stateChangeLog: undefined,
1131
+ props: {
1132
+ isRoot: true,
1133
+ },
1134
+ });
1135
+ }
1136
+ catch (error) {
1137
+ logger.error(`IncidentAlertService could not change the state of linked alert ${alertId}: ${error}`, {
1138
+ projectId: projectId.toString(),
1139
+ incidentId: incidentId.toString(),
1140
+ alertId: alertId,
1141
+ });
1142
+ }
1143
+ }
1144
+ }
1145
+ /*
1146
+ * An alert linked to several incidents is resolved only once none of them
1147
+ * is still open: resolving one incident must not close an alert another
1148
+ * open incident is still tracking. Only alerts that would otherwise be
1149
+ * resolved are looked up.
1150
+ */
1151
+ async getAlertsHeldOpenByAnotherIncident(data) {
1152
+ var _a;
1153
+ const held = new Set();
1154
+ const resolvedAlertStateOrder = (_a = data.plan.resolvedAlertState) === null || _a === void 0 ? void 0 : _a.order;
1155
+ if (resolvedAlertStateOrder === undefined) {
1156
+ return held;
1157
+ }
1158
+ const candidateIds = [];
1159
+ for (const alert of data.alerts) {
1160
+ const order = alert.currentAlertStateId
1161
+ ? data.plan.alertStateOrderById.get(normalizeId(alert.currentAlertStateId))
1162
+ : undefined;
1163
+ if (alert._id && order !== undefined && order < resolvedAlertStateOrder) {
1164
+ candidateIds.push(normalizeId(alert._id));
1165
+ }
1166
+ }
1167
+ if (candidateIds.length === 0) {
1168
+ return held;
1169
+ }
1170
+ const otherLinks = await this.findBy({
1171
+ query: {
1172
+ alertId: QueryHelper.any(candidateIds),
1173
+ projectId: data.projectId,
1174
+ },
1175
+ select: {
1176
+ alertId: true,
1177
+ incidentId: true,
1178
+ },
1179
+ limit: LIMIT_PER_PROJECT,
1180
+ skip: 0,
1181
+ props: {
1182
+ isRoot: true,
1183
+ },
1184
+ });
1185
+ const thisIncidentId = normalizeId(data.incidentId);
1186
+ const otherIncidentIdsByAlert = new Map();
1187
+ const otherIncidentIds = new Set();
1188
+ for (const link of otherLinks) {
1189
+ if (!link.alertId || !link.incidentId) {
1190
+ continue;
1191
+ }
1192
+ const incidentId = normalizeId(link.incidentId);
1193
+ if (incidentId === thisIncidentId) {
1194
+ continue;
1195
+ }
1196
+ const alertId = normalizeId(link.alertId);
1197
+ const incidentIds = otherIncidentIdsByAlert.get(alertId) || [];
1198
+ incidentIds.push(incidentId);
1199
+ otherIncidentIdsByAlert.set(alertId, incidentIds);
1200
+ otherIncidentIds.add(incidentId);
1201
+ }
1202
+ if (otherIncidentIds.size === 0) {
1203
+ return held;
1204
+ }
1205
+ const otherIncidents = await IncidentService.findBy({
1206
+ query: {
1207
+ _id: QueryHelper.any(Array.from(otherIncidentIds)),
1208
+ projectId: data.projectId,
1209
+ },
1210
+ select: {
1211
+ _id: true,
1212
+ currentIncidentStateId: true,
1213
+ },
1214
+ limit: LIMIT_PER_PROJECT,
1215
+ skip: 0,
1216
+ props: {
1217
+ isRoot: true,
1218
+ },
1219
+ });
1220
+ const openIncidentIds = new Set();
1221
+ for (const incident of otherIncidents) {
1222
+ if (!incident._id) {
1223
+ continue;
1224
+ }
1225
+ const order = incident.currentIncidentStateId
1226
+ ? data.plan.incidentStateOrderById.get(normalizeId(incident.currentIncidentStateId))
1227
+ : undefined;
1228
+ /*
1229
+ * An incident whose state cannot be placed is treated as open: leaving
1230
+ * an alert unresolved is recoverable, resolving it too early is not.
1231
+ */
1232
+ const isResolved = order !== undefined &&
1233
+ data.plan.resolvedIncidentStateOrder !== undefined &&
1234
+ order >= data.plan.resolvedIncidentStateOrder;
1235
+ if (!isResolved) {
1236
+ openIncidentIds.add(normalizeId(incident._id));
1237
+ }
1238
+ }
1239
+ for (const [alertId, incidentIds] of otherIncidentIdsByAlert) {
1240
+ if (incidentIds.some((incidentId) => {
1241
+ return openIncidentIds.has(incidentId);
1242
+ })) {
1243
+ held.add(alertId);
1244
+ }
1245
+ }
1246
+ return held;
1247
+ }
1248
+ }
1249
+ __decorate([
1250
+ CaptureSpan(),
1251
+ __metadata("design:type", Function),
1252
+ __metadata("design:paramtypes", [Object]),
1253
+ __metadata("design:returntype", Promise)
1254
+ ], Service.prototype, "onBeforeFind", null);
1255
+ __decorate([
1256
+ CaptureSpan(),
1257
+ __metadata("design:type", Function),
1258
+ __metadata("design:paramtypes", [Object]),
1259
+ __metadata("design:returntype", Promise)
1260
+ ], Service.prototype, "countBy", null);
1261
+ __decorate([
1262
+ CaptureSpan(),
1263
+ __metadata("design:type", Function),
1264
+ __metadata("design:paramtypes", [Object]),
1265
+ __metadata("design:returntype", Promise)
1266
+ ], Service.prototype, "onBeforeUpdate", null);
1267
+ __decorate([
1268
+ CaptureSpan(),
1269
+ __metadata("design:type", Function),
1270
+ __metadata("design:paramtypes", [Object]),
1271
+ __metadata("design:returntype", Promise)
1272
+ ], Service.prototype, "onBeforeCreate", null);
1273
+ __decorate([
1274
+ CaptureSpan(),
1275
+ __metadata("design:type", Function),
1276
+ __metadata("design:paramtypes", [Function]),
1277
+ __metadata("design:returntype", Promise)
1278
+ ], Service.prototype, "findVisible", null);
1279
+ __decorate([
1280
+ CaptureSpan(),
1281
+ __metadata("design:type", Function),
1282
+ __metadata("design:paramtypes", [Object, Model]),
1283
+ __metadata("design:returntype", Promise)
1284
+ ], Service.prototype, "onCreateSuccess", null);
1285
+ __decorate([
1286
+ CaptureSpan(),
1287
+ __metadata("design:type", Function),
1288
+ __metadata("design:paramtypes", [Object]),
1289
+ __metadata("design:returntype", Promise)
1290
+ ], Service.prototype, "onBeforeDelete", null);
1291
+ __decorate([
1292
+ CaptureSpan(),
1293
+ __metadata("design:type", Function),
1294
+ __metadata("design:paramtypes", [Object, Array]),
1295
+ __metadata("design:returntype", Promise)
1296
+ ], Service.prototype, "onDeleteSuccess", null);
1297
+ __decorate([
1298
+ CaptureSpan(),
1299
+ __metadata("design:type", Function),
1300
+ __metadata("design:paramtypes", [Object]),
1301
+ __metadata("design:returntype", Promise)
1302
+ ], Service.prototype, "createLinkFeedItems", null);
1303
+ __decorate([
1304
+ CaptureSpan(),
1305
+ __metadata("design:type", Function),
1306
+ __metadata("design:paramtypes", [Object]),
1307
+ __metadata("design:returntype", Promise)
1308
+ ], Service.prototype, "createDeclaredFromAlertsFeedItem", null);
1309
+ __decorate([
1310
+ CaptureSpan(),
1311
+ __metadata("design:type", Function),
1312
+ __metadata("design:paramtypes", [Object]),
1313
+ __metadata("design:returntype", Promise)
1314
+ ], Service.prototype, "buildDeclaredFromAlertsMarkdown", null);
1315
+ __decorate([
1316
+ CaptureSpan(),
1317
+ __metadata("design:type", Function),
1318
+ __metadata("design:paramtypes", [Object]),
1319
+ __metadata("design:returntype", Promise)
1320
+ ], Service.prototype, "copyAlertOwnersToIncident", null);
1321
+ __decorate([
1322
+ CaptureSpan(),
1323
+ __metadata("design:type", Function),
1324
+ __metadata("design:paramtypes", [Object]),
1325
+ __metadata("design:returntype", Promise)
1326
+ ], Service.prototype, "validateAlertIdsForNewIncident", null);
1327
+ __decorate([
1328
+ CaptureSpan(),
1329
+ __metadata("design:type", Function),
1330
+ __metadata("design:paramtypes", [Object]),
1331
+ __metadata("design:returntype", Promise)
1332
+ ], Service.prototype, "linkAlertsToIncident", null);
1333
+ __decorate([
1334
+ CaptureSpan(),
1335
+ __metadata("design:type", Function),
1336
+ __metadata("design:paramtypes", [Object]),
1337
+ __metadata("design:returntype", Promise)
1338
+ ], Service.prototype, "cascadeIncidentStateToLinkedAlerts", null);
1339
+ __decorate([
1340
+ CaptureSpan(),
1341
+ __metadata("design:type", Function),
1342
+ __metadata("design:paramtypes", [Object]),
1343
+ __metadata("design:returntype", Promise)
1344
+ ], Service.prototype, "syncAlertWithLinkedIncidentState", null);
1345
+ __decorate([
1346
+ CaptureSpan(),
1347
+ __metadata("design:type", Function),
1348
+ __metadata("design:paramtypes", [ObjectID]),
1349
+ __metadata("design:returntype", Promise)
1350
+ ], Service.prototype, "getLinkedAlertSwitches", null);
1351
+ __decorate([
1352
+ CaptureSpan(),
1353
+ __metadata("design:type", Function),
1354
+ __metadata("design:paramtypes", [Object]),
1355
+ __metadata("design:returntype", Promise)
1356
+ ], Service.prototype, "buildLinkedAlertStatePlan", null);
1357
+ __decorate([
1358
+ CaptureSpan(),
1359
+ __metadata("design:type", Function),
1360
+ __metadata("design:paramtypes", [Object]),
1361
+ __metadata("design:returntype", Promise)
1362
+ ], Service.prototype, "applyLinkedAlertStatePlan", null);
1363
+ __decorate([
1364
+ CaptureSpan(),
1365
+ __metadata("design:type", Function),
1366
+ __metadata("design:paramtypes", [Object]),
1367
+ __metadata("design:returntype", Promise)
1368
+ ], Service.prototype, "getAlertsHeldOpenByAnotherIncident", null);
1369
+ export default new Service();
1370
+ //# sourceMappingURL=IncidentAlertService.js.map