@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.
- package/Models/DatabaseModels/Alert.ts +55 -0
- package/Models/DatabaseModels/AlertFeed.ts +2 -0
- package/Models/DatabaseModels/DatabaseServer.ts +1650 -0
- package/Models/DatabaseModels/DatabaseServerEndpoint.ts +540 -0
- package/Models/DatabaseModels/DatabaseServerFeed.ts +625 -0
- package/Models/DatabaseModels/DatabaseServerLabelRule.ts +514 -0
- package/Models/DatabaseModels/DatabaseServerOwnerRule.ts +596 -0
- package/Models/DatabaseModels/DatabaseServerOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/DatabaseServerOwnerUser.ts +490 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/IncidentAlert.ts +540 -0
- package/Models/DatabaseModels/IncidentFeed.ts +2 -0
- package/Models/DatabaseModels/Index.ts +18 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +26 -0
- package/Models/DatabaseModels/Project.ts +60 -0
- package/Models/DatabaseModels/RumApplication.ts +52 -1
- package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
- package/Models/DatabaseModels/TelemetryException.ts +2 -0
- package/Models/DatabaseModels/UserProjectSsoConsent.ts +146 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.ts +28 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.ts +89 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.ts +673 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Middleware/MultipartFormData.ts +1 -1
- package/Server/Middleware/TelemetryIngest.ts +15 -8
- package/Server/Services/AlertReminderRuleService.ts +100 -24
- package/Server/Services/DatabaseServerEndpointService.ts +895 -0
- package/Server/Services/DatabaseServerFeedService.ts +128 -0
- package/Server/Services/DatabaseServerLabelRuleEngineService.ts +340 -0
- package/Server/Services/DatabaseServerLabelRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerRuleEngineService.ts +425 -0
- package/Server/Services/DatabaseServerOwnerRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerTeamService.ts +180 -0
- package/Server/Services/DatabaseServerOwnerUserService.ts +173 -0
- package/Server/Services/DatabaseServerService.ts +4546 -0
- package/Server/Services/DatabaseService.ts +14 -8
- package/Server/Services/DockerResourceService.ts +43 -2
- package/Server/Services/IncidentAlertService.ts +1811 -0
- package/Server/Services/IncidentReminderRuleService.ts +103 -23
- package/Server/Services/IncidentService.ts +210 -10
- package/Server/Services/IncidentStateTimelineService.ts +24 -0
- package/Server/Services/Index.ts +18 -0
- package/Server/Services/InventoryItemService.ts +113 -5
- package/Server/Services/IoTDeviceService.ts +145 -37
- package/Server/Services/OpenTelemetryIngestService.ts +19 -0
- package/Server/Services/PodmanResourceService.ts +43 -2
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +107 -23
- package/Server/Services/ServiceService.ts +1 -1
- package/Server/Services/TelemetryUsageBillingService.ts +29 -2
- package/Server/Services/UserProjectSsoConsentService.ts +74 -0
- package/Server/Services/UserService.ts +14 -1
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +18 -0
- package/Server/Types/Database/QueryHelper.ts +30 -1
- package/Server/Utils/AI/Toolbox/ResourceTools.ts +69 -1
- package/Server/Utils/Database/AffectedResourceRelations.ts +6 -0
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +188 -6
- package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +2262 -755
- package/Server/Utils/Monitor/MonitorIncident.ts +28 -1
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +268 -6
- package/Server/Utils/Monitor/MonitorResource.ts +47 -11
- package/Server/Utils/Monitor/MonitorResourceContext.ts +1 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +239 -21
- package/Server/Utils/Monitor/PerSeriesResolutionRootCause.ts +43 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +291 -0
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +111 -12
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +24 -2
- package/Server/Utils/StartServer.ts +26 -6
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/DatabaseEndpointDiscovery.ts +688 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +5 -1
- package/Server/Utils/Telemetry/LogExceptionExtractor.ts +18 -1
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +175 -12
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +12 -0
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +606 -36
- package/Server/Utils/Telemetry/Telemetry.ts +16 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +22 -22
- package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +16 -10
- package/Tests/App/Accounts/SignedInRedirect.test.tsx +241 -0
- package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +221 -4
- package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +42 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +100 -0
- package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +86 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +2 -0
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +19 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +14 -0
- package/Tests/App/Dashboard/BulkIncidentLinkActions.test.tsx +869 -0
- package/Tests/App/Dashboard/CephMetricTooltips.test.tsx +1777 -0
- package/Tests/App/Dashboard/CloudFleetSummary.test.ts +8 -0
- package/Tests/App/Dashboard/CloudMetricTooltips.test.tsx +887 -0
- package/Tests/App/Dashboard/ContainerHostMetricTooltips.test.tsx +1309 -0
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +26 -1
- package/Tests/App/Dashboard/DashboardAppSsoError.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +64 -1
- package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +178 -18
- package/Tests/App/Dashboard/DashboardMasterPageSsoRedirect.test.tsx +444 -0
- package/Tests/App/Dashboard/DashboardNavBarForeignHiddenRule.test.tsx +573 -0
- package/Tests/App/Dashboard/DatabaseChartAxes.test.tsx +431 -0
- package/Tests/App/Dashboard/DatabaseContainerDetailBadge.test.tsx +249 -0
- package/Tests/App/Dashboard/DatabaseDashboardE2EFixes.test.ts +681 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +1801 -0
- package/Tests/App/Dashboard/DatabaseFleetSummaryRefresh.test.tsx +280 -0
- package/Tests/App/Dashboard/DatabaseFormHelpers.test.tsx +321 -0
- package/Tests/App/Dashboard/DatabaseMetricMonitorLink.test.tsx +795 -0
- package/Tests/App/Dashboard/DatabaseOverviewHeader.test.tsx +580 -0
- package/Tests/App/Dashboard/DatabaseRecommendationsEngineMetrics.test.ts +270 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +1486 -0
- package/Tests/App/Dashboard/DatabaseServerEngineMetricsFilter.test.ts +223 -0
- package/Tests/App/Dashboard/DatabaseServerPresentation.test.ts +435 -0
- package/Tests/App/Dashboard/DatabaseServerSummary.test.ts +186 -0
- package/Tests/App/Dashboard/DatabaseServerTelemetryQueries.test.ts +1553 -0
- package/Tests/App/Dashboard/DatabaseTableTruncation.test.tsx +326 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +512 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +774 -0
- package/Tests/App/Dashboard/DatabaseViewLayout.test.tsx +233 -0
- package/Tests/App/Dashboard/DatabaseWorkloadBadge.test.tsx +972 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +5 -0
- package/Tests/App/Dashboard/DiscoveryReviewUnnamedHostHint.test.tsx +1061 -0
- package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +39 -0
- package/Tests/App/Dashboard/DockerSwarmClustersListTooltips.test.tsx +414 -0
- package/Tests/App/Dashboard/DockerSwarmMetricTooltips.test.ts +796 -0
- package/Tests/App/Dashboard/DockerSwarmOverviewTooltips.test.tsx +747 -0
- package/Tests/App/Dashboard/EventOverlayScope.test.ts +147 -0
- package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +1 -0
- package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +38 -18
- package/Tests/App/Dashboard/HostDetailViewTooltips.test.tsx +725 -0
- package/Tests/App/Dashboard/HostListColumnTooltips.test.tsx +472 -0
- package/Tests/App/Dashboard/HostMetricTooltips.test.ts +709 -0
- package/Tests/App/Dashboard/HostOverviewTooltips.test.tsx +698 -0
- package/Tests/App/Dashboard/HostTooltipHarness.ts +124 -0
- package/Tests/App/Dashboard/HostsListTooltips.test.tsx +395 -0
- package/Tests/App/Dashboard/IncidentAlertLinkDialog.test.tsx +691 -0
- package/Tests/App/Dashboard/IncidentAlertLinkHelpers.test.ts +458 -0
- package/Tests/App/Dashboard/IncidentAlertLinkPages.test.tsx +828 -0
- package/Tests/App/Dashboard/IncidentAlertLinkSideMenus.test.tsx +231 -0
- package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +689 -0
- package/Tests/App/Dashboard/IoTMetricTooltips.test.tsx +1123 -0
- package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +837 -0
- package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +699 -0
- package/Tests/App/Dashboard/KubernetesContainersTabTooltips.test.tsx +320 -0
- package/Tests/App/Dashboard/KubernetesCostTooltips.test.tsx +502 -0
- package/Tests/App/Dashboard/KubernetesInsightsTooltips.test.tsx +222 -0
- package/Tests/App/Dashboard/KubernetesResourceMetricTooltips.test.ts +561 -0
- package/Tests/App/Dashboard/KubernetesResourcePagesTooltips.test.tsx +1168 -0
- package/Tests/App/Dashboard/LinkIncidentAlertModal.test.tsx +154 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +1 -0
- package/Tests/App/Dashboard/MetricDescriptionRules.ts +170 -0
- package/Tests/App/Dashboard/MetricDescriptionsCatalog.test.ts +206 -0
- package/Tests/App/Dashboard/MetricDescriptionsConsistency.test.ts +275 -0
- package/Tests/App/Dashboard/MetricsViewerDrillDown.test.tsx +310 -0
- package/Tests/App/Dashboard/MetricsViewerEntityScopedRows.test.tsx +495 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +132 -1
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +5 -0
- package/Tests/App/Dashboard/NetworkDeviceTooltips.test.tsx +852 -0
- package/Tests/App/Dashboard/NetworkDiagnosticsTooltips.test.tsx +556 -0
- package/Tests/App/Dashboard/NetworkMetricTooltips.test.ts +1348 -0
- package/Tests/App/Dashboard/NetworkSiteTooltips.test.tsx +679 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +4 -3
- package/Tests/App/Dashboard/ProxmoxMetricTooltips.test.ts +592 -0
- package/Tests/App/Dashboard/ProxmoxOverviewTooltips.test.tsx +1002 -0
- package/Tests/App/Dashboard/ProxmoxResourcePageTooltips.test.tsx +923 -0
- package/Tests/App/Dashboard/RecommendationsLoadedContext.test.tsx +349 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +62 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +14 -0
- package/Tests/App/Dashboard/ResourceOverviewTileTooltips.test.tsx +1066 -0
- package/Tests/App/Dashboard/RumOverviewPage.test.tsx +1195 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +2 -0
- package/Tests/App/Dashboard/ServerlessMetricTooltips.test.tsx +474 -0
- package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +1085 -0
- package/Tests/App/Dashboard/ServiceMetricTooltips.test.tsx +772 -0
- package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +56 -1
- package/Tests/App/Dashboard/TelemetryMetricsSignals.test.ts +1207 -0
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +10 -0
- package/Tests/App/Dashboard/TelemetryResourceTabTooltips.test.tsx +437 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +2 -1
- package/Tests/App/Dashboard/VMwareMetricTooltips.test.ts +801 -0
- package/Tests/App/Dashboard/VMwareOverviewTooltips.test.tsx +601 -0
- package/Tests/App/Dashboard/VMwareResourcePagesTooltips.test.tsx +646 -0
- package/Tests/App/Dashboard/VMwareTooltipHarness.ts +145 -0
- package/Tests/App/StatusPage/StatusPageHeaderForeignHiddenRule.test.tsx +284 -0
- package/Tests/ClassStrings.ts +178 -0
- package/Tests/Fixtures/MobilePasskeyUser.json +1 -2
- package/Tests/ForeignHiddenRuleGuard.ts +2152 -0
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +2250 -0
- package/Tests/Models/DatabaseModels/IncidentAlertModel.test.ts +554 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +24 -5
- package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +117 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/RenderedMarkup.ts +518 -0
- package/Tests/ResponsiveVisibility.test.ts +490 -4
- package/Tests/ResponsiveVisibility.ts +505 -52
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +541 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentAlertMigration.test.ts +341 -0
- package/Tests/Server/Infrastructure/Postgres/AddSessionReplaySameOriginTracePropagationMigration.test.ts +247 -0
- package/Tests/Server/Infrastructure/Postgres/AddUserProjectSsoConsentMigration.test.ts +234 -0
- package/Tests/Server/Services/ContainerSnapshotUpsertPostgres.test.ts +319 -0
- package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +13 -0
- package/Tests/Server/Services/DatabaseServerEndpointService.test.ts +2033 -0
- package/Tests/Server/Services/DatabaseServerFeedAndOwnerServices.test.ts +529 -0
- package/Tests/Server/Services/DatabaseServerLifecycle.test.ts +3302 -0
- package/Tests/Server/Services/DatabaseServerRegistries.test.ts +603 -0
- package/Tests/Server/Services/DatabaseServerRuleEngines.test.ts +754 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +3558 -0
- package/Tests/Server/Services/DatabaseServerSqlPostgres.test.ts +2045 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedPostgres.test.ts +362 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedReply.test.ts +210 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +18 -0
- package/Tests/Server/Services/IncidentAlertPostgres.test.ts +903 -0
- package/Tests/Server/Services/IncidentAlertRegistration.test.ts +96 -0
- package/Tests/Server/Services/IncidentAlertService.test.ts +2225 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +2 -0
- package/Tests/Server/Services/IncidentAlertStateCascade.test.ts +970 -0
- package/Tests/Server/Services/IncidentCreateFromAlerts.test.ts +1284 -0
- package/Tests/Server/Services/IncomingCallPolicyEscalationRuleTarget.test.ts +225 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +280 -2
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +8 -2
- package/Tests/Server/Services/IoTDeviceLatestMetricsPostgres.test.ts +689 -0
- package/Tests/Server/Services/IoTDeviceService.test.ts +379 -0
- package/Tests/Server/Services/LatestMetricsValuesShape.test.ts +360 -0
- package/Tests/Server/Services/LlmModelPriceService.test.ts +402 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +61 -9
- package/Tests/Server/Services/ReminderRuleLookupPostgres.test.ts +2250 -0
- package/Tests/Server/Services/ReminderRuleRefreshOpenSubjectsPaging.test.ts +653 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +68 -20
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +9 -0
- package/Tests/Server/Services/UserProjectSsoConsentPostgres.test.ts +153 -0
- package/Tests/Server/Services/UserProjectSsoConsentService.test.ts +192 -0
- package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +71 -0
- package/Tests/Server/Services/UserSignupIdTakeoverPostgres.test.ts +238 -0
- package/Tests/Server/Services/WorkspaceNotificationSummaryHelpers.test.ts +592 -0
- package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +3 -0
- package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +1 -0
- package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +11 -0
- package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +8 -0
- package/Tests/Server/Types/Database/QueryHelperBooleanForCriteriaBackedRule.test.ts +1094 -0
- package/Tests/Server/Utils/AI/ResourceTools.test.ts +134 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +41 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +279 -9
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaDisplayContext.test.ts +933 -0
- package/Tests/Server/Utils/Monitor/DatabaseMaintenanceSuppression.test.ts +582 -0
- package/Tests/Server/Utils/Monitor/DatabaseServerMonitorLinking.test.ts +753 -0
- package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +119 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +60 -25
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorAffectedResourceEdgeCases.test.ts +1719 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesAffectedResources.test.ts +1447 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesRatioEmail.test.ts +352 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformMetricUnits.test.ts +717 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformRawScan.test.ts +2125 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformSeriesAffectedResources.test.ts +1288 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +88 -0
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +205 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +62 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceDatabaseMaintenance.test.ts +803 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +133 -3
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/PerSeriesRecoveryResolution.test.ts +472 -1
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +236 -2
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +70 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +103 -0
- package/Tests/Server/Utils/StartServerProtobufContentType.test.ts +54 -0
- package/Tests/Server/Utils/Telemetry/DatabaseEndpointDiscovery.test.ts +1895 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +7 -0
- package/Tests/Server/Utils/Telemetry/LogExceptionExtractorSeverityGate.test.ts +90 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +570 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +97 -2
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +1337 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +295 -0
- package/Tests/Types/AI/AIResourceContext.test.ts +30 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerClassifier.test.ts +3644 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommand.test.ts +340 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandCorpus.ts +826 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandPostgres.test.ts +150 -0
- package/Tests/Types/DatabaseServer/DatabaseEndpoint.test.ts +2657 -0
- package/Tests/Types/DatabaseServer/DatabaseServerDiscoverySource.test.ts +64 -0
- package/Tests/Types/DatabaseServer/DatabaseServerEntityKeys.test.ts +952 -0
- package/Tests/Types/DatabaseServer/DatabaseServerMetricCatalog.test.ts +1161 -0
- package/Tests/Types/DatabaseServer/DatabaseSystem.test.ts +1514 -0
- package/Tests/Types/DatabaseServer/DatabaseTelemetryResolver.test.ts +1558 -0
- package/Tests/Types/Monitor/CephAlertTemplates.test.ts +255 -6
- package/Tests/Types/Monitor/DatabaseAlertTemplates.test.ts +2254 -0
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +298 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +271 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +253 -9
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +13 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +4 -2
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +111 -2
- package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +61 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +114 -0
- package/Tests/Types/Monitor/Utils/KubernetesAgentEmittedMetrics.ts +181 -0
- package/Tests/Types/NetworkDevice/DiscoveredHostNamingStatus.test.ts +401 -0
- package/Tests/Types/Rum/WebVitals.test.ts +173 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +4 -1
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +24 -2
- package/Tests/UI/Components/Card.test.tsx +93 -2
- package/Tests/UI/Components/FeedOptions.test.ts +6 -0
- package/Tests/UI/Components/FeedOptionsButton.test.tsx +8 -1
- package/Tests/UI/Components/FieldLabelInfoCardTooltip.test.tsx +413 -0
- package/Tests/UI/Components/ForeignHiddenRuleResilience.test.tsx +1147 -0
- package/Tests/UI/Components/HeaderRightRail.test.tsx +41 -1
- package/Tests/UI/Components/InfoTooltip.test.tsx +242 -0
- package/Tests/UI/Components/LogsEntityNames.test.ts +16 -1
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +7 -3
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +207 -3
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDeleteVerb.test.tsx +367 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableCreateButtonTitle.test.tsx +275 -0
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +2 -1
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/SrOnlyForeignRule.test.tsx +994 -0
- package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +34 -1
- package/Tests/UI/Components/TableHeaderTooltip.test.tsx +662 -0
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +4 -1
- package/Tests/UI/ForeignHiddenRuleGuard.test.ts +1951 -0
- package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +166 -9
- package/Tests/UI/Rum/RecordingHealthTooltips.test.tsx +447 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +164 -0
- package/Tests/UI/Rum/ReplayFrameCapture.test.ts +6750 -0
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +19 -1
- package/Tests/UI/Rum/ReplayRail.test.tsx +723 -12
- package/Tests/UI/Rum/ReplayRailDetail.test.tsx +86 -0
- package/Tests/UI/Rum/ReplayScreenshot.test.ts +2124 -0
- package/Tests/UI/Rum/ReplayScreenshotActions.test.tsx +3288 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +62 -0
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +983 -2
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +19 -1
- package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +149 -0
- package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +107 -6
- package/Tests/UI/Rum/SessionReplayUsersTableTooltips.test.tsx +330 -0
- package/Tests/UI/Rum/UserFlowTooltips.test.tsx +886 -0
- package/Tests/UI/TailwindPlayCdnForeignHiddenRule.test.ts +1005 -0
- package/Tests/UI/ThemeGroupHoverReveal.test.ts +847 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +80 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +23 -0
- package/Tests/UI/Utils/ModelAPISsoRedirect.test.ts +127 -0
- package/Tests/UI/Utils/Navigation.test.ts +102 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +76 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +23 -0
- package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +696 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/MetricUnitUtil.test.ts +227 -2
- package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +288 -2
- package/Tests/Utils/Monitor/PlatformResourceIdentityAndUnits.test.ts +1559 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.test.ts +2546 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +315 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +336 -1
- package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +244 -0
- package/Tests/Utils/Rum/SessionTraceState.test.ts +239 -0
- package/Tests/Utils/ValueFormatter.test.ts +50 -0
- package/Tests/tsconfig.json +16 -0
- package/Types/AI/AIResourceContext.ts +7 -0
- package/Types/Dashboard/DashboardTemplates.ts +2 -1
- package/Types/DatabaseServer/DatabaseConnectionSpan.ts +77 -0
- package/Types/DatabaseServer/DatabaseContainerClassifier.ts +2068 -0
- package/Types/DatabaseServer/DatabaseContainerCommand.ts +801 -0
- package/Types/DatabaseServer/DatabaseEndpoint.ts +1943 -0
- package/Types/DatabaseServer/DatabaseServerDiscoverySource.ts +68 -0
- package/Types/DatabaseServer/DatabaseServerMetricCatalog.ts +966 -0
- package/Types/DatabaseServer/DatabaseSystem.ts +2124 -0
- package/Types/DatabaseServer/DatabaseTelemetryResolver.ts +555 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Incident/IncidentAlertLink.ts +38 -0
- package/Types/Monitor/CephAlertTemplates.ts +18 -0
- package/Types/Monitor/DatabaseAlertTemplates.ts +2020 -0
- package/Types/Monitor/KubernetesAlertTemplates.ts +64 -24
- package/Types/Monitor/KubernetesMetricCatalog.ts +118 -19
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +14 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +93 -10
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +109 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +36 -7
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +43 -2
- package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +41 -6
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +26 -0
- package/Types/NetworkDevice/DiscoveredHostNamingStatus.ts +147 -0
- package/Types/Permission.ts +315 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +8 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +10 -0
- package/Types/Rules/RuleRun.ts +12 -0
- package/Types/Rum/SessionReplay.ts +25 -6
- package/Types/Rum/WebVitals.ts +52 -0
- package/Types/Telemetry/EntityType.ts +23 -0
- package/Types/Telemetry/ResourceFacetCatalog.ts +14 -0
- package/Types/Telemetry/ServiceType.ts +8 -0
- package/UI/Components/Banner/Banner.tsx +1 -1
- package/UI/Components/Card/Card.tsx +1 -1
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +2 -2
- package/UI/Components/Charts/Line/LineChart.tsx +7 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +1 -1
- package/UI/Components/Date/StartAndEndDate.tsx +5 -5
- package/UI/Components/Detail/FieldLabel.tsx +8 -0
- package/UI/Components/Diagram/HorizontalStepChain.tsx +1 -1
- package/UI/Components/Feed/FeedOptionsButton.tsx +1 -1
- package/UI/Components/Forms/BasicForm.tsx +1 -1
- package/UI/Components/Header/Header.tsx +1 -1
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -1
- package/UI/Components/HeaderAlert/HeaderAlert.tsx +1 -1
- package/UI/Components/InfoCard/InfoCard.tsx +47 -1
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +1 -1
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +1 -1
- package/UI/Components/Modal/ModalFooter.tsx +1 -1
- package/UI/Components/ModelDetail/CardModelDetail.tsx +2 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +99 -21
- package/UI/Components/ModelTable/Column.ts +5 -0
- package/UI/Components/Navbar/NavBar.tsx +9 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -2
- package/UI/Components/Page/Page.tsx +1 -1
- package/UI/Components/Pagination/Pagination.tsx +3 -3
- package/UI/Components/ProgressButtons/ProgressButtonItem.tsx +1 -1
- package/UI/Components/SideMenu/SideMenu.tsx +4 -1
- package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +4 -2
- package/UI/Components/StatusPage/ResourceList.tsx +6 -6
- package/UI/Components/Table/TableHeader.tsx +47 -2
- package/UI/Components/Table/Types/Column.ts +7 -0
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +1 -1
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +1 -1
- package/UI/Components/Tooltip/InfoTooltip.tsx +78 -0
- package/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.tsx +1 -1
- package/UI/Components/Workflow/ComponentsModal.tsx +2 -2
- package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
- package/UI/Styles/Theme.css +8 -1
- package/UI/Utils/Navigation.ts +89 -42
- package/UI/Utils/PermissionGate.ts +11 -2
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +7 -0
- package/UI/Utils/TelemetryService.ts +4 -3
- package/Utils/Incident/IncidentFromAlerts.ts +516 -0
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/MetricUnitUtil.ts +103 -11
- package/Utils/Monitor/MetricValueFormatter.ts +66 -13
- package/Utils/Monitor/PlatformMetricUnitUtil.ts +215 -0
- package/Utils/Monitor/PlatformResourceIdentity.ts +514 -0
- package/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.ts +425 -0
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +32 -0
- package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +73 -0
- package/Utils/Rum/SessionTraceState.ts +212 -0
- package/Utils/Telemetry/DatabaseServerEntityKeys.ts +275 -0
- package/Utils/Telemetry/EntityKey.ts +176 -0
- package/Utils/ValueFormatter.ts +16 -0
- package/build/dist/Models/DatabaseModels/Alert.js +54 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +1683 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js +559 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Incident.js +54 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentAlert.js +553 -0
- package/build/dist/Models/DatabaseModels/IncidentAlert.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +18 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +62 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +53 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +2 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js +162 -0
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js +42 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js +240 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +15 -8
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +72 -23
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerEndpointService.js +694 -0
- package/build/dist/Server/Services/DatabaseServerEndpointService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js +110 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js +272 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js +340 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js +160 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js +153 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerService.js +3272 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseService.js +8 -4
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerResourceService.js +30 -3
- package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
- package/build/dist/Server/Services/IncidentAlertService.js +1370 -0
- package/build/dist/Server/Services/IncidentAlertService.js.map +1 -0
- package/build/dist/Server/Services/IncidentReminderRuleService.js +73 -23
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +164 -12
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +21 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +18 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +88 -5
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceService.js +111 -24
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +24 -9
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanResourceService.js +30 -3
- package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +75 -23
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +1 -1
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +23 -2
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/UserProjectSsoConsentService.js +79 -0
- package/build/dist/Server/Services/UserProjectSsoConsentService.js.map +1 -0
- package/build/dist/Server/Services/UserService.js +13 -1
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +18 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +26 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +46 -0
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +6 -0
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +134 -13
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +1489 -524
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +196 -6
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +36 -9
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +175 -17
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js +29 -0
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +211 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +82 -10
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +8 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +20 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js +442 -0
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +15 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +121 -5
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +12 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +438 -36
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +12 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +17 -18
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +16 -10
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -1
- package/build/dist/Types/AI/AIResourceContext.js +7 -0
- package/build/dist/Types/AI/AIResourceContext.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +2 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js +71 -0
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js +1462 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js +691 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js +1407 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js +60 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js +804 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js +1860 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js +406 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Incident/IncidentAlertLink.js +34 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -0
- package/build/dist/Types/Monitor/CephAlertTemplates.js +18 -0
- package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js +1518 -0
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +57 -24
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +104 -18
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +80 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +10 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +29 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +21 -6
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +25 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js +136 -0
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js.map +1 -0
- package/build/dist/Types/Permission.js +276 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +10 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Rum/WebVitals.js +25 -0
- package/build/dist/Types/Rum/WebVitals.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +23 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +14 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +8 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Banner/Banner.js +1 -1
- package/build/dist/UI/Components/Banner/Banner.js.map +1 -1
- package/build/dist/UI/Components/Card/Card.js +1 -1
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/Date/StartAndEndDate.js +5 -5
- package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
- package/build/dist/UI/Components/Detail/FieldLabel.js +2 -0
- package/build/dist/UI/Components/Detail/FieldLabel.js.map +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js +22 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +2 -2
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +70 -18
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +9 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/Page/Page.js +1 -1
- package/build/dist/UI/Components/Page/Page.js.map +1 -1
- package/build/dist/UI/Components/Pagination/Pagination.js +3 -3
- package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +3 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceList.js +6 -6
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
- package/build/dist/UI/Components/Table/TableHeader.js +18 -2
- package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/InfoTooltip.js +28 -0
- package/build/dist/UI/Components/Tooltip/InfoTooltip.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js +1 -1
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +2 -2
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +66 -33
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +4 -2
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +7 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +3 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/Utils/Incident/IncidentFromAlerts.js +306 -0
- package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -0
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/MetricUnitUtil.js +77 -13
- package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +58 -13
- package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -1
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js +161 -0
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js +323 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js +270 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +23 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +61 -0
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -1
- package/build/dist/Utils/Rum/SessionTraceState.js +154 -0
- package/build/dist/Utils/Rum/SessionTraceState.js.map +1 -0
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js +178 -0
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +133 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/ValueFormatter.js +15 -0
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +1 -1
- package/tsconfig.tests.json +7 -5
|
@@ -0,0 +1,903 @@
|
|
|
1
|
+
import Entities from "../../../Models/DatabaseModels/Index";
|
|
2
|
+
import IncidentAlert from "../../../Models/DatabaseModels/IncidentAlert";
|
|
3
|
+
import PostgresAppInstance from "../../../Server/Infrastructure/PostgresDatabase";
|
|
4
|
+
import AlertFeedService from "../../../Server/Services/AlertFeedService";
|
|
5
|
+
import AlertService from "../../../Server/Services/AlertService";
|
|
6
|
+
import IncidentAlertService, {
|
|
7
|
+
LinkAlertsToIncidentResult,
|
|
8
|
+
} from "../../../Server/Services/IncidentAlertService";
|
|
9
|
+
import IncidentFeedService from "../../../Server/Services/IncidentFeedService";
|
|
10
|
+
import IncidentService from "../../../Server/Services/IncidentService";
|
|
11
|
+
import PostgresErrorTranslator from "../../../Server/Utils/Database/PostgresErrorTranslator";
|
|
12
|
+
import URL from "../../../Types/API/URL";
|
|
13
|
+
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
14
|
+
import { INCIDENT_ALERT_ALREADY_LINKED_MESSAGE } from "../../../Types/Incident/IncidentAlertLink";
|
|
15
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
16
|
+
import Permission, {
|
|
17
|
+
UserTenantAccessPermission,
|
|
18
|
+
} from "../../../Types/Permission";
|
|
19
|
+
import PositiveNumber from "../../../Types/PositiveNumber";
|
|
20
|
+
import UserType from "../../../Types/UserType";
|
|
21
|
+
import { IncidentFeedEventType } from "../../../Models/DatabaseModels/IncidentFeed";
|
|
22
|
+
import { DataSource } from "typeorm";
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Opt in with RUN_POSTGRES_INCIDENT_ALERT_TESTS=true against a database the
|
|
26
|
+
* registered migrations have been applied to, e.g.
|
|
27
|
+
*
|
|
28
|
+
* RUN_POSTGRES_INCIDENT_ALERT_TESTS=true \
|
|
29
|
+
* INCIDENT_ALERT_TEST_DATABASE_HOST=127.0.0.1 \
|
|
30
|
+
* INCIDENT_ALERT_TEST_DATABASE_PORT=5400 \
|
|
31
|
+
* DATABASE_PASSWORD=... npx jest Tests/Server/Services/IncidentAlertPostgres.test.ts
|
|
32
|
+
*
|
|
33
|
+
* CI runs it in .github/workflows/postgres-schema-drift.yaml ("Test
|
|
34
|
+
* IncidentAlert link table on migrated Postgres"), right after that job has
|
|
35
|
+
* applied every registered migration to an empty database. The Common test
|
|
36
|
+
* job's Postgres is not migrated, so the suite is skipped there.
|
|
37
|
+
*
|
|
38
|
+
* Two halves:
|
|
39
|
+
*
|
|
40
|
+
* - the migrated public."IncidentAlert" is inspected as it is: its unique
|
|
41
|
+
* index and the ON DELETE rule of every foreign key;
|
|
42
|
+
* - behaviour runs in a uniquely named schema holding structure-only clones
|
|
43
|
+
* of Project, User, Incident, Alert and IncidentAlert. The clones carry the
|
|
44
|
+
* migrated indexes (LIKE ... INCLUDING ALL), and IncidentAlert's foreign
|
|
45
|
+
* keys are copied from the migrated table's own definitions, so a cascade
|
|
46
|
+
* observed here is the cascade the migration declared. No row is ever
|
|
47
|
+
* written outside that schema, and the schema is dropped afterwards.
|
|
48
|
+
*
|
|
49
|
+
* The production IncidentAlertService runs against the clones; only feed
|
|
50
|
+
* delivery, dashboard links, realtime and workflow triggers are stubbed.
|
|
51
|
+
* Privacy clauses reference the owner and team tables, which are not cloned:
|
|
52
|
+
* they resolve to the migrated public tables through the search path, where a
|
|
53
|
+
* member with a freshly generated id owns nothing.
|
|
54
|
+
*/
|
|
55
|
+
const describePostgres: typeof describe =
|
|
56
|
+
process.env["RUN_POSTGRES_INCIDENT_ALERT_TESTS"] === "true"
|
|
57
|
+
? describe
|
|
58
|
+
: describe.skip;
|
|
59
|
+
|
|
60
|
+
const TABLES: Array<string> = [
|
|
61
|
+
"Project",
|
|
62
|
+
"User",
|
|
63
|
+
"Incident",
|
|
64
|
+
"Alert",
|
|
65
|
+
"IncidentAlert",
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
const UNIQUE_INDEX_NAME: string = "IDX_b836b78cef9ce62e4d8f2cc586";
|
|
69
|
+
|
|
70
|
+
interface ForeignKeyRow {
|
|
71
|
+
name: string;
|
|
72
|
+
column: string;
|
|
73
|
+
referencedTable: string;
|
|
74
|
+
onDelete: string;
|
|
75
|
+
definition: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
describePostgres("IncidentAlert against a migrated Postgres", () => {
|
|
79
|
+
const schema: string = `incident_alert_${ObjectID.generate()
|
|
80
|
+
.toString()
|
|
81
|
+
.replace(/-/g, "")}`;
|
|
82
|
+
|
|
83
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
84
|
+
const otherProjectId: ObjectID = ObjectID.generate();
|
|
85
|
+
|
|
86
|
+
let database: DataSource;
|
|
87
|
+
let migratedForeignKeys: Array<ForeignKeyRow> = [];
|
|
88
|
+
|
|
89
|
+
let incidentFeed: jest.SpyInstance;
|
|
90
|
+
|
|
91
|
+
beforeAll(async () => {
|
|
92
|
+
database = new DataSource({
|
|
93
|
+
type: "postgres",
|
|
94
|
+
host: process.env["INCIDENT_ALERT_TEST_DATABASE_HOST"] || "localhost",
|
|
95
|
+
port: Number(process.env["INCIDENT_ALERT_TEST_DATABASE_PORT"] || "5400"),
|
|
96
|
+
username: process.env["DATABASE_USERNAME"] || "postgres",
|
|
97
|
+
password: process.env["DATABASE_PASSWORD"] || "password",
|
|
98
|
+
database:
|
|
99
|
+
process.env["INCIDENT_ALERT_TEST_DATABASE_NAME"] ||
|
|
100
|
+
process.env["DATABASE_NAME"] ||
|
|
101
|
+
"oneuptimedb",
|
|
102
|
+
entities: Entities,
|
|
103
|
+
schema,
|
|
104
|
+
synchronize: false,
|
|
105
|
+
extra: { options: `-c search_path=${schema},public` },
|
|
106
|
+
});
|
|
107
|
+
await database.initialize();
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
* Read the migrated foreign keys before the clones exist, so their
|
|
111
|
+
* definitions name the referenced tables without a schema.
|
|
112
|
+
*/
|
|
113
|
+
migratedForeignKeys = await database.query(
|
|
114
|
+
`SELECT c.conname AS "name",
|
|
115
|
+
a.attname AS "column",
|
|
116
|
+
r.relname AS "referencedTable",
|
|
117
|
+
c.confdeltype AS "onDelete",
|
|
118
|
+
pg_get_constraintdef(c.oid) AS "definition"
|
|
119
|
+
FROM pg_constraint c
|
|
120
|
+
JOIN pg_class t ON t.oid = c.conrelid
|
|
121
|
+
JOIN pg_namespace n ON n.oid = t.relnamespace
|
|
122
|
+
JOIN pg_class r ON r.oid = c.confrelid
|
|
123
|
+
JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = c.conkey[1]
|
|
124
|
+
WHERE n.nspname = 'public' AND t.relname = 'IncidentAlert' AND c.contype = 'f'
|
|
125
|
+
ORDER BY a.attname`,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
await database.query(`CREATE SCHEMA "${schema}"`);
|
|
129
|
+
|
|
130
|
+
for (const table of TABLES) {
|
|
131
|
+
await database.query(
|
|
132
|
+
`CREATE TABLE "${schema}"."${table}" (LIKE public."${table}" INCLUDING ALL)`,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
for (const foreignKey of migratedForeignKeys) {
|
|
137
|
+
const definition: string = foreignKey.definition.replace(
|
|
138
|
+
/REFERENCES public\./g,
|
|
139
|
+
"REFERENCES ",
|
|
140
|
+
);
|
|
141
|
+
await database.query(
|
|
142
|
+
`ALTER TABLE "${schema}"."IncidentAlert" ADD CONSTRAINT "${foreignKey.name}" ${definition}`,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const currentSchema: Array<{ current_schema: string }> =
|
|
147
|
+
await database.query("SELECT current_schema()");
|
|
148
|
+
expect(currentSchema[0]?.current_schema).toBe(schema);
|
|
149
|
+
|
|
150
|
+
jest.spyOn(PostgresAppInstance, "isConnected").mockReturnValue(true);
|
|
151
|
+
jest.spyOn(PostgresAppInstance, "getDataSource").mockReturnValue(database);
|
|
152
|
+
jest
|
|
153
|
+
.spyOn(IncidentAlertService, "onTriggerRealtime")
|
|
154
|
+
.mockResolvedValue(undefined);
|
|
155
|
+
jest
|
|
156
|
+
.spyOn(IncidentAlertService, "onTriggerWorkflow")
|
|
157
|
+
.mockResolvedValue(undefined);
|
|
158
|
+
jest
|
|
159
|
+
.spyOn(IncidentService, "getIncidentLinkInDashboard")
|
|
160
|
+
.mockResolvedValue(URL.fromString("https://oneuptime.example/incident"));
|
|
161
|
+
jest
|
|
162
|
+
.spyOn(AlertService, "getAlertLinkInDashboard")
|
|
163
|
+
.mockResolvedValue(URL.fromString("https://oneuptime.example/alert"));
|
|
164
|
+
jest
|
|
165
|
+
.spyOn(AlertFeedService, "createAlertFeedItem")
|
|
166
|
+
.mockResolvedValue(undefined);
|
|
167
|
+
incidentFeed = jest
|
|
168
|
+
.spyOn(IncidentFeedService, "createIncidentFeedItem")
|
|
169
|
+
.mockResolvedValue(undefined);
|
|
170
|
+
// The state sync has its own tests; here it would only read the switches.
|
|
171
|
+
jest
|
|
172
|
+
.spyOn(IncidentAlertService, "syncAlertWithLinkedIncidentState")
|
|
173
|
+
.mockResolvedValue(undefined);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
beforeEach(async () => {
|
|
177
|
+
incidentFeed.mockClear();
|
|
178
|
+
await database.query(
|
|
179
|
+
TABLES.map((table: string): string => {
|
|
180
|
+
return `DELETE FROM "${schema}"."${table}"`;
|
|
181
|
+
})
|
|
182
|
+
.reverse()
|
|
183
|
+
.join("; "),
|
|
184
|
+
);
|
|
185
|
+
await seedProject(projectId);
|
|
186
|
+
await seedProject(otherProjectId);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
afterAll(async () => {
|
|
190
|
+
jest.restoreAllMocks();
|
|
191
|
+
if (database?.isInitialized) {
|
|
192
|
+
await database.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
|
|
193
|
+
await database.destroy();
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
async function seedProject(id: ObjectID): Promise<void> {
|
|
198
|
+
await database.query(
|
|
199
|
+
`INSERT INTO "${schema}"."Project" ("_id", "name", "slug", "version")
|
|
200
|
+
VALUES ($1, 'Incident alert link test', $2, 1)`,
|
|
201
|
+
[id.toString(), `incident-alert-${id.toString()}`],
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function seedUser(): Promise<ObjectID> {
|
|
206
|
+
const id: ObjectID = ObjectID.generate();
|
|
207
|
+
await database.query(
|
|
208
|
+
`INSERT INTO "${schema}"."User" ("_id", "email", "slug", "version")
|
|
209
|
+
VALUES ($1, $2, $3, 1)`,
|
|
210
|
+
[
|
|
211
|
+
id.toString(),
|
|
212
|
+
`incident-alert-${id.toString()}@example.com`,
|
|
213
|
+
`incident-alert-${id.toString()}`,
|
|
214
|
+
],
|
|
215
|
+
);
|
|
216
|
+
return id;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function seedIncident(
|
|
220
|
+
options: { project?: ObjectID; isPrivate?: boolean } = {},
|
|
221
|
+
): Promise<ObjectID> {
|
|
222
|
+
const id: ObjectID = ObjectID.generate();
|
|
223
|
+
await database.query(
|
|
224
|
+
`INSERT INTO "${schema}"."Incident"
|
|
225
|
+
("_id", "projectId", "title", "slug", "currentIncidentStateId", "incidentSeverityId", "isPrivate", "version")
|
|
226
|
+
VALUES ($1, $2, 'Checkout is failing', $3, $4, $5, $6, 1)`,
|
|
227
|
+
[
|
|
228
|
+
id.toString(),
|
|
229
|
+
(options.project || projectId).toString(),
|
|
230
|
+
`incident-${id.toString()}`,
|
|
231
|
+
ObjectID.generate().toString(),
|
|
232
|
+
ObjectID.generate().toString(),
|
|
233
|
+
Boolean(options.isPrivate),
|
|
234
|
+
],
|
|
235
|
+
);
|
|
236
|
+
return id;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function seedAlert(
|
|
240
|
+
options: { project?: ObjectID; isPrivate?: boolean } = {},
|
|
241
|
+
): Promise<ObjectID> {
|
|
242
|
+
const id: ObjectID = ObjectID.generate();
|
|
243
|
+
await database.query(
|
|
244
|
+
`INSERT INTO "${schema}"."Alert"
|
|
245
|
+
("_id", "projectId", "title", "currentAlertStateId", "alertSeverityId", "isPrivate", "version")
|
|
246
|
+
VALUES ($1, $2, 'Checkout p95 latency is high', $3, $4, $5, 1)`,
|
|
247
|
+
[
|
|
248
|
+
id.toString(),
|
|
249
|
+
(options.project || projectId).toString(),
|
|
250
|
+
ObjectID.generate().toString(),
|
|
251
|
+
ObjectID.generate().toString(),
|
|
252
|
+
Boolean(options.isPrivate),
|
|
253
|
+
],
|
|
254
|
+
);
|
|
255
|
+
return id;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async function insertLink(
|
|
259
|
+
incidentId: ObjectID,
|
|
260
|
+
alertId: ObjectID,
|
|
261
|
+
createdByUserId: ObjectID | null = null,
|
|
262
|
+
): Promise<ObjectID> {
|
|
263
|
+
const id: ObjectID = ObjectID.generate();
|
|
264
|
+
await database.query(
|
|
265
|
+
`INSERT INTO "${schema}"."IncidentAlert"
|
|
266
|
+
("_id", "projectId", "incidentId", "alertId", "createdByUserId", "version")
|
|
267
|
+
VALUES ($1, $2, $3, $4, $5, 1)`,
|
|
268
|
+
[
|
|
269
|
+
id.toString(),
|
|
270
|
+
projectId.toString(),
|
|
271
|
+
incidentId.toString(),
|
|
272
|
+
alertId.toString(),
|
|
273
|
+
createdByUserId ? createdByUserId.toString() : null,
|
|
274
|
+
],
|
|
275
|
+
);
|
|
276
|
+
return id;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async function linkRows(): Promise<
|
|
280
|
+
Array<{ _id: string; createdByUserId: string | null }>
|
|
281
|
+
> {
|
|
282
|
+
return database.query(
|
|
283
|
+
`SELECT "_id", "createdByUserId" FROM "${schema}"."IncidentAlert" ORDER BY "createdAt"`,
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async function linkCount(): Promise<number> {
|
|
288
|
+
const rows: Array<{ count: string }> = await database.query(
|
|
289
|
+
`SELECT count(*)::text AS "count" FROM "${schema}"."IncidentAlert"`,
|
|
290
|
+
);
|
|
291
|
+
return Number(rows[0]!.count);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// A ProjectMember of the test project, who owns nothing.
|
|
295
|
+
function memberProps(
|
|
296
|
+
userId: ObjectID = ObjectID.generate(),
|
|
297
|
+
): DatabaseCommonInteractionProps {
|
|
298
|
+
const tenantPermission: UserTenantAccessPermission = {
|
|
299
|
+
projectId: projectId,
|
|
300
|
+
_type: "UserTenantAccessPermission",
|
|
301
|
+
permissions: [
|
|
302
|
+
{
|
|
303
|
+
_type: "UserPermission",
|
|
304
|
+
permission: Permission.ProjectMember,
|
|
305
|
+
labelIds: [],
|
|
306
|
+
isBlockPermission: false,
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
tenantId: projectId,
|
|
313
|
+
userId: userId,
|
|
314
|
+
userType: UserType.User,
|
|
315
|
+
userTenantAccessPermission: {
|
|
316
|
+
[projectId.toString()]: tenantPermission,
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
async function failureOf(run: () => Promise<unknown>): Promise<unknown> {
|
|
322
|
+
try {
|
|
323
|
+
await run();
|
|
324
|
+
} catch (error) {
|
|
325
|
+
return error;
|
|
326
|
+
}
|
|
327
|
+
throw new Error("expected the call to fail");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function sqlState(run: () => Promise<unknown>): Promise<string> {
|
|
331
|
+
try {
|
|
332
|
+
await run();
|
|
333
|
+
} catch (error) {
|
|
334
|
+
return String(
|
|
335
|
+
(error as { code?: string; driverError?: { code?: string } }).code ||
|
|
336
|
+
(error as { driverError?: { code?: string } }).driverError?.code,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
return "no error";
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
describe("the migrated table", () => {
|
|
343
|
+
test("a pair is unique: (incidentId, alertId, projectId) has a unique index", async () => {
|
|
344
|
+
const rows: Array<{ indexdef: string }> = await database.query(
|
|
345
|
+
`SELECT indexdef FROM pg_indexes WHERE schemaname = 'public' AND tablename = 'IncidentAlert' AND indexname = $1`,
|
|
346
|
+
[UNIQUE_INDEX_NAME],
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
expect(rows).toHaveLength(1);
|
|
350
|
+
expect(rows[0]!.indexdef).toContain("CREATE UNIQUE INDEX");
|
|
351
|
+
expect(rows[0]!.indexdef).toContain(
|
|
352
|
+
'("incidentId", "alertId", "projectId")',
|
|
353
|
+
);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test("a link goes with its project, incident or alert, and outlives its users", () => {
|
|
357
|
+
expect(
|
|
358
|
+
migratedForeignKeys.map((foreignKey: ForeignKeyRow) => {
|
|
359
|
+
return [
|
|
360
|
+
foreignKey.column,
|
|
361
|
+
foreignKey.referencedTable,
|
|
362
|
+
foreignKey.onDelete,
|
|
363
|
+
];
|
|
364
|
+
}),
|
|
365
|
+
).toEqual([
|
|
366
|
+
// confdeltype: c = CASCADE, n = SET NULL
|
|
367
|
+
["alertId", "Alert", "c"],
|
|
368
|
+
["createdByUserId", "User", "n"],
|
|
369
|
+
["deletedByUserId", "User", "n"],
|
|
370
|
+
["incidentId", "Incident", "c"],
|
|
371
|
+
["projectId", "Project", "c"],
|
|
372
|
+
]);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test("every existing project starts with both switches off", async () => {
|
|
376
|
+
const rows: Array<{ column_name: string; column_default: string }> =
|
|
377
|
+
await database.query(
|
|
378
|
+
`SELECT column_name, column_default FROM information_schema.columns
|
|
379
|
+
WHERE table_schema = 'public' AND table_name = 'Project'
|
|
380
|
+
AND column_name IN ('acknowledgeLinkedAlertsWhenIncidentAcknowledged', 'resolveLinkedAlertsWhenIncidentResolved')
|
|
381
|
+
AND is_nullable = 'NO'
|
|
382
|
+
ORDER BY column_name`,
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
expect(rows).toEqual([
|
|
386
|
+
{
|
|
387
|
+
column_name: "acknowledgeLinkedAlertsWhenIncidentAcknowledged",
|
|
388
|
+
column_default: "false",
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
column_name: "resolveLinkedAlertsWhenIncidentResolved",
|
|
392
|
+
column_default: "false",
|
|
393
|
+
},
|
|
394
|
+
]);
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
describe("the database keeps a pair unique", () => {
|
|
399
|
+
test("a second row for the same incident and alert is rejected", async () => {
|
|
400
|
+
const incidentId: ObjectID = await seedIncident();
|
|
401
|
+
const alertId: ObjectID = await seedAlert();
|
|
402
|
+
|
|
403
|
+
await insertLink(incidentId, alertId);
|
|
404
|
+
|
|
405
|
+
expect(
|
|
406
|
+
await sqlState(() => {
|
|
407
|
+
return insertLink(incidentId, alertId);
|
|
408
|
+
}),
|
|
409
|
+
).toBe("23505");
|
|
410
|
+
expect(await linkCount()).toBe(1);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test("one alert may be linked to several incidents, and one incident to several alerts", async () => {
|
|
414
|
+
const incidentId: ObjectID = await seedIncident();
|
|
415
|
+
const otherIncidentId: ObjectID = await seedIncident();
|
|
416
|
+
const alertId: ObjectID = await seedAlert();
|
|
417
|
+
const otherAlertId: ObjectID = await seedAlert();
|
|
418
|
+
|
|
419
|
+
await insertLink(incidentId, alertId);
|
|
420
|
+
await insertLink(otherIncidentId, alertId);
|
|
421
|
+
await insertLink(incidentId, otherAlertId);
|
|
422
|
+
|
|
423
|
+
expect(await linkCount()).toBe(3);
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
describe("deleting either end removes the link", () => {
|
|
428
|
+
test("deleting the alert deletes its links", async () => {
|
|
429
|
+
const incidentId: ObjectID = await seedIncident();
|
|
430
|
+
const alertId: ObjectID = await seedAlert();
|
|
431
|
+
const otherAlertId: ObjectID = await seedAlert();
|
|
432
|
+
await insertLink(incidentId, alertId);
|
|
433
|
+
const keptLinkId: ObjectID = await insertLink(incidentId, otherAlertId);
|
|
434
|
+
|
|
435
|
+
await database.query(`DELETE FROM "${schema}"."Alert" WHERE "_id" = $1`, [
|
|
436
|
+
alertId.toString(),
|
|
437
|
+
]);
|
|
438
|
+
|
|
439
|
+
expect(
|
|
440
|
+
(await linkRows()).map((row: { _id: string }) => {
|
|
441
|
+
return row._id;
|
|
442
|
+
}),
|
|
443
|
+
).toEqual([keptLinkId.toString()]);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
test("deleting the incident deletes its links", async () => {
|
|
447
|
+
const incidentId: ObjectID = await seedIncident();
|
|
448
|
+
const otherIncidentId: ObjectID = await seedIncident();
|
|
449
|
+
const alertId: ObjectID = await seedAlert();
|
|
450
|
+
await insertLink(incidentId, alertId);
|
|
451
|
+
const keptLinkId: ObjectID = await insertLink(otherIncidentId, alertId);
|
|
452
|
+
|
|
453
|
+
await database.query(
|
|
454
|
+
`DELETE FROM "${schema}"."Incident" WHERE "_id" = $1`,
|
|
455
|
+
[incidentId.toString()],
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
expect(
|
|
459
|
+
(await linkRows()).map((row: { _id: string }) => {
|
|
460
|
+
return row._id;
|
|
461
|
+
}),
|
|
462
|
+
).toEqual([keptLinkId.toString()]);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test("deleting the project deletes its links", async () => {
|
|
466
|
+
await insertLink(await seedIncident(), await seedAlert());
|
|
467
|
+
|
|
468
|
+
await database.query(
|
|
469
|
+
`DELETE FROM "${schema}"."Project" WHERE "_id" = $1`,
|
|
470
|
+
[projectId.toString()],
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
expect(await linkCount()).toBe(0);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("deleting the user who linked it keeps the link and forgets the user", async () => {
|
|
477
|
+
const userId: ObjectID = await seedUser();
|
|
478
|
+
const linkId: ObjectID = await insertLink(
|
|
479
|
+
await seedIncident(),
|
|
480
|
+
await seedAlert(),
|
|
481
|
+
userId,
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
expect((await linkRows())[0]!.createdByUserId).toBe(userId.toString());
|
|
485
|
+
|
|
486
|
+
await database.query(`DELETE FROM "${schema}"."User" WHERE "_id" = $1`, [
|
|
487
|
+
userId.toString(),
|
|
488
|
+
]);
|
|
489
|
+
|
|
490
|
+
expect(await linkRows()).toEqual([
|
|
491
|
+
{ _id: linkId.toString(), createdByUserId: null },
|
|
492
|
+
]);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
test("a link to an incident or alert that does not exist is rejected", async () => {
|
|
496
|
+
const alertId: ObjectID = await seedAlert();
|
|
497
|
+
|
|
498
|
+
expect(
|
|
499
|
+
await sqlState(() => {
|
|
500
|
+
return insertLink(ObjectID.generate(), alertId);
|
|
501
|
+
}),
|
|
502
|
+
).toBe("23503");
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
describe("IncidentAlertService on the real tables", () => {
|
|
507
|
+
function link(incidentId: ObjectID, alertId: ObjectID): IncidentAlert {
|
|
508
|
+
const row: IncidentAlert = new IncidentAlert();
|
|
509
|
+
row.projectId = projectId;
|
|
510
|
+
row.incidentId = incidentId;
|
|
511
|
+
row.alertId = alertId;
|
|
512
|
+
return row;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
test("links an alert, and refuses to link it twice", async () => {
|
|
516
|
+
const incidentId: ObjectID = await seedIncident();
|
|
517
|
+
const alertId: ObjectID = await seedAlert();
|
|
518
|
+
|
|
519
|
+
await IncidentAlertService.create({
|
|
520
|
+
data: link(incidentId, alertId),
|
|
521
|
+
props: { isRoot: true },
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
let duplicate: unknown = null;
|
|
525
|
+
try {
|
|
526
|
+
await IncidentAlertService.create({
|
|
527
|
+
data: link(incidentId, alertId),
|
|
528
|
+
props: { isRoot: true },
|
|
529
|
+
});
|
|
530
|
+
} catch (error) {
|
|
531
|
+
duplicate = error;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
expect(PostgresErrorTranslator.isUniqueViolation(duplicate)).toBe(true);
|
|
535
|
+
expect((duplicate as Error).message).toBe(
|
|
536
|
+
INCIDENT_ALERT_ALREADY_LINKED_MESSAGE,
|
|
537
|
+
);
|
|
538
|
+
expect(await linkCount()).toBe(1);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
test("two requests racing past the unique-together check: the unique index answers 'already linked'", async () => {
|
|
542
|
+
const incidentId: ObjectID = await seedIncident();
|
|
543
|
+
const alertId: ObjectID = await seedAlert();
|
|
544
|
+
|
|
545
|
+
await IncidentAlertService.create({
|
|
546
|
+
data: link(incidentId, alertId),
|
|
547
|
+
props: { isRoot: true },
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
/*
|
|
551
|
+
* The second request's check ran before the first request's insert
|
|
552
|
+
* committed, so it found nothing: the INSERT itself hits the index.
|
|
553
|
+
*/
|
|
554
|
+
const uniqueTogetherCheck: jest.SpyInstance = jest
|
|
555
|
+
.spyOn(IncidentAlertService, "countBy")
|
|
556
|
+
.mockResolvedValue(new PositiveNumber(0));
|
|
557
|
+
|
|
558
|
+
try {
|
|
559
|
+
const duplicate: unknown = await failureOf(() => {
|
|
560
|
+
return IncidentAlertService.create({
|
|
561
|
+
data: link(incidentId, alertId),
|
|
562
|
+
props: { isRoot: true },
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
expect(uniqueTogetherCheck).toHaveBeenCalled();
|
|
567
|
+
expect((duplicate as Error).message).toBe(
|
|
568
|
+
INCIDENT_ALERT_ALREADY_LINKED_MESSAGE,
|
|
569
|
+
);
|
|
570
|
+
expect(PostgresErrorTranslator.isUniqueViolation(duplicate)).toBe(true);
|
|
571
|
+
|
|
572
|
+
// ...and a bulk link counts it as done, not as a failure.
|
|
573
|
+
const result: LinkAlertsToIncidentResult =
|
|
574
|
+
await IncidentAlertService.linkAlertsToIncident({
|
|
575
|
+
projectId: projectId,
|
|
576
|
+
incidentId: incidentId,
|
|
577
|
+
alertIds: [alertId],
|
|
578
|
+
props: { isRoot: true },
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
expect(result.alreadyLinkedAlertIds.map(String)).toEqual([
|
|
582
|
+
alertId.toString(),
|
|
583
|
+
]);
|
|
584
|
+
expect(result.failed).toEqual([]);
|
|
585
|
+
} finally {
|
|
586
|
+
uniqueTogetherCheck.mockRestore();
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
expect(await linkCount()).toBe(1);
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
test("linkAlertsToIncident links new alerts and counts linked ones as done", async () => {
|
|
593
|
+
const incidentId: ObjectID = await seedIncident();
|
|
594
|
+
const alertId: ObjectID = await seedAlert();
|
|
595
|
+
const otherAlertId: ObjectID = await seedAlert();
|
|
596
|
+
await insertLink(incidentId, alertId);
|
|
597
|
+
|
|
598
|
+
const result: LinkAlertsToIncidentResult =
|
|
599
|
+
await IncidentAlertService.linkAlertsToIncident({
|
|
600
|
+
projectId: projectId,
|
|
601
|
+
incidentId: incidentId,
|
|
602
|
+
alertIds: [alertId, otherAlertId],
|
|
603
|
+
props: { isRoot: true },
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
expect(result.linkedAlertIds.map(String)).toEqual([
|
|
607
|
+
otherAlertId.toString(),
|
|
608
|
+
]);
|
|
609
|
+
expect(result.alreadyLinkedAlertIds.map(String)).toEqual([
|
|
610
|
+
alertId.toString(),
|
|
611
|
+
]);
|
|
612
|
+
expect(result.failed).toEqual([]);
|
|
613
|
+
expect(await linkCount()).toBe(2);
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
test("refuses a link to another project's alert", async () => {
|
|
617
|
+
const incidentId: ObjectID = await seedIncident();
|
|
618
|
+
const foreignAlertId: ObjectID = await seedAlert({
|
|
619
|
+
project: otherProjectId,
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
await expect(
|
|
623
|
+
IncidentAlertService.create({
|
|
624
|
+
data: link(incidentId, foreignAlertId),
|
|
625
|
+
props: { isRoot: true },
|
|
626
|
+
}),
|
|
627
|
+
).rejects.toThrow("belong to a different project");
|
|
628
|
+
expect(await linkCount()).toBe(0);
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
test("unlinking deletes the row and reports it on the incident's feed", async () => {
|
|
632
|
+
const incidentId: ObjectID = await seedIncident();
|
|
633
|
+
const alertId: ObjectID = await seedAlert();
|
|
634
|
+
const linkId: ObjectID = await insertLink(incidentId, alertId);
|
|
635
|
+
|
|
636
|
+
await IncidentAlertService.deleteOneById({
|
|
637
|
+
id: linkId,
|
|
638
|
+
props: { isRoot: true },
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
expect(await linkCount()).toBe(0);
|
|
642
|
+
expect(incidentFeed).toHaveBeenCalledTimes(1);
|
|
643
|
+
expect(incidentFeed.mock.calls[0]![0].incidentFeedEventType).toBe(
|
|
644
|
+
IncidentFeedEventType.AlertUnlinked,
|
|
645
|
+
);
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
test("a member only sees links whose incident and alert they can both see", async () => {
|
|
649
|
+
const publicIncidentId: ObjectID = await seedIncident();
|
|
650
|
+
const privateIncidentId: ObjectID = await seedIncident({
|
|
651
|
+
isPrivate: true,
|
|
652
|
+
});
|
|
653
|
+
const publicAlertId: ObjectID = await seedAlert();
|
|
654
|
+
const privateAlertId: ObjectID = await seedAlert({ isPrivate: true });
|
|
655
|
+
|
|
656
|
+
const visibleLinkId: ObjectID = await insertLink(
|
|
657
|
+
publicIncidentId,
|
|
658
|
+
publicAlertId,
|
|
659
|
+
);
|
|
660
|
+
await insertLink(privateIncidentId, publicAlertId);
|
|
661
|
+
await insertLink(publicIncidentId, privateAlertId);
|
|
662
|
+
|
|
663
|
+
const member: DatabaseCommonInteractionProps = memberProps();
|
|
664
|
+
|
|
665
|
+
const visible: Array<IncidentAlert> = await IncidentAlertService.findBy({
|
|
666
|
+
query: {},
|
|
667
|
+
select: { _id: true },
|
|
668
|
+
limit: 10,
|
|
669
|
+
skip: 0,
|
|
670
|
+
props: member,
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
expect(
|
|
674
|
+
visible.map((row: IncidentAlert) => {
|
|
675
|
+
return row._id?.toString();
|
|
676
|
+
}),
|
|
677
|
+
).toEqual([visibleLinkId.toString()]);
|
|
678
|
+
|
|
679
|
+
const counted: number = (
|
|
680
|
+
await IncidentAlertService.countBy({
|
|
681
|
+
query: {},
|
|
682
|
+
props: member,
|
|
683
|
+
})
|
|
684
|
+
).toNumber();
|
|
685
|
+
|
|
686
|
+
expect(counted).toBe(1);
|
|
687
|
+
|
|
688
|
+
// Root, which bypasses privacy, sees all three.
|
|
689
|
+
const all: Array<IncidentAlert> = await IncidentAlertService.findBy({
|
|
690
|
+
query: {},
|
|
691
|
+
select: { _id: true },
|
|
692
|
+
limit: 10,
|
|
693
|
+
skip: 0,
|
|
694
|
+
props: { isRoot: true },
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
expect(all).toHaveLength(3);
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
/*
|
|
701
|
+
* The queries the two dashboard pages send: an incident's Linked Alerts
|
|
702
|
+
* list ({ incidentId }) and an alert's Linked Incidents list
|
|
703
|
+
* ({ alertId }). Each carries the caller's own filter on the same column
|
|
704
|
+
* the privacy clause narrows, so the two must be ANDed, not replaced.
|
|
705
|
+
*/
|
|
706
|
+
test("each page's list shows a member only the links whose other end they can see", async () => {
|
|
707
|
+
const publicIncidentId: ObjectID = await seedIncident();
|
|
708
|
+
const privateIncidentId: ObjectID = await seedIncident({
|
|
709
|
+
isPrivate: true,
|
|
710
|
+
});
|
|
711
|
+
const otherIncidentId: ObjectID = await seedIncident();
|
|
712
|
+
const publicAlertId: ObjectID = await seedAlert();
|
|
713
|
+
const privateAlertId: ObjectID = await seedAlert({ isPrivate: true });
|
|
714
|
+
const otherAlertId: ObjectID = await seedAlert();
|
|
715
|
+
|
|
716
|
+
const visibleLinkId: ObjectID = await insertLink(
|
|
717
|
+
publicIncidentId,
|
|
718
|
+
publicAlertId,
|
|
719
|
+
);
|
|
720
|
+
await insertLink(publicIncidentId, privateAlertId);
|
|
721
|
+
await insertLink(privateIncidentId, publicAlertId);
|
|
722
|
+
// Links of other records, which neither page may show.
|
|
723
|
+
await insertLink(otherIncidentId, otherAlertId);
|
|
724
|
+
|
|
725
|
+
const member: DatabaseCommonInteractionProps = memberProps();
|
|
726
|
+
|
|
727
|
+
async function listed(
|
|
728
|
+
query: Record<string, ObjectID>,
|
|
729
|
+
props: DatabaseCommonInteractionProps,
|
|
730
|
+
): Promise<Array<string>> {
|
|
731
|
+
const rows: Array<IncidentAlert> = await IncidentAlertService.findBy({
|
|
732
|
+
query: { ...query, projectId: projectId },
|
|
733
|
+
select: { _id: true },
|
|
734
|
+
limit: 10,
|
|
735
|
+
skip: 0,
|
|
736
|
+
props: props,
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
return rows.map((row: IncidentAlert) => {
|
|
740
|
+
return row._id!.toString();
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
async function counted(
|
|
745
|
+
query: Record<string, ObjectID>,
|
|
746
|
+
props: DatabaseCommonInteractionProps,
|
|
747
|
+
): Promise<number> {
|
|
748
|
+
return (
|
|
749
|
+
await IncidentAlertService.countBy({
|
|
750
|
+
query: { ...query, projectId: projectId },
|
|
751
|
+
props: props,
|
|
752
|
+
})
|
|
753
|
+
).toNumber();
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// The incident's Linked Alerts: the private alert's link is hidden.
|
|
757
|
+
expect(await listed({ incidentId: publicIncidentId }, member)).toEqual([
|
|
758
|
+
visibleLinkId.toString(),
|
|
759
|
+
]);
|
|
760
|
+
expect(await counted({ incidentId: publicIncidentId }, member)).toBe(1);
|
|
761
|
+
|
|
762
|
+
// The alert's Linked Incidents: the private incident's link is hidden.
|
|
763
|
+
expect(await listed({ alertId: publicAlertId }, member)).toEqual([
|
|
764
|
+
visibleLinkId.toString(),
|
|
765
|
+
]);
|
|
766
|
+
expect(await counted({ alertId: publicAlertId }, member)).toBe(1);
|
|
767
|
+
|
|
768
|
+
// A private end's own page shows the member nothing.
|
|
769
|
+
expect(await listed({ incidentId: privateIncidentId }, member)).toEqual(
|
|
770
|
+
[],
|
|
771
|
+
);
|
|
772
|
+
expect(await listed({ alertId: privateAlertId }, member)).toEqual([]);
|
|
773
|
+
|
|
774
|
+
// Root sees both links on each page.
|
|
775
|
+
expect(
|
|
776
|
+
await counted({ incidentId: publicIncidentId }, { isRoot: true }),
|
|
777
|
+
).toBe(2);
|
|
778
|
+
expect(await counted({ alertId: publicAlertId }, { isRoot: true })).toBe(
|
|
779
|
+
2,
|
|
780
|
+
);
|
|
781
|
+
});
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
describe("a project member linking through the service", () => {
|
|
785
|
+
function link(incidentId: ObjectID, alertId: ObjectID): IncidentAlert {
|
|
786
|
+
const row: IncidentAlert = new IncidentAlert();
|
|
787
|
+
row.incidentId = incidentId;
|
|
788
|
+
row.alertId = alertId;
|
|
789
|
+
return row;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
test("a member links a pair they can see, and is recorded as the one who linked it", async () => {
|
|
793
|
+
const userId: ObjectID = await seedUser();
|
|
794
|
+
const incidentId: ObjectID = await seedIncident();
|
|
795
|
+
const alertId: ObjectID = await seedAlert();
|
|
796
|
+
|
|
797
|
+
await IncidentAlertService.create({
|
|
798
|
+
data: link(incidentId, alertId),
|
|
799
|
+
props: memberProps(userId),
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
const rows: Array<{
|
|
803
|
+
projectId: string;
|
|
804
|
+
incidentId: string;
|
|
805
|
+
alertId: string;
|
|
806
|
+
createdByUserId: string | null;
|
|
807
|
+
}> = await database.query(
|
|
808
|
+
`SELECT "projectId", "incidentId", "alertId", "createdByUserId" FROM "${schema}"."IncidentAlert"`,
|
|
809
|
+
);
|
|
810
|
+
|
|
811
|
+
expect(rows).toEqual([
|
|
812
|
+
{
|
|
813
|
+
projectId: projectId.toString(),
|
|
814
|
+
incidentId: incidentId.toString(),
|
|
815
|
+
alertId: alertId.toString(),
|
|
816
|
+
createdByUserId: userId.toString(),
|
|
817
|
+
},
|
|
818
|
+
]);
|
|
819
|
+
|
|
820
|
+
// The incident's entry names the member.
|
|
821
|
+
expect(incidentFeed).toHaveBeenCalledTimes(1);
|
|
822
|
+
expect(String(incidentFeed.mock.calls[0]![0].userId)).toBe(
|
|
823
|
+
userId.toString(),
|
|
824
|
+
);
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
test("a member linking the same pair twice is told it is already linked", async () => {
|
|
828
|
+
const userId: ObjectID = await seedUser();
|
|
829
|
+
const incidentId: ObjectID = await seedIncident();
|
|
830
|
+
const alertId: ObjectID = await seedAlert();
|
|
831
|
+
|
|
832
|
+
await IncidentAlertService.create({
|
|
833
|
+
data: link(incidentId, alertId),
|
|
834
|
+
props: memberProps(userId),
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
const duplicate: unknown = await failureOf(() => {
|
|
838
|
+
return IncidentAlertService.create({
|
|
839
|
+
data: link(incidentId, alertId),
|
|
840
|
+
props: memberProps(userId),
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
expect((duplicate as Error).message).toBe(
|
|
845
|
+
INCIDENT_ALERT_ALREADY_LINKED_MESSAGE,
|
|
846
|
+
);
|
|
847
|
+
expect(await linkCount()).toBe(1);
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
test("a member cannot link a private alert they do not own", async () => {
|
|
851
|
+
const userId: ObjectID = await seedUser();
|
|
852
|
+
const incidentId: ObjectID = await seedIncident();
|
|
853
|
+
const privateAlertId: ObjectID = await seedAlert({ isPrivate: true });
|
|
854
|
+
|
|
855
|
+
await expect(
|
|
856
|
+
IncidentAlertService.create({
|
|
857
|
+
data: link(incidentId, privateAlertId),
|
|
858
|
+
props: memberProps(userId),
|
|
859
|
+
}),
|
|
860
|
+
).rejects.toThrow(
|
|
861
|
+
"The alert to link does not exist in this project, or you do not have access to it.",
|
|
862
|
+
);
|
|
863
|
+
expect(await linkCount()).toBe(0);
|
|
864
|
+
expect(incidentFeed).not.toHaveBeenCalled();
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
test("a member cannot link to a private incident they do not own", async () => {
|
|
868
|
+
const userId: ObjectID = await seedUser();
|
|
869
|
+
const privateIncidentId: ObjectID = await seedIncident({
|
|
870
|
+
isPrivate: true,
|
|
871
|
+
});
|
|
872
|
+
const alertId: ObjectID = await seedAlert();
|
|
873
|
+
|
|
874
|
+
await expect(
|
|
875
|
+
IncidentAlertService.create({
|
|
876
|
+
data: link(privateIncidentId, alertId),
|
|
877
|
+
props: memberProps(userId),
|
|
878
|
+
}),
|
|
879
|
+
).rejects.toThrow(
|
|
880
|
+
"The incident to link does not exist in this project, or you do not have access to it.",
|
|
881
|
+
);
|
|
882
|
+
expect(await linkCount()).toBe(0);
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
test("a member cannot link another project's alert, and is not told it exists", async () => {
|
|
886
|
+
const userId: ObjectID = await seedUser();
|
|
887
|
+
const incidentId: ObjectID = await seedIncident();
|
|
888
|
+
const foreignAlertId: ObjectID = await seedAlert({
|
|
889
|
+
project: otherProjectId,
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
await expect(
|
|
893
|
+
IncidentAlertService.create({
|
|
894
|
+
data: link(incidentId, foreignAlertId),
|
|
895
|
+
props: memberProps(userId),
|
|
896
|
+
}),
|
|
897
|
+
).rejects.toThrow(
|
|
898
|
+
"The alert to link does not exist in this project, or you do not have access to it.",
|
|
899
|
+
);
|
|
900
|
+
expect(await linkCount()).toBe(0);
|
|
901
|
+
});
|
|
902
|
+
});
|
|
903
|
+
});
|