@oneuptime/common 13.0.5 → 13.0.6
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/AnalyticsModels/AuditLog.ts +81 -1
- package/Models/AnalyticsModels/SecurityEvent.ts +4 -4
- package/Models/DatabaseModels/Alert.ts +62 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/Incident.ts +66 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +74 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +74 -0
- package/Models/DatabaseModels/Index.ts +6 -4
- package/Models/DatabaseModels/NetworkDevice.ts +67 -0
- package/Models/DatabaseModels/NetworkDeviceDiagnostic.ts +746 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +151 -0
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +1 -1
- package/Models/DatabaseModels/Project.ts +41 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +74 -0
- package/Models/DatabaseModels/SecurityEventConnection.ts +11 -11
- package/Models/DatabaseModels/ServiceLevelObjective.ts +185 -8
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +746 -43
- package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +575 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +582 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +16 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +16 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +75 -0
- package/Models/DatabaseModels/ThreatIntelFeed.ts +1 -1
- package/Server/API/BaseAPI.ts +17 -0
- package/Server/API/BillingInvoiceAPI.ts +343 -30
- package/Server/API/BillingPaymentMethodAPI.ts +126 -5
- package/Server/API/DashboardAPI.ts +96 -2
- package/Server/API/SecurityEventConnectionAPI.ts +141 -11
- package/Server/API/StatusPageAPI.ts +308 -199
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.ts +83 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.ts +36 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.ts +516 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.ts +98 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.ts +97 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
- package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +138 -67
- package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +213 -84
- package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +112 -35
- package/Server/Services/AlertLabelRuleEngineService.ts +299 -217
- package/Server/Services/AlertOwnerRuleEngineService.ts +572 -396
- package/Server/Services/AlertPrivacyRuleEngineService.ts +116 -40
- package/Server/Services/AlertService.ts +111 -4
- package/Server/Services/AuditLogService.ts +612 -59
- package/Server/Services/BillingInvoiceService.ts +112 -102
- package/Server/Services/BillingService.ts +539 -11
- package/Server/Services/CephClusterLabelRuleEngineService.ts +170 -109
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +233 -115
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +163 -100
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +236 -115
- package/Server/Services/DashboardLabelRuleEngineService.ts +145 -84
- package/Server/Services/DashboardOwnerRuleEngineService.ts +213 -95
- package/Server/Services/DatabaseService.ts +171 -21
- package/Server/Services/DockerHostLabelRuleEngineService.ts +171 -110
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +233 -115
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +181 -112
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +243 -118
- package/Server/Services/HostLabelRuleEngineService.ts +167 -106
- package/Server/Services/HostOwnerRuleEngineService.ts +229 -111
- package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +141 -67
- package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +272 -72
- package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +112 -35
- package/Server/Services/IncidentEpisodePublicNoteService.ts +24 -0
- package/Server/Services/IncidentLabelRuleEngineService.ts +279 -204
- package/Server/Services/IncidentOwnerRuleEngineService.ts +595 -425
- package/Server/Services/IncidentPrivacyRuleEngineService.ts +117 -44
- package/Server/Services/IncidentPublicNoteService.ts +24 -0
- package/Server/Services/IncidentService.ts +114 -3
- package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +147 -83
- package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +221 -100
- package/Server/Services/Index.ts +6 -4
- package/Server/Services/IoTFleetLabelRuleEngineService.ts +145 -84
- package/Server/Services/IoTFleetOwnerRuleEngineService.ts +213 -95
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +181 -112
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +243 -118
- package/Server/Services/LabelService.ts +23 -28
- package/Server/Services/MonitorLabelRuleEngineService.ts +152 -92
- package/Server/Services/MonitorOwnerRuleEngineService.ts +220 -104
- package/Server/Services/MonitorProbeService.ts +20 -2
- package/Server/Services/MonitorService.ts +11 -9
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +376 -5
- package/Server/Services/NetworkDeviceDiagnosticService.ts +417 -0
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +147 -83
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +218 -97
- package/Server/Services/NetworkDeviceService.ts +39 -2
- package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +151 -80
- package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +222 -97
- package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +154 -83
- package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +225 -100
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +171 -110
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +235 -115
- package/Server/Services/ProjectService.ts +111 -10
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +174 -110
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +239 -116
- package/Server/Services/RumApplicationLabelRuleEngineService.ts +137 -73
- package/Server/Services/RumApplicationOwnerRuleEngineService.ts +200 -83
- package/Server/Services/RunbookLabelRuleEngineService.ts +146 -84
- package/Server/Services/RunbookOwnerRuleEngineService.ts +216 -95
- package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +324 -230
- package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +613 -428
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +24 -0
- package/Server/Services/ScheduledMaintenanceService.ts +43 -14
- package/Server/Services/SecurityEventConnectionService.ts +56 -4
- package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +143 -74
- package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +206 -85
- package/Server/Services/ServiceLabelRuleEngineService.ts +172 -110
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +1057 -18
- package/Server/Services/ServiceLevelObjectiveFeedService.ts +108 -0
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +793 -97
- package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +1069 -0
- package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +240 -1
- package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +257 -1
- package/Server/Services/ServiceLevelObjectiveService.ts +1356 -56
- package/Server/Services/ServiceOwnerRuleEngineService.ts +238 -116
- package/Server/Services/StatusPageAnnouncementService.ts +13 -0
- package/Server/Services/StatusPageLabelRuleEngineService.ts +146 -85
- package/Server/Services/StatusPageOwnerRuleEngineService.ts +210 -99
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +28 -232
- package/Server/Services/StatusPageSubscriberService.ts +6 -0
- package/Server/Services/TelemetryUsageBillingService.ts +38 -7
- package/Server/Services/ThreatIntelFeedService.ts +1 -1
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +173 -110
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +238 -116
- package/Server/Services/WorkflowLabelRuleEngineService.ts +145 -84
- package/Server/Services/WorkflowOwnerRuleEngineService.ts +215 -95
- package/Server/Types/Database/UpdateByID.ts +3 -0
- package/Server/Types/Database/UpdateOneBy.ts +7 -0
- package/Server/Utils/AI/AlertAIContextBuilder.ts +19 -0
- package/Server/Utils/AI/IncidentAIContextBuilder.ts +39 -0
- package/Server/Utils/AI/Toolbox/AlertTools.ts +37 -1
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +22 -1
- package/Server/Utils/AI/Toolbox/SloTools.ts +416 -51
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +151 -13
- package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +17 -4
- package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +155 -8
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +16 -0
- package/Server/Utils/Database/RelationValueUtil.ts +106 -0
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +6 -1
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +22 -27
- package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +3 -1
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +50 -20
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +13 -1
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +6 -11
- package/Server/Utils/Rules/MonitorRulePatternValidator.ts +51 -0
- package/Server/Utils/Rules/OwnerRuleAssignment.ts +110 -0
- package/Server/Utils/Rules/RuleRun/RuleApplication.ts +81 -0
- package/Server/Utils/Rules/RuleRun/RuleRunPermission.ts +188 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +803 -0
- package/Server/Utils/Rules/RuleRun/RuleRunner.ts +341 -0
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +3 -2
- package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +6 -4
- package/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.ts +263 -16
- package/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.ts +2101 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +194 -14
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +1 -2
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +38 -7
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +2 -0
- package/Server/Utils/SecurityEvent/Connectors/Types.ts +242 -2
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +1 -1
- package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +3 -3
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +2 -2
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +217 -56
- package/Server/Utils/Slo/SloFeedUtil.ts +200 -0
- package/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.ts +173 -0
- package/Server/Utils/Slo/SloMetricUtil.ts +327 -0
- package/Server/Utils/Slo/SloOwnerReferenceValidator.ts +208 -0
- package/Server/Utils/Slo/SloRecordReferenceValidator.ts +169 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +6 -43
- package/Server/Utils/StatusPageResource.ts +50 -5
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +664 -15
- package/Tests/App/Dashboard/AddWidgetModal.test.tsx +4 -1
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +307 -0
- package/Tests/App/Dashboard/ArchiveResourceCard.test.tsx +289 -0
- package/Tests/App/Dashboard/AuditLogsTable.test.tsx +598 -0
- package/Tests/App/Dashboard/BillingDefaultPaymentMethod.test.tsx +1046 -0
- package/Tests/App/Dashboard/BillingPaidUsageFlow.test.tsx +3 -0
- package/Tests/App/Dashboard/BillingPaymentMethodForm.test.tsx +201 -7
- package/Tests/App/Dashboard/BooleanSeriesCriteriaFilterText.test.ts +82 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +16 -1
- package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +116 -8
- package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +168 -1
- package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +1 -1
- package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +20 -3
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +1095 -1
- package/Tests/App/Dashboard/CorrelateFilterChips.test.tsx +910 -0
- package/Tests/App/Dashboard/CorrelateGraph.test.tsx +3747 -25
- package/Tests/App/Dashboard/CorrelateGraphHelpers.test.ts +1085 -0
- package/Tests/App/Dashboard/CorrelateInspector.test.tsx +1534 -0
- package/Tests/App/Dashboard/CorrelateNodeCard.test.tsx +965 -0
- package/Tests/App/Dashboard/CorrelateResultSummary.test.tsx +1525 -0
- package/Tests/App/Dashboard/CorrelationGraph.test.ts +1030 -0
- package/Tests/App/Dashboard/CorrelationGraphLayout.test.ts +526 -0
- package/Tests/App/Dashboard/DeviceDiagnostics.test.tsx +787 -0
- package/Tests/App/Dashboard/DeviceLatencyTrend.test.tsx +278 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +279 -0
- package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +87 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +443 -8
- package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +340 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +98 -2
- package/Tests/App/Dashboard/ExceptionSegmentedControl.test.tsx +1020 -0
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +268 -47
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1114 -76
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +124 -2
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +279 -176
- package/Tests/App/Dashboard/InvestigationRunDetails.test.tsx +1166 -0
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +437 -0
- package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +65 -0
- package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +5 -0
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +74 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +125 -5
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +1764 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1000 -64
- package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +448 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +739 -189
- package/Tests/App/Dashboard/SecurityEventSeverityPill.test.tsx +233 -0
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +282 -0
- package/Tests/App/Dashboard/SloActiveBurnEventsCard.test.tsx +538 -0
- package/Tests/App/Dashboard/SloBulkActionsArchive.test.tsx +252 -0
- package/Tests/App/Dashboard/SloDashboardTemplateWidgets.test.tsx +322 -518
- package/Tests/App/Dashboard/SloElement.test.tsx +194 -0
- package/Tests/App/Dashboard/SloFeed.test.tsx +289 -0
- package/Tests/App/Dashboard/SloHistoryCharts.test.tsx +471 -0
- package/Tests/App/Dashboard/SloHistorySeries.test.tsx +607 -0
- package/Tests/App/Dashboard/SloListWidget.test.tsx +783 -0
- package/Tests/App/Dashboard/SloMetricsPage.test.tsx +346 -0
- package/Tests/App/Dashboard/SloMonitorsPage.test.tsx +661 -0
- package/Tests/App/Dashboard/SloMonitorsSummaryCard.test.tsx +489 -0
- package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +437 -0
- package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +305 -0
- package/Tests/App/Dashboard/SloOverviewData.test.tsx +563 -0
- package/Tests/App/Dashboard/SloOverviewHero.test.tsx +311 -0
- package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +426 -0
- package/Tests/App/Dashboard/SloOverviewSidebarCards.test.tsx +493 -0
- package/Tests/App/Dashboard/SloSettings.test.tsx +633 -0
- package/Tests/App/Dashboard/SloStatusSummaryCards.test.tsx +403 -0
- package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +373 -0
- package/Tests/App/Dashboard/SloWidgetVariableBinding.test.tsx +689 -0
- package/Tests/App/Dashboard/TopologyConnectivitySection.test.tsx +206 -0
- package/Tests/App/Dashboard/TracesEntityNames.test.tsx +47 -15
- package/Tests/App/Dashboard/UseBulkShortenDeviceNames.test.tsx +1312 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +9 -1
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +14 -16
- package/Tests/Models/DatabaseModels/AuditLogModelConfiguration.test.ts +442 -0
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +9 -10
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +48 -1
- package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +835 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +3 -2
- package/Tests/Models/DiscoveryScanNetbiosLookupColumn.test.ts +328 -0
- package/Tests/Models/DiscoveryScanShortDeviceNamesColumn.test.ts +335 -0
- package/Tests/Models/NetworkDeviceDiagnosticContract.test.ts +194 -0
- package/Tests/Models/NetworkDeviceDnsNameColumn.test.ts +321 -0
- package/Tests/Models/ProjectDataResidencyColumn.test.ts +154 -0
- package/Tests/Models/SecurityDomainAccessControl.test.ts +181 -50
- package/Tests/Server/API/BaseAPI.test.ts +6 -0
- package/Tests/Server/API/BaseAPIUpdateMiscDataProps.test.ts +217 -0
- package/Tests/Server/API/BillingInvoiceAPI.test.ts +7 -0
- package/Tests/Server/API/BillingInvoiceAPIPaymentStates.test.ts +990 -0
- package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +498 -0
- package/Tests/Server/API/DashboardPublicSloAPI.test.ts +405 -0
- package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +901 -7
- package/Tests/Server/API/SessionReplayAPI.test.ts +116 -0
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +857 -0
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +1084 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +33 -3
- package/Tests/Server/Infrastructure/Postgres/AddDataResidencyToProjectMigration.test.ts +202 -0
- package/Tests/Server/Infrastructure/Postgres/AddNetbiosLookupToNetworkDeviceDiscoveryScanMigration.test.ts +330 -0
- package/Tests/Server/Infrastructure/Postgres/AddNetworkDeviceDnsNameAndShortDeviceNamesMigration.test.ts +340 -0
- package/Tests/Server/Infrastructure/Postgres/BackfillSloMonitorRulesAndAffectedResourcesMigration.test.ts +343 -0
- package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +801 -0
- package/Tests/Server/Services/AddSubscriberUpdateNotificationStatusMigration.test.ts +307 -0
- package/Tests/Server/Services/AuditLogService.test.ts +1124 -0
- package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +200 -1
- package/Tests/Server/Services/BillingInvoiceServiceMutexRelease.test.ts +254 -0
- package/Tests/Server/Services/BillingService.test.ts +70 -0
- package/Tests/Server/Services/BillingServicePayInvoiceStates.test.ts +723 -0
- package/Tests/Server/Services/BillingServicePaymentMethodReads.test.ts +14 -2
- package/Tests/Server/Services/BillingServiceSubscriptionPaymentMethodSync.test.ts +1634 -0
- package/Tests/Server/Services/DatabaseServiceAuditRelationDiff.test.ts +492 -0
- package/Tests/Server/Services/DatabaseServicePasswordFieldSecrets.test.ts +629 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +431 -0
- package/Tests/Server/Services/IncidentAlertSloReferenceGuard.test.ts +358 -0
- package/Tests/Server/Services/MonitorProbeServicePastDueMonitoring.test.ts +362 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +1460 -1
- package/Tests/Server/Services/NetworkDeviceDiagnosticService.test.ts +962 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +106 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +10 -1
- package/Tests/Server/Services/NetworkDeviceServicePastDueMonitoring.test.ts +335 -0
- package/Tests/Server/Services/NetworkDeviceSiteRuleDnsName.test.ts +568 -0
- package/Tests/Server/Services/ProjectDataResidencyPostgres.test.ts +344 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +187 -0
- package/Tests/Server/Services/ProjectServiceDataResidency.test.ts +369 -0
- package/Tests/Server/Services/ProjectServiceDataResidencySelfHosted.test.ts +176 -0
- package/Tests/Server/Services/ProjectServicePastDueMonitoring.test.ts +289 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +24 -8
- package/Tests/Server/Services/RuleRun/IncidentAlertMaintenanceRuleEnginesRun.test.ts +1396 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupARun.test.ts +917 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +1262 -0
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +902 -0
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +1163 -0
- package/Tests/Server/Services/RuleRun/PrivacyRuleEnginesRun.test.ts +843 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +465 -0
- package/Tests/Server/Services/SecurityEventConnectionService.test.ts +525 -4
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +77 -23
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleFeedWrites.test.ts +777 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleOptions.test.ts +1399 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +67 -74
- package/Tests/Server/Services/ServiceLevelObjectiveChildRowTenancy.test.ts +906 -0
- package/Tests/Server/Services/ServiceLevelObjectiveDeleteTenancy.test.ts +1029 -0
- package/Tests/Server/Services/ServiceLevelObjectiveFeedService.test.ts +313 -0
- package/Tests/Server/Services/ServiceLevelObjectiveFeedWrites.test.ts +1214 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMarkdownLink.test.ts +289 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +1455 -430
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleLegacyLabelAdoption.test.ts +634 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +1193 -0
- package/Tests/Server/Services/{SloMonitorLabelRuleHooks.test.ts → ServiceLevelObjectiveMonitorRuleTriggers.test.ts} +135 -41
- package/Tests/Server/Services/ServiceLevelObjectiveOwnerFeedWrites.test.ts +671 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +180 -85
- package/Tests/Server/Services/ServiceLevelObjectiveServiceArchive.test.ts +537 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceLegacyMonitorLabelWrite.test.ts +870 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceMonitorRuleGuard.test.ts +343 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceReEvaluation.test.ts +246 -0
- package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +501 -0
- package/Tests/Server/Services/SloAffectedResourceLinkContract.test.ts +86 -0
- package/Tests/Server/Services/SloAffectedResourceMetricAttributes.test.ts +547 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +10 -4
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +7 -2
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +174 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateServiceVariables.test.ts +40 -0
- package/Tests/Server/Services/SubscriberUpdateNotificationHooks.test.ts +541 -0
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +288 -0
- package/Tests/Server/TestingUtils/PastDueMonitoringClaimSql.ts +177 -0
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +51 -10
- package/Tests/Server/TestingUtils/__mocks__/Stripe.mock.ts +16 -1
- package/Tests/Server/Types/Database/Permissions/ProjectDataResidencyColumn.test.ts +386 -0
- package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +26 -36
- package/Tests/Server/Utils/AI/SloAffectedResourceAIContext.test.ts +445 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +423 -1
- package/Tests/Server/Utils/AI/SloToolsArchive.test.ts +294 -0
- package/Tests/Server/Utils/AI/SloToolsRuleReadPermissions.test.ts +297 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +255 -10
- package/Tests/Server/Utils/Dashboard/SloTemplatePublicDashboard.test.ts +404 -750
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +45 -0
- package/Tests/Server/Utils/Database/RelationValueUtil.test.ts +157 -0
- package/Tests/Server/Utils/Monitor/Criteria/BooleanSeriesEvaluateOverTime.test.ts +260 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +181 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +147 -30
- package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.test.ts +17 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +136 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidatorLoadOrder.test.ts +472 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +48 -2
- package/Tests/Server/Utils/Monitor/SloTemplateMetricEmitterContract.test.ts +435 -475
- package/Tests/Server/Utils/Rules/MonitorRulePatternValidator.test.ts +77 -0
- package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +177 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +365 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunRegistry.test.ts +173 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunner.test.ts +675 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +8 -8
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorFetchSummary.test.ts +261 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +68 -13
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsAuth.test.ts → Connectors/GoogleSecOps/GoogleSecOpsAuth.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClient.test.ts → Connectors/GoogleSecOps/GoogleSecOpsClient.test.ts} +4 -4
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.test.ts +483 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorCuratedAndLateAlerts.test.ts +676 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFetchEvents.test.ts +1994 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFixtures.ts +332 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorHttpIntegration.test.ts +680 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorRequestContract.test.ts +1206 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorTestConnection.test.ts +1136 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsCuratedRuleCounts.test.ts +407 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsErrorHandling.test.ts → Connectors/GoogleSecOps/GoogleSecOpsErrorHandling.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingAdaptiveCatchUp.test.ts +730 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClickhouseIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingClickhouseIntegration.test.ts} +130 -35
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFailureTaxonomy.test.ts +772 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFixtures.ts +648 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsHttpIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingHttpIntegration.test.ts} +230 -225
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingIntegration.test.ts +1390 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingLoop.test.ts +981 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingNothingImportedRegression.test.ts +290 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsRequestContract.test.ts → Connectors/GoogleSecOps/GoogleSecOpsRequestContract.test.ts} +2 -2
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsResponseParsing.test.ts → Connectors/GoogleSecOps/GoogleSecOpsResponseParsing.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsSearchDetections.test.ts → Connectors/GoogleSecOps/GoogleSecOpsSearchDetections.test.ts} +38 -5
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsTesterIntegration.test.ts +421 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +1445 -3
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +14 -4
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +313 -4
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +352 -0
- package/Tests/Server/Utils/Slo/SloFeedUtil.test.ts +326 -0
- package/Tests/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.test.ts +260 -0
- package/Tests/Server/Utils/Slo/SloMetricUtil.test.ts +592 -0
- package/Tests/Server/Utils/Slo/SloRecordReferenceValidator.test.ts +311 -0
- package/Tests/Server/Utils/StatusPageResource.test.ts +91 -3
- package/Tests/Types/Billing/SubscriptionStatus.test.ts +176 -0
- package/Tests/Types/Billing/SubscriptionStatusPastDueMonitoring.test.ts +187 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +53 -7
- package/Tests/Types/Dashboard/SloDashboardTemplate.test.ts +816 -792
- package/Tests/Types/Monitor/CriteriaFilter.test.ts +216 -24
- package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepRetriesParsing.test.ts +201 -0
- package/Tests/Types/Rules/RuleRun.test.ts +315 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +60 -0
- package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +29 -4
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +217 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +200 -0
- package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +141 -87
- package/Tests/UI/Components/AlertBanner.test.tsx +319 -0
- package/Tests/UI/Components/BulkArchiveActionsCopy.test.tsx +310 -0
- package/Tests/UI/Components/Detail/DetailIdIsUnique.test.tsx +87 -0
- package/Tests/UI/Components/Dropdown/DropdownClearable.test.tsx +393 -0
- package/Tests/UI/Components/Dropdown/DropdownMultiSelectChipAccessibleName.test.tsx +64 -0
- package/Tests/UI/Components/EmptyState/EmptyState.test.tsx +335 -4
- package/Tests/UI/Components/EmptyState/EmptyStateGuideLinks.test.tsx +337 -0
- package/Tests/UI/Components/Forms/ModelFormJsonColumns.test.tsx +21 -20
- package/Tests/UI/Components/LabelRuleImportExport.test.tsx +15 -2
- package/Tests/UI/Components/LockedFilterChip.test.tsx +281 -144
- package/Tests/UI/Components/MoreMenu.test.tsx +133 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +84 -3
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/RuleRun/RuleDetailFields.test.tsx +336 -0
- package/Tests/UI/Components/RuleRun/RuleTable.test.tsx +304 -0
- package/Tests/UI/Components/RuleRun/RunRuleNowModal.test.tsx +231 -0
- package/Tests/UI/Components/RuleRun/RunRulesBulkAction.test.ts +213 -0
- package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +124 -61
- package/Tests/UI/Rum/ReplayEngine.test.ts +154 -0
- package/Tests/UI/Rum/ReplayHeader.test.tsx +234 -123
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +122 -0
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +245 -0
- package/Tests/UI/Rum/ReplayRail.test.tsx +294 -0
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +213 -1
- package/Tests/UI/Rum/ReplayStage.test.tsx +565 -172
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +260 -3
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +1391 -0
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +222 -0
- package/Tests/UI/Utils/DashboardStackingLayers.test.ts +8 -1
- package/Tests/UI/Utils/RuleRunClient.test.ts +303 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +1 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentDefaults.test.ts +2 -0
- package/Tests/Utils/Dashboard/Components/DashboardSloListComponent.test.ts +206 -0
- package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +36 -2
- package/Tests/Utils/Dashboard/SloTemplateVariableScoping.test.ts +409 -588
- package/Tests/Utils/Dashboard/SloWidgetSource.test.ts +351 -0
- package/Tests/Utils/Markdown/MarkdownEscape.test.ts +361 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +1425 -118
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +188 -3
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +661 -13
- package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +349 -0
- package/Tests/Utils/NetworkDiscovery/RunImportedDeviceNaming.test.ts +656 -0
- package/Tests/Utils/NetworkDiscovery/ShortDeviceNamePlanner.test.ts +1020 -0
- package/Tests/Utils/NetworkDiscovery/ShortHostnameUtil.test.ts +619 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +317 -0
- package/Tests/Utils/Project/DataResidency.test.ts +198 -0
- package/Tests/Utils/Rules/RuleRunSummary.test.ts +394 -0
- package/Tests/Utils/Slo/SloAffectedResourceMarkdown.test.ts +302 -0
- package/Tests/Utils/Slo/SloBurnRateTemplate.test.ts +468 -0
- package/Tests/Utils/Slo/SloEvaluation.test.ts +20 -4
- package/Tests/Utils/Slo/SloFeedMarkdown.test.ts +1185 -0
- package/Tests/Utils/Slo/SloHealth.test.ts +262 -0
- package/Tests/Utils/Slo/SloHistoryMetricName.test.ts +102 -0
- package/Tests/Utils/Slo/SloListWidgetFormat.test.ts +522 -0
- package/Tests/Utils/Slo/SloMetricType.test.ts +355 -0
- package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +387 -0
- package/Tests/Utils/Slo/SloMonitorStatusSummary.test.ts +210 -0
- package/Tests/Utils/Slo/SloOverviewText.test.ts +226 -0
- package/Tests/Utils/Slo/SloProjection.test.ts +1039 -0
- package/Tests/Utils/Slo/SloWidgetFormat.test.ts +47 -0
- package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +1 -80
- package/Types/BaseDatabase/EnableAuditLogOn.ts +41 -0
- package/Types/Billing/SubscriptionStatus.ts +39 -4
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +5 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +10 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloListComponent.ts +29 -0
- package/Types/Dashboard/DashboardTemplates.ts +290 -297
- package/Types/Database/EnableAuditLog.ts +23 -1
- package/Types/Email/EmailTemplateType.ts +4 -0
- package/Types/Monitor/CriteriaFilter.ts +55 -8
- package/Types/Monitor/MonitorStep.ts +5 -2
- package/Types/Monitor/MonitorStepDnsMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepDnssecMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepDomainMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepExternalStatusPageMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepRetries.ts +59 -0
- package/Types/Monitor/MonitorStepSnmpMonitor.ts +9 -2
- package/Types/NetworkDevice/NetworkDeviceDiagnosticResult.ts +104 -0
- package/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.ts +47 -0
- package/Types/NetworkDevice/NetworkDeviceDiagnosticType.ts +47 -0
- package/Types/NetworkDevice/NetworkDevicePingMetricNames.ts +20 -0
- package/Types/Permission.ts +127 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +5 -0
- package/Types/Rules/RuleRun.ts +518 -0
- package/Types/Rum/SessionReplayApi.ts +18 -0
- package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +6 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +30 -4
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +108 -1
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +6 -2
- package/Types/ServiceLevelObjective/SloHistoryMetricName.ts +25 -0
- package/Types/ServiceLevelObjective/SloMetricType.ts +49 -0
- package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +4 -0
- package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +331 -0
- package/Types/StatusPage/SubscriberNotificationTrigger.ts +12 -0
- package/Types/StatusPage/SubscriberUpdateNotification.ts +89 -0
- package/Types/Telemetry/LockedFilterDetail.ts +7 -28
- package/Types/Telemetry/ServiceType.ts +7 -0
- package/Typings/Index.d.ts +53 -3
- package/UI/Components/AlertBanner/AlertBanner.tsx +85 -27
- package/UI/Components/BulkUpdate/BulkArchiveActions.tsx +21 -2
- package/UI/Components/Detail/Detail.tsx +9 -2
- package/UI/Components/Dropdown/Dropdown.tsx +64 -1
- package/UI/Components/EmptyState/EmptyState.tsx +27 -3
- package/UI/Components/EmptyState/EmptyStateGuideLinks.tsx +124 -0
- package/UI/Components/Forms/ModelForm.tsx +6 -5
- package/UI/Components/LabelRule/LabelRuleTable.tsx +8 -2
- package/UI/Components/LogsViewer/LogsViewer.tsx +2 -6
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +2 -13
- package/UI/Components/LogsViewer/types.ts +2 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +14 -3
- package/UI/Components/RuleRun/RuleDetailFields.tsx +359 -0
- package/UI/Components/RuleRun/RuleTable.tsx +183 -0
- package/UI/Components/RuleRun/RuleView.tsx +170 -0
- package/UI/Components/RuleRun/RunRuleNowModal.tsx +147 -0
- package/UI/Components/RuleRun/RunRulesBulkAction.ts +103 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +2 -6
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +38 -104
- package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +2 -18
- package/UI/Components/TelemetryViewer/types.ts +2 -2
- package/UI/Utils/Rules/RuleRunClient.ts +178 -0
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +8 -0
- package/Utils/Dashboard/Components/DashboardSloComponent.ts +19 -2
- package/Utils/Dashboard/Components/DashboardSloListComponent.ts +126 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/Dashboard/SloWidgetSource.ts +188 -0
- package/Utils/Markdown/MarkdownEscape.ts +63 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +161 -36
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +25 -0
- package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +146 -0
- package/Utils/NetworkDiscovery/RunImportedDeviceNaming.ts +390 -0
- package/Utils/NetworkDiscovery/ShortDeviceNamePlanner.ts +291 -0
- package/Utils/NetworkDiscovery/ShortHostnameUtil.ts +91 -0
- package/Utils/NetworkSite/CidrMatchUtil.ts +37 -12
- package/Utils/Project/DataResidency.ts +63 -0
- package/Utils/Rules/RuleRunSummary.ts +323 -0
- package/Utils/Slo/SloAffectedResourceMarkdown.ts +123 -0
- package/Utils/Slo/SloBurnRateTemplate.ts +373 -0
- package/Utils/Slo/SloFeedMarkdown.ts +1507 -0
- package/Utils/Slo/SloHealth.ts +96 -9
- package/Utils/Slo/SloListWidgetFormat.ts +370 -0
- package/Utils/Slo/SloMetricType.ts +237 -0
- package/Utils/Slo/SloMonitorRuleCriteria.ts +364 -0
- package/Utils/Slo/SloMonitorStatusSummary.ts +210 -0
- package/Utils/Slo/SloOverviewText.ts +265 -0
- package/Utils/Slo/SloProjection.ts +967 -0
- package/Utils/Slo/SloWidgetFormat.ts +12 -2
- package/Utils/Telemetry/LockedFilterSearch.ts +3 -49
- package/build/dist/Models/AnalyticsModels/AuditLog.js +70 -1
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/SecurityEvent.js +4 -4
- package/build/dist/Models/DatabaseModels/Alert.js +60 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +64 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +6 -4
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +68 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js +772 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +140 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +42 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +11 -11
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +192 -10
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +798 -96
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +596 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +590 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +16 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +16 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +75 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +1 -1
- package/build/dist/Server/API/BaseAPI.js +14 -0
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js +233 -19
- package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
- package/build/dist/Server/API/BillingPaymentMethodAPI.js +86 -5
- package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +72 -2
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/SecurityEventConnectionAPI.js +102 -10
- package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +236 -154
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js +21 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js +207 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js +72 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js +46 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +112 -56
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +167 -68
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +87 -26
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js +270 -203
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +498 -354
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +97 -34
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +91 -8
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AuditLogService.js +408 -44
- package/build/dist/Server/Services/AuditLogService.js.map +1 -1
- package/build/dist/Server/Services/BillingInvoiceService.js +94 -85
- package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +406 -14
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +135 -86
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +189 -100
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +125 -18
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +145 -91
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +191 -101
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +190 -102
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +112 -56
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +220 -63
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +87 -26
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +258 -192
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +519 -376
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +95 -32
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +90 -5
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +113 -65
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +6 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +145 -91
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +191 -101
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +20 -25
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +123 -77
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +167 -82
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +18 -2
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +11 -9
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +287 -5
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js +333 -0
- package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +36 -2
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +117 -64
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +173 -83
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +116 -65
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +82 -10
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +111 -63
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +161 -77
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +280 -209
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +521 -376
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +24 -0
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +24 -8
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventConnectionService.js +43 -3
- package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +115 -62
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +163 -77
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +769 -18
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js +96 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +614 -87
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +844 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +207 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +221 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +997 -50
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +191 -102
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageAnnouncementService.js +12 -0
- package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +118 -70
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +158 -76
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +19 -215
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +6 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +27 -5
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/ThreatIntelFeedService.js +1 -1
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js +17 -0
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js +31 -0
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +24 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +21 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +337 -53
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +108 -15
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +2 -2
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +115 -6
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +13 -0
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/Database/RelationValueUtil.js +82 -0
- package/build/dist/Server/Utils/Database/RelationValueUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +10 -6
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +17 -21
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +5 -4
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +50 -10
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +13 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +6 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js +34 -0
- package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +69 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js +128 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +746 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js +221 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +3 -2
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +6 -4
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.js +174 -14
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js +1417 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +138 -18
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +1 -2
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +23 -18
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +2 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +95 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +3 -3
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +2 -2
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +118 -40
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/Slo/SloFeedUtil.js +150 -0
- package/build/dist/Server/Utils/Slo/SloFeedUtil.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js +136 -0
- package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloMetricUtil.js +269 -0
- package/build/dist/Server/Utils/Slo/SloMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js +134 -0
- package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js +137 -0
- package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +6 -26
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageResource.js +31 -5
- package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
- package/build/dist/Types/Billing/SubscriptionStatus.js +37 -3
- package/build/dist/Types/Billing/SubscriptionStatus.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +5 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +275 -286
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Database/EnableAuditLog.js +19 -1
- package/build/dist/Types/Database/EnableAuditLog.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +4 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -6
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +2 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepRetries.js +47 -0
- package/build/dist/Types/Monitor/MonitorStepRetries.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js.map +1 -1
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js +29 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js +37 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js +42 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js +20 -0
- package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js.map +1 -0
- package/build/dist/Types/Permission.js +114 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +5 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +267 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +16 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +65 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +6 -2
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -1
- package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js +26 -0
- package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloMetricType.js +45 -0
- package/build/dist/Types/ServiceLevelObjective/SloMetricType.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +4 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +295 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js +13 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +67 -0
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js +7 -7
- package/build/dist/Types/Telemetry/ServiceType.js +7 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/AlertBanner/AlertBanner.js +48 -19
- package/build/dist/UI/Components/AlertBanner/AlertBanner.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js +10 -2
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +12 -3
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +33 -5
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js +3 -3
- package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js +47 -0
- package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js.map +1 -0
- package/build/dist/UI/Components/Forms/ModelForm.js +6 -5
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js +6 -2
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +0 -2
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +3 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/RuleRun/RuleDetailFields.js +226 -0
- package/build/dist/UI/Components/RuleRun/RuleDetailFields.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RuleTable.js +97 -0
- package/build/dist/UI/Components/RuleRun/RuleTable.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RuleView.js +83 -0
- package/build/dist/UI/Components/RuleRun/RuleView.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js +74 -0
- package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js +78 -0
- package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +24 -50
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +0 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Utils/Rules/RuleRunClient.js +98 -0
- package/build/dist/UI/Utils/Rules/RuleRunClient.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +8 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +16 -2
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js +94 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Dashboard/SloWidgetSource.js +125 -0
- package/build/dist/Utils/Dashboard/SloWidgetSource.js.map +1 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js +49 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +112 -34
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +22 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +129 -0
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js +255 -0
- package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js +184 -0
- package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js +79 -0
- package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +21 -12
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
- package/build/dist/Utils/Project/DataResidency.js +51 -0
- package/build/dist/Utils/Project/DataResidency.js.map +1 -0
- package/build/dist/Utils/Rules/RuleRunSummary.js +197 -0
- package/build/dist/Utils/Rules/RuleRunSummary.js.map +1 -0
- package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js +51 -0
- package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js.map +1 -0
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js +228 -0
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js.map +1 -0
- package/build/dist/Utils/Slo/SloFeedMarkdown.js +934 -0
- package/build/dist/Utils/Slo/SloFeedMarkdown.js.map +1 -0
- package/build/dist/Utils/Slo/SloHealth.js +75 -9
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
- package/build/dist/Utils/Slo/SloListWidgetFormat.js +217 -0
- package/build/dist/Utils/Slo/SloListWidgetFormat.js.map +1 -0
- package/build/dist/Utils/Slo/SloMetricType.js +212 -0
- package/build/dist/Utils/Slo/SloMetricType.js.map +1 -0
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +216 -0
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -0
- package/build/dist/Utils/Slo/SloMonitorStatusSummary.js +129 -0
- package/build/dist/Utils/Slo/SloMonitorStatusSummary.js.map +1 -0
- package/build/dist/Utils/Slo/SloOverviewText.js +110 -0
- package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -0
- package/build/dist/Utils/Slo/SloProjection.js +448 -0
- package/build/dist/Utils/Slo/SloProjection.js.map +1 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js +4 -2
- package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -1
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js +1 -26
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -1
- package/package.json +1 -1
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +0 -447
- package/Models/DatabaseModels/GoogleSecOpsConnectionRun.ts +0 -263
- package/Server/API/GoogleSecOpsConnectionAPI.ts +0 -320
- package/Server/Services/GoogleSecOpsConnectionRunService.ts +0 -10
- package/Server/Services/GoogleSecOpsConnectionService.ts +0 -116
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +0 -777
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +0 -1373
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +0 -512
- package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +0 -838
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +0 -441
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +0 -1001
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +0 -657
- package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +0 -153
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +0 -784
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +0 -823
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +0 -918
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +0 -738
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +0 -874
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +0 -1297
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +0 -1577
- package/Tests/UI/Components/LockedFilterActions.test.tsx +0 -396
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +0 -111
- package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +0 -205
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +0 -478
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +0 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js +0 -287
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +0 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +0 -231
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js +0 -9
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +0 -70
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +0 -537
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +0 -1034
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +0 -410
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +0 -1
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js +0 -2
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js.map +0 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +0 -88
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +0 -1
|
@@ -12,12 +12,14 @@ import OneUptimeDate from "../../Types/Date";
|
|
|
12
12
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
13
13
|
import ObjectID from "../../Types/ObjectID";
|
|
14
14
|
import SloWindowType from "../../Types/ServiceLevelObjective/SloWindowType";
|
|
15
|
+
import { escapeMarkdownInline } from "../../Utils/Markdown/MarkdownEscape";
|
|
15
16
|
import DatabaseConfig from "../DatabaseConfig";
|
|
16
17
|
import CreateBy from "../Types/Database/CreateBy";
|
|
17
18
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
18
19
|
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
19
20
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
20
21
|
import UpdateBy from "../Types/Database/UpdateBy";
|
|
22
|
+
import { resolveReferenceId } from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
21
23
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
22
24
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
23
25
|
import AlertSeverityService from "./AlertSeverityService";
|
|
@@ -26,9 +28,87 @@ import MonitorStatusService from "./MonitorStatusService";
|
|
|
26
28
|
import ProjectService from "./ProjectService";
|
|
27
29
|
import ServiceLevelObjectiveBurnRateRuleService from "./ServiceLevelObjectiveBurnRateRuleService";
|
|
28
30
|
import ServiceLevelObjectiveMonitorRuleEngineService from "./ServiceLevelObjectiveMonitorRuleEngineService";
|
|
31
|
+
import ServiceLevelObjectiveMonitorRuleService from "./ServiceLevelObjectiveMonitorRuleService";
|
|
29
32
|
import ServiceLevelObjectiveOwnerTeamService from "./ServiceLevelObjectiveOwnerTeamService";
|
|
30
33
|
import ServiceLevelObjectiveOwnerUserService from "./ServiceLevelObjectiveOwnerUserService";
|
|
31
34
|
import TeamMemberService from "./TeamMemberService";
|
|
35
|
+
import ServiceLevelObjectiveFeedService from "./ServiceLevelObjectiveFeedService";
|
|
36
|
+
import Monitor from "../../Models/DatabaseModels/Monitor";
|
|
37
|
+
import { ServiceLevelObjectiveFeedEventType } from "../../Models/DatabaseModels/ServiceLevelObjectiveFeed";
|
|
38
|
+
import {
|
|
39
|
+
Blue500,
|
|
40
|
+
Gray500,
|
|
41
|
+
Green500,
|
|
42
|
+
Orange500,
|
|
43
|
+
Yellow500,
|
|
44
|
+
} from "../../Types/BrandColors";
|
|
45
|
+
import Color from "../../Types/Color";
|
|
46
|
+
import Dictionary from "../../Types/Dictionary";
|
|
47
|
+
import {
|
|
48
|
+
SLO_FEED_IS_ARCHIVED_COLUMN,
|
|
49
|
+
SLO_FEED_IS_ENABLED_COLUMN,
|
|
50
|
+
SLO_FEED_MONITORS_COLUMN,
|
|
51
|
+
SLO_FEED_UPDATE_COLUMNS,
|
|
52
|
+
SloFeedColumn,
|
|
53
|
+
SloFeedColumnChange,
|
|
54
|
+
SloFeedMarkdown,
|
|
55
|
+
SloFeedMonitorReference,
|
|
56
|
+
SloFeedRow,
|
|
57
|
+
getSloArchivedFeedMarkdown,
|
|
58
|
+
getSloCreatedFeedMarkdown,
|
|
59
|
+
getSloEnabledFeedMarkdown,
|
|
60
|
+
getSloFeedColumnChanges,
|
|
61
|
+
getSloFeedEntityIds,
|
|
62
|
+
getSloFeedSelect,
|
|
63
|
+
getSloFeedWatchedColumns,
|
|
64
|
+
getSloMonitorsChangedFeedMarkdown,
|
|
65
|
+
getSloUpdatedFeedMarkdown,
|
|
66
|
+
isSloFeedValueEqual,
|
|
67
|
+
normalizeSloFeedBoolean,
|
|
68
|
+
} from "../../Utils/Slo/SloFeedMarkdown";
|
|
69
|
+
import Select from "../Types/Database/Select";
|
|
70
|
+
import SloFeedUtil from "../Utils/Slo/SloFeedUtil";
|
|
71
|
+
import SloLegacyMonitorLabelAdoption from "../Utils/Slo/SloLegacyMonitorLabelAdoption";
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* What the SLO feed carries from onBeforeUpdate to onUpdateSuccess: the watched
|
|
75
|
+
* columns the payload wrote, and each matched SLO as it was BEFORE the write.
|
|
76
|
+
* The rows are gone from memory by the time the write lands, and "old -> new"
|
|
77
|
+
* and "did it actually change" both need them.
|
|
78
|
+
*/
|
|
79
|
+
interface SloFeedUpdateSnapshot {
|
|
80
|
+
columns: Array<SloFeedColumn>;
|
|
81
|
+
rowsById: Dictionary<Model>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// One feed item an update earned, built once the SLO's link is known.
|
|
85
|
+
interface SloFeedPendingItem {
|
|
86
|
+
eventType: ServiceLevelObjectiveFeedEventType;
|
|
87
|
+
displayColor: Color;
|
|
88
|
+
getMarkdown: (sloMarkdownLink: string) => SloFeedMarkdown;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* The root cause stamped on every burn-rate alert and incident an archive
|
|
93
|
+
* resolves. Distinct from the disable/delete default so a responder reading a
|
|
94
|
+
* closed page can tell "somebody retired this SLO" from "somebody paused it" -
|
|
95
|
+
* the first will not come back on its own, the second may.
|
|
96
|
+
*/
|
|
97
|
+
export const SLO_ARCHIVED_ROOT_CAUSE: string =
|
|
98
|
+
"Auto-resolved because the Service Level Objective was archived.";
|
|
99
|
+
|
|
100
|
+
export const SLO_DISABLED_OR_DELETED_ROOT_CAUSE: string =
|
|
101
|
+
"Auto-resolved because the Service Level Objective was disabled or deleted.";
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
* What onBeforeDelete reads for onDeleteSuccess: the SLOs the delete may
|
|
105
|
+
* remove, and the burn rate rules of each - Postgres cascades those away with
|
|
106
|
+
* the SLO, so they cannot be read afterwards.
|
|
107
|
+
*/
|
|
108
|
+
interface SloDeleteCarryForward {
|
|
109
|
+
itemsToDelete: Array<Model>;
|
|
110
|
+
burnRateRules: Array<ServiceLevelObjectiveBurnRateRule>;
|
|
111
|
+
}
|
|
32
112
|
|
|
33
113
|
export class Service extends DatabaseService<Model> {
|
|
34
114
|
public constructor() {
|
|
@@ -120,9 +200,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
120
200
|
|
|
121
201
|
@CaptureSpan()
|
|
122
202
|
protected override async onCreateSuccess(
|
|
123
|
-
|
|
203
|
+
onCreate: OnCreate<Model>,
|
|
124
204
|
createdItem: Model,
|
|
125
205
|
): Promise<Model> {
|
|
206
|
+
/*
|
|
207
|
+
* The row's own creation time, so the "created" feed item - written last,
|
|
208
|
+
* and without waiting - still sorts ahead of everything the create sets
|
|
209
|
+
* off, like the creator being added as an owner.
|
|
210
|
+
*/
|
|
211
|
+
const createdAt: Date =
|
|
212
|
+
createdItem.createdAt || OneUptimeDate.getCurrentDate();
|
|
213
|
+
|
|
126
214
|
/*
|
|
127
215
|
* Stamp nextEvaluationAt = now so the evaluation worker picks this SLO up
|
|
128
216
|
* on its next tick. Done here (isRoot update) instead of onBeforeCreate
|
|
@@ -148,8 +236,23 @@ export class Service extends DatabaseService<Model> {
|
|
|
148
236
|
}
|
|
149
237
|
|
|
150
238
|
// Seed the two canonical multi-window burn rate rules. Non-fatal.
|
|
239
|
+
let seededBurnRateRules: Array<ServiceLevelObjectiveBurnRateRule> = [];
|
|
240
|
+
|
|
151
241
|
try {
|
|
152
|
-
|
|
242
|
+
/*
|
|
243
|
+
* Marked as seeding so the burn rate rule service does not post its own
|
|
244
|
+
* "rule added" items for these two: they are part of creating the SLO
|
|
245
|
+
* and are described by its "created" item (see SloFeedUtil for why this
|
|
246
|
+
* signal and not "root with no user").
|
|
247
|
+
*/
|
|
248
|
+
seededBurnRateRules = createdItem.id
|
|
249
|
+
? await SloFeedUtil.runWhileSeedingDefaultBurnRateRules({
|
|
250
|
+
sloId: createdItem.id,
|
|
251
|
+
seed: (): Promise<Array<ServiceLevelObjectiveBurnRateRule>> => {
|
|
252
|
+
return this.seedDefaultBurnRateRules(createdItem);
|
|
253
|
+
},
|
|
254
|
+
})
|
|
255
|
+
: await this.seedDefaultBurnRateRules(createdItem);
|
|
153
256
|
} catch (err) {
|
|
154
257
|
logger.error(
|
|
155
258
|
`Error seeding default burn rate rules for SLO ${createdItem.id?.toString()}: ${err}`,
|
|
@@ -158,9 +261,20 @@ export class Service extends DatabaseService<Model> {
|
|
|
158
261
|
}
|
|
159
262
|
|
|
160
263
|
/*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
264
|
+
* A create that still carries the deprecated "Auto-Add Monitors With
|
|
265
|
+
* Labels" list gets it as a monitor rule first, so the sync below attaches
|
|
266
|
+
* what the list matches - as the previous release did. See
|
|
267
|
+
* applyDeprecatedMonitorLabelWrite for who still sends it and why.
|
|
268
|
+
*/
|
|
269
|
+
await this.adoptDeprecatedMonitorLabelsWrittenOnCreate(createdItem);
|
|
270
|
+
|
|
271
|
+
/*
|
|
272
|
+
* Reconcile the new SLO's monitor list with its monitor rules. A brand-new
|
|
273
|
+
* SLO normally has none yet (rules are added afterwards, on the Monitor
|
|
274
|
+
* Rules page), so this is usually a read and no write - but it keeps an
|
|
275
|
+
* SLO created with rows already pointing at it (an API import, a rolling
|
|
276
|
+
* deploy's backfill) from reading "no monitors attached" until someone
|
|
277
|
+
* happens to edit a rule or a monitor.
|
|
164
278
|
*/
|
|
165
279
|
try {
|
|
166
280
|
await ServiceLevelObjectiveMonitorRuleEngineService.syncMonitorsForSlo({
|
|
@@ -168,11 +282,28 @@ export class Service extends DatabaseService<Model> {
|
|
|
168
282
|
});
|
|
169
283
|
} catch (err) {
|
|
170
284
|
logger.error(
|
|
171
|
-
`Error applying the monitor
|
|
285
|
+
`Error applying the monitor rules for SLO ${createdItem.id?.toString()}: ${err}`,
|
|
172
286
|
{ projectId: createdItem.projectId?.toString() } as LogAttributes,
|
|
173
287
|
);
|
|
174
288
|
}
|
|
175
289
|
|
|
290
|
+
/*
|
|
291
|
+
* Fire-and-forget, like ServiceService's created item: the SLO exists
|
|
292
|
+
* whether or not its feed item does, and the create request should not
|
|
293
|
+
* wait on user and link lookups just to describe itself.
|
|
294
|
+
*/
|
|
295
|
+
this.writeSloCreatedFeed({
|
|
296
|
+
onCreate: onCreate,
|
|
297
|
+
createdItem: createdItem,
|
|
298
|
+
seededBurnRateRules: seededBurnRateRules,
|
|
299
|
+
postedAt: createdAt,
|
|
300
|
+
}).catch((err: Error) => {
|
|
301
|
+
logger.error(
|
|
302
|
+
`Error writing the created feed item for SLO ${createdItem.id?.toString()}: ${err}`,
|
|
303
|
+
{ projectId: createdItem.projectId?.toString() } as LogAttributes,
|
|
304
|
+
);
|
|
305
|
+
});
|
|
306
|
+
|
|
176
307
|
return createdItem;
|
|
177
308
|
}
|
|
178
309
|
|
|
@@ -209,9 +340,25 @@ export class Service extends DatabaseService<Model> {
|
|
|
209
340
|
this.validateAtRiskThresholdPercentage(newAtRiskThresholdPercentage);
|
|
210
341
|
}
|
|
211
342
|
|
|
343
|
+
await this.assertMonitorEditRespectsMonitorRules(updateBy);
|
|
344
|
+
|
|
345
|
+
/*
|
|
346
|
+
* Last, so a payload the checks above rejected never costs the feed a
|
|
347
|
+
* read. Null unless the payload writes a column the feed describes.
|
|
348
|
+
*/
|
|
349
|
+
const feedSnapshot: SloFeedUpdateSnapshot | null =
|
|
350
|
+
await this.readFeedSnapshotBeforeUpdate(updateBy);
|
|
351
|
+
|
|
352
|
+
// Null unless the payload writes the deprecated monitor label list.
|
|
353
|
+
const monitorLabelIdsBeforeUpdate: Dictionary<Array<string>> | null =
|
|
354
|
+
await this.readDeprecatedMonitorLabelsBeforeUpdate(updateBy);
|
|
355
|
+
|
|
212
356
|
return {
|
|
213
357
|
updateBy,
|
|
214
|
-
carryForward:
|
|
358
|
+
carryForward: {
|
|
359
|
+
feedSnapshot: feedSnapshot,
|
|
360
|
+
monitorLabelIdsBeforeUpdate: monitorLabelIdsBeforeUpdate,
|
|
361
|
+
},
|
|
215
362
|
};
|
|
216
363
|
}
|
|
217
364
|
|
|
@@ -221,12 +368,40 @@ export class Service extends DatabaseService<Model> {
|
|
|
221
368
|
updatedItemIds: Array<ObjectID>,
|
|
222
369
|
): Promise<OnUpdate<Model>> {
|
|
223
370
|
/*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
371
|
+
* Fire-and-forget, and only when onBeforeUpdate took a snapshot - so the
|
|
372
|
+
* worker's per-tick state write does no feed work at all. The time is
|
|
373
|
+
* taken here so the items sort where the edit happened, not where their
|
|
374
|
+
* lookups finished.
|
|
228
375
|
*/
|
|
229
|
-
if (
|
|
376
|
+
if (onUpdate.carryForward?.feedSnapshot) {
|
|
377
|
+
const updatedAt: Date = OneUptimeDate.getCurrentDate();
|
|
378
|
+
|
|
379
|
+
this.writeSloUpdatedFeed({
|
|
380
|
+
onUpdate: onUpdate,
|
|
381
|
+
updatedItemIds: updatedItemIds,
|
|
382
|
+
postedAt: updatedAt,
|
|
383
|
+
}).catch((err: Error) => {
|
|
384
|
+
logger.error(`Error writing SLO feed items after an update: ${err}`);
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/*
|
|
389
|
+
* When an SLO is disabled or archived, resolve everything its burn-rate
|
|
390
|
+
* rules have open — the evaluation worker skips disabled and archived
|
|
391
|
+
* SLOs alike, so nothing else would ever resolve them (and their on-call
|
|
392
|
+
* escalations would stay open forever).
|
|
393
|
+
*
|
|
394
|
+
* One pass even when a single write both disables and archives: the
|
|
395
|
+
* second would only re-query every rule for records the first already
|
|
396
|
+
* closed. The archive wording wins, because it is the more permanent of
|
|
397
|
+
* the two and the one a responder reading the root cause needs to know.
|
|
398
|
+
*/
|
|
399
|
+
const isDisablingSlo: boolean =
|
|
400
|
+
(onUpdate.updateBy.data.isEnabled as boolean | undefined) === false;
|
|
401
|
+
const isArchivingSlo: boolean =
|
|
402
|
+
(onUpdate.updateBy.data.isArchived as boolean | undefined) === true;
|
|
403
|
+
|
|
404
|
+
if (isDisablingSlo || isArchivingSlo) {
|
|
230
405
|
for (const updatedItemId of updatedItemIds) {
|
|
231
406
|
try {
|
|
232
407
|
const slo: Model | null = await this.findOneById({
|
|
@@ -243,49 +418,89 @@ export class Service extends DatabaseService<Model> {
|
|
|
243
418
|
continue;
|
|
244
419
|
}
|
|
245
420
|
|
|
246
|
-
|
|
421
|
+
/*
|
|
422
|
+
* rootCause is only set for an archive, so a plain disable keeps
|
|
423
|
+
* calling with exactly the payload it always has.
|
|
424
|
+
*/
|
|
425
|
+
const resolveData: {
|
|
426
|
+
sloId: ObjectID;
|
|
427
|
+
projectId: ObjectID;
|
|
428
|
+
rootCause?: string | undefined;
|
|
429
|
+
} = {
|
|
247
430
|
sloId: updatedItemId,
|
|
248
431
|
projectId: slo.projectId,
|
|
249
|
-
}
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
if (isArchivingSlo) {
|
|
435
|
+
resolveData.rootCause = SLO_ARCHIVED_ROOT_CAUSE;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
await this.resolveOpenBurnRateAlertsAndIncidentsForSlo(resolveData);
|
|
250
439
|
} catch (err) {
|
|
440
|
+
/*
|
|
441
|
+
* Never fail the user's write: the disable or archive already
|
|
442
|
+
* landed, and refusing it over a stale open record would be worse
|
|
443
|
+
* than the record itself.
|
|
444
|
+
*/
|
|
251
445
|
logger.error(
|
|
252
|
-
`Error resolving open burn rate alerts and incidents for
|
|
446
|
+
`Error resolving open burn rate alerts and incidents for ${
|
|
447
|
+
isArchivingSlo ? "archived" : "disabled"
|
|
448
|
+
} SLO ${updatedItemId.toString()}: ${err}`,
|
|
253
449
|
);
|
|
254
450
|
}
|
|
255
451
|
}
|
|
256
452
|
}
|
|
257
453
|
|
|
258
454
|
/*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
455
|
+
* Monitor membership follows the SLO's monitor rules, and
|
|
456
|
+
* ServiceLevelObjectiveMonitorRuleService re-syncs whenever one of those
|
|
457
|
+
* changes, so an ordinary SLO edit needs no sync. The exception is a write
|
|
458
|
+
* of the deprecated "Auto-Add Monitors With Labels" list, which nothing
|
|
459
|
+
* else on this release would act on - see applyDeprecatedMonitorLabelWrite.
|
|
263
460
|
*/
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
461
|
+
if (
|
|
462
|
+
onUpdate.updateBy.data.monitorLabels !== undefined &&
|
|
463
|
+
updatedItemIds.length > 0
|
|
464
|
+
) {
|
|
465
|
+
await this.applyDeprecatedMonitorLabelWrite({
|
|
466
|
+
serviceLevelObjectiveIds: updatedItemIds,
|
|
467
|
+
writtenMonitorLabels: onUpdate.updateBy.data.monitorLabels as unknown,
|
|
468
|
+
labelIdsBeforeUpdateBySloId:
|
|
469
|
+
(onUpdate.carryForward?.monitorLabelIdsBeforeUpdate as
|
|
470
|
+
| Dictionary<Array<string>>
|
|
471
|
+
| null
|
|
472
|
+
| undefined) || {},
|
|
473
|
+
});
|
|
278
474
|
}
|
|
279
475
|
|
|
280
476
|
/*
|
|
281
477
|
* If the objective's math inputs changed, force a re-evaluation on the
|
|
282
478
|
* worker's next tick.
|
|
479
|
+
*
|
|
480
|
+
* "Inputs" means every column the worker's result depends on, not only
|
|
481
|
+
* the objective's: the downtime statuses and multi-monitor mode decide
|
|
482
|
+
* which seconds count as bad, the timezone moves calendar-month
|
|
483
|
+
* boundaries, and the at-risk threshold decides the status. All four are
|
|
484
|
+
* edited on the Settings page, and without them a saved change kept
|
|
485
|
+
* showing the old numbers until the SLO's regular cadence came round.
|
|
283
486
|
*/
|
|
284
487
|
const isEvaluationConfigUpdated: boolean =
|
|
285
488
|
onUpdate.updateBy.data.targetPercentage !== undefined ||
|
|
286
489
|
onUpdate.updateBy.data.windowDays !== undefined ||
|
|
287
490
|
onUpdate.updateBy.data.windowType !== undefined ||
|
|
288
|
-
onUpdate.updateBy.data.monitors !== undefined
|
|
491
|
+
onUpdate.updateBy.data.monitors !== undefined ||
|
|
492
|
+
onUpdate.updateBy.data.multiMonitorMode !== undefined ||
|
|
493
|
+
onUpdate.updateBy.data.downtimeMonitorStatuses !== undefined ||
|
|
494
|
+
onUpdate.updateBy.data.atRiskThresholdPercentage !== undefined ||
|
|
495
|
+
onUpdate.updateBy.data.timezone !== undefined ||
|
|
496
|
+
/*
|
|
497
|
+
* Unarchived: the worker stopped looking at this SLO while it was
|
|
498
|
+
* archived, so its status and budget are frozen at archive time. Its
|
|
499
|
+
* nextEvaluationAt is normally already in the past, but stamping it
|
|
500
|
+
* explicitly guarantees the numbers refresh on the very next tick.
|
|
501
|
+
* (A still-disabled SLO stays skipped by getDueSlos regardless.)
|
|
502
|
+
*/
|
|
503
|
+
(onUpdate.updateBy.data.isArchived as boolean | undefined) === false;
|
|
289
504
|
|
|
290
505
|
if (isEvaluationConfigUpdated) {
|
|
291
506
|
for (const updatedItemId of updatedItemIds) {
|
|
@@ -310,12 +525,39 @@ export class Service extends DatabaseService<Model> {
|
|
|
310
525
|
return onUpdate;
|
|
311
526
|
}
|
|
312
527
|
|
|
528
|
+
/*
|
|
529
|
+
* READ ONLY: notes down the SLOs this delete may remove and, for each, the
|
|
530
|
+
* burn rate rules whose open alerts and incidents onDeleteSuccess resolves.
|
|
531
|
+
*
|
|
532
|
+
* The rules have to be read now. They cascade away with the SLO in Postgres,
|
|
533
|
+
* with no hook of their own, and a rule's id is half of the fingerprint that
|
|
534
|
+
* finds what it opened.
|
|
535
|
+
*
|
|
536
|
+
* Nothing is resolved here. DatabaseService runs this hook BEFORE it applies
|
|
537
|
+
* the caller's delete permissions, and the CRUD API passes a raw id, so these
|
|
538
|
+
* rows are only candidates. Resolving here as root let a delete that named
|
|
539
|
+
* another project's SLO close that project's burn rate alerts and incidents
|
|
540
|
+
* while deleting nothing. onDeleteSuccess acts only on the ids the delete
|
|
541
|
+
* really removed, and the tenant pin keeps this read from even seeing
|
|
542
|
+
* another project's SLOs. A multi-tenant request is left unpinned because
|
|
543
|
+
* DatabaseService does not pin it either: candidates narrower than what the
|
|
544
|
+
* delete removes would strand records instead.
|
|
545
|
+
*
|
|
546
|
+
* A failed read is deliberately not caught: deleting an SLO without knowing
|
|
547
|
+
* its rules would strand everything they opened, and the on-call escalations
|
|
548
|
+
* with it, because the evaluation worker never looks at a deleted SLO again.
|
|
549
|
+
*/
|
|
313
550
|
@CaptureSpan()
|
|
314
551
|
protected override async onBeforeDelete(
|
|
315
552
|
deleteBy: DeleteBy<Model>,
|
|
316
553
|
): Promise<OnDelete<Model>> {
|
|
317
554
|
const itemsToDelete: Array<Model> = await this.findBy({
|
|
318
|
-
query:
|
|
555
|
+
query: SloFeedUtil.getTenantPinnedQuery({
|
|
556
|
+
query: deleteBy.query,
|
|
557
|
+
tenantId: deleteBy.props.isMultiTenantRequest
|
|
558
|
+
? undefined
|
|
559
|
+
: deleteBy.props.tenantId,
|
|
560
|
+
}),
|
|
319
561
|
limit: LIMIT_MAX,
|
|
320
562
|
skip: 0,
|
|
321
563
|
select: {
|
|
@@ -327,42 +569,142 @@ export class Service extends DatabaseService<Model> {
|
|
|
327
569
|
},
|
|
328
570
|
});
|
|
329
571
|
|
|
572
|
+
const burnRateRules: Array<ServiceLevelObjectiveBurnRateRule> = [];
|
|
573
|
+
|
|
330
574
|
for (const item of itemsToDelete) {
|
|
331
575
|
if (!item.id || !item.projectId) {
|
|
332
576
|
continue;
|
|
333
577
|
}
|
|
334
578
|
|
|
335
|
-
|
|
336
|
-
await
|
|
337
|
-
|
|
338
|
-
|
|
579
|
+
const rulesOfSlo: Array<ServiceLevelObjectiveBurnRateRule> =
|
|
580
|
+
await ServiceLevelObjectiveBurnRateRuleService.findBy({
|
|
581
|
+
query: {
|
|
582
|
+
serviceLevelObjectiveId: item.id,
|
|
583
|
+
projectId: item.projectId,
|
|
584
|
+
},
|
|
585
|
+
select: {
|
|
586
|
+
_id: true,
|
|
587
|
+
projectId: true,
|
|
588
|
+
serviceLevelObjectiveId: true,
|
|
589
|
+
},
|
|
590
|
+
skip: 0,
|
|
591
|
+
limit: LIMIT_PER_PROJECT,
|
|
592
|
+
props: {
|
|
593
|
+
isRoot: true,
|
|
594
|
+
},
|
|
339
595
|
});
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
`Error resolving open burn rate alerts and incidents for SLO ${item.id?.toString()} before delete: ${err}`,
|
|
343
|
-
{ projectId: item.projectId?.toString() } as LogAttributes,
|
|
344
|
-
);
|
|
345
|
-
}
|
|
596
|
+
|
|
597
|
+
burnRateRules.push(...rulesOfSlo);
|
|
346
598
|
}
|
|
347
599
|
|
|
600
|
+
const carryForward: SloDeleteCarryForward = {
|
|
601
|
+
itemsToDelete: itemsToDelete,
|
|
602
|
+
burnRateRules: burnRateRules,
|
|
603
|
+
};
|
|
604
|
+
|
|
348
605
|
return {
|
|
349
606
|
deleteBy,
|
|
350
|
-
carryForward:
|
|
351
|
-
itemsToDelete: itemsToDelete,
|
|
352
|
-
},
|
|
607
|
+
carryForward: carryForward,
|
|
353
608
|
};
|
|
354
609
|
}
|
|
355
610
|
|
|
611
|
+
/*
|
|
612
|
+
* Resolves what the burn rate rules of every SLO this delete really removed
|
|
613
|
+
* left open. Nothing else ever will: the evaluation worker never looks at a
|
|
614
|
+
* deleted SLO again, so those alerts and incidents, and their on-call
|
|
615
|
+
* escalations, would otherwise stay open forever.
|
|
616
|
+
*
|
|
617
|
+
* Only the SLOs whose ids DatabaseService reports as deleted are acted on
|
|
618
|
+
* (SloFeedUtil.getRowsActuallyDeleted), never every candidate onBeforeDelete
|
|
619
|
+
* read - see there for why.
|
|
620
|
+
*
|
|
621
|
+
* Resolving after the delete is safe: open records are found by fingerprint
|
|
622
|
+
* in the Alert and Incident tables, not through the SLO or rule rows. It is
|
|
623
|
+
* also the honest order - a delete that fails leaves its records open next
|
|
624
|
+
* to the SLO that still stands behind them.
|
|
625
|
+
*
|
|
626
|
+
* Rule by rule rather than through resolveOpenBurnRateAlertsAndIncidentsForSlo:
|
|
627
|
+
* that one reads the SLO's rules, which the cascade has already removed, and
|
|
628
|
+
* clears their lifecycle columns, which no longer exist.
|
|
629
|
+
*/
|
|
630
|
+
@CaptureSpan()
|
|
631
|
+
protected override async onDeleteSuccess(
|
|
632
|
+
onDelete: OnDelete<Model>,
|
|
633
|
+
itemIdsBeforeDelete: Array<ObjectID>,
|
|
634
|
+
): Promise<OnDelete<Model>> {
|
|
635
|
+
const carryForward: SloDeleteCarryForward | null =
|
|
636
|
+
(onDelete.carryForward as SloDeleteCarryForward | null) || null;
|
|
637
|
+
|
|
638
|
+
const deletedSlos: Array<Model> = SloFeedUtil.getRowsActuallyDeleted({
|
|
639
|
+
rows: carryForward?.itemsToDelete || [],
|
|
640
|
+
deletedIds: itemIdsBeforeDelete,
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
for (const slo of deletedSlos) {
|
|
644
|
+
if (!slo.id || !slo.projectId) {
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const sloId: ObjectID = slo.id;
|
|
649
|
+
const projectId: ObjectID = slo.projectId;
|
|
650
|
+
|
|
651
|
+
const rulesOfSlo: Array<ServiceLevelObjectiveBurnRateRule> = (
|
|
652
|
+
carryForward?.burnRateRules || []
|
|
653
|
+
).filter((rule: ServiceLevelObjectiveBurnRateRule): boolean => {
|
|
654
|
+
return (
|
|
655
|
+
rule.serviceLevelObjectiveId?.toString().toLowerCase() ===
|
|
656
|
+
sloId.toString().toLowerCase()
|
|
657
|
+
);
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
for (const rule of rulesOfSlo) {
|
|
661
|
+
if (!rule.id) {
|
|
662
|
+
continue;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
try {
|
|
666
|
+
await ServiceLevelObjectiveBurnRateRuleService.resolveOpenAlertsAndIncidentsForRule(
|
|
667
|
+
{
|
|
668
|
+
serviceLevelObjectiveId: sloId,
|
|
669
|
+
burnRateRuleId: rule.id,
|
|
670
|
+
projectId: projectId,
|
|
671
|
+
rootCause: SLO_DISABLED_OR_DELETED_ROOT_CAUSE,
|
|
672
|
+
},
|
|
673
|
+
);
|
|
674
|
+
} catch (err) {
|
|
675
|
+
/*
|
|
676
|
+
* Never fail the request - the SLO is already gone - and never let
|
|
677
|
+
* one rule's failure cost the next rule its resolve.
|
|
678
|
+
*/
|
|
679
|
+
logger.error(
|
|
680
|
+
`Error resolving open alerts and incidents for burn rate rule ${rule.id.toString()} of deleted SLO ${sloId.toString()}: ${err}`,
|
|
681
|
+
{ projectId: projectId.toString() } as LogAttributes,
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return onDelete;
|
|
688
|
+
}
|
|
689
|
+
|
|
356
690
|
/*
|
|
357
691
|
* Resolve everything any of this SLO's burn rate rules has left open — the
|
|
358
692
|
* Alerts they raised and the Incidents they declared. Called when the SLO is
|
|
359
|
-
* disabled or deleted, and by the worker's Misconfigured / Paused
|
|
693
|
+
* disabled, archived or deleted, and by the worker's Misconfigured / Paused
|
|
694
|
+
* guards.
|
|
695
|
+
*
|
|
696
|
+
* `rootCause` is what the resolved records say closed them; it defaults to
|
|
697
|
+
* the disable/delete wording so every existing caller is unchanged.
|
|
360
698
|
*/
|
|
361
699
|
@CaptureSpan()
|
|
362
700
|
public async resolveOpenBurnRateAlertsAndIncidentsForSlo(data: {
|
|
363
701
|
sloId: ObjectID;
|
|
364
702
|
projectId: ObjectID;
|
|
703
|
+
rootCause?: string | undefined;
|
|
365
704
|
}): Promise<void> {
|
|
705
|
+
const rootCause: string =
|
|
706
|
+
data.rootCause || SLO_DISABLED_OR_DELETED_ROOT_CAUSE;
|
|
707
|
+
|
|
366
708
|
const burnRateRules: Array<ServiceLevelObjectiveBurnRateRule> =
|
|
367
709
|
await ServiceLevelObjectiveBurnRateRuleService.findBy({
|
|
368
710
|
query: {
|
|
@@ -405,8 +747,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
405
747
|
serviceLevelObjectiveId: data.sloId,
|
|
406
748
|
burnRateRuleId: rule.id,
|
|
407
749
|
projectId: data.projectId,
|
|
408
|
-
rootCause:
|
|
409
|
-
"Auto-resolved because the Service Level Objective was disabled or deleted.",
|
|
750
|
+
rootCause: rootCause,
|
|
410
751
|
},
|
|
411
752
|
);
|
|
412
753
|
|
|
@@ -444,15 +785,22 @@ export class Service extends DatabaseService<Model> {
|
|
|
444
785
|
}
|
|
445
786
|
|
|
446
787
|
/*
|
|
447
|
-
* All enabled SLOs in active projects that are due for
|
|
448
|
-
* (nextEvaluationAt in the past, or never evaluated). Selects
|
|
449
|
-
* and state column the evaluation worker needs.
|
|
788
|
+
* All enabled, unarchived SLOs in active projects that are due for
|
|
789
|
+
* evaluation (nextEvaluationAt in the past, or never evaluated). Selects
|
|
790
|
+
* every config and state column the evaluation worker needs.
|
|
791
|
+
*
|
|
792
|
+
* Archived is checked separately from enabled on purpose: the two flags are
|
|
793
|
+
* independent (unarchiving must not re-enable an SLO somebody paused), and
|
|
794
|
+
* either one alone takes the SLO out of evaluation. The worker re-reads both
|
|
795
|
+
* right before a burn rate rule fires, because this snapshot can go stale
|
|
796
|
+
* while a long sweep is still running.
|
|
450
797
|
*/
|
|
451
798
|
@CaptureSpan()
|
|
452
799
|
public async getDueSlos(): Promise<Array<Model>> {
|
|
453
800
|
return await this.findAllBy({
|
|
454
801
|
query: {
|
|
455
802
|
isEnabled: true,
|
|
803
|
+
isArchived: false,
|
|
456
804
|
nextEvaluationAt: QueryHelper.lessThanEqualToOrNull(
|
|
457
805
|
OneUptimeDate.getCurrentDate(),
|
|
458
806
|
),
|
|
@@ -464,6 +812,15 @@ export class Service extends DatabaseService<Model> {
|
|
|
464
812
|
_id: true,
|
|
465
813
|
projectId: true,
|
|
466
814
|
name: true,
|
|
815
|
+
/*
|
|
816
|
+
* Stamped as oneuptime.label.* on the oneuptime.slo.* metrics the
|
|
817
|
+
* worker posts (SloMetricUtil), so SLO series group and filter by
|
|
818
|
+
* the same labels as the SLO list.
|
|
819
|
+
*/
|
|
820
|
+
labels: {
|
|
821
|
+
_id: true,
|
|
822
|
+
name: true,
|
|
823
|
+
},
|
|
467
824
|
isEnabled: true,
|
|
468
825
|
sliType: true,
|
|
469
826
|
multiMonitorMode: true,
|
|
@@ -587,6 +944,61 @@ export class Service extends DatabaseService<Model> {
|
|
|
587
944
|
);
|
|
588
945
|
}
|
|
589
946
|
|
|
947
|
+
/*
|
|
948
|
+
* `[SLO <name>](<dashboard link>)` for feed items and notifications.
|
|
949
|
+
*
|
|
950
|
+
* The name is user-controlled and feeds render without safe mode, so it is
|
|
951
|
+
* escaped here, once, at the point it becomes markdown - a name like
|
|
952
|
+
* `x](https://evil)` must not be able to re-point the link.
|
|
953
|
+
*
|
|
954
|
+
* Pass `sloName` whenever the caller already has it (the worker always
|
|
955
|
+
* does); the lookup is only a fallback for callers holding just an id. An
|
|
956
|
+
* SLO that cannot be found still gets a working link, labelled "SLO".
|
|
957
|
+
*
|
|
958
|
+
* The lookup is pinned to `projectId`. Its callers are feed writers running
|
|
959
|
+
* after a write, and several of them hold an SLO id nobody checked against
|
|
960
|
+
* the tenant (an owner row or burn rate rule created with another project's
|
|
961
|
+
* SLO id). Read as root without the pin, that id would copy another
|
|
962
|
+
* project's SLO name into a feed item the caller's project can read. An SLO
|
|
963
|
+
* outside the project is treated exactly like one that does not exist.
|
|
964
|
+
*/
|
|
965
|
+
@CaptureSpan()
|
|
966
|
+
public async getSloMarkdownLink(data: {
|
|
967
|
+
projectId: ObjectID;
|
|
968
|
+
sloId: ObjectID;
|
|
969
|
+
sloName?: string | undefined;
|
|
970
|
+
}): Promise<string> {
|
|
971
|
+
let sloName: string | undefined = data.sloName;
|
|
972
|
+
|
|
973
|
+
if (sloName === undefined) {
|
|
974
|
+
const slo: Model | null = await this.findOneBy({
|
|
975
|
+
query: {
|
|
976
|
+
_id: data.sloId.toString(),
|
|
977
|
+
projectId: data.projectId,
|
|
978
|
+
},
|
|
979
|
+
select: {
|
|
980
|
+
name: true,
|
|
981
|
+
},
|
|
982
|
+
props: {
|
|
983
|
+
isRoot: true,
|
|
984
|
+
},
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
sloName = slo?.name || undefined;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
const link: URL = await this.getSloLinkInDashboard(
|
|
991
|
+
data.projectId,
|
|
992
|
+
data.sloId,
|
|
993
|
+
);
|
|
994
|
+
|
|
995
|
+
const escapedName: string = escapeMarkdownInline(sloName).trim();
|
|
996
|
+
|
|
997
|
+
const linkText: string = escapedName ? `SLO ${escapedName}` : "SLO";
|
|
998
|
+
|
|
999
|
+
return `[${linkText}](${link.toString()})`;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
590
1002
|
/*
|
|
591
1003
|
* Seed the two canonical Google-SRE multi-window burn rate rules, with
|
|
592
1004
|
* thresholds scaled to the SLO's compliance window. The textbook constants
|
|
@@ -595,9 +1007,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
595
1007
|
* A 30-day window reproduces exactly 14.4 and 6; shorter or longer windows
|
|
596
1008
|
* stay correctly calibrated.
|
|
597
1009
|
*/
|
|
598
|
-
private async seedDefaultBurnRateRules(
|
|
1010
|
+
private async seedDefaultBurnRateRules(
|
|
1011
|
+
createdItem: Model,
|
|
1012
|
+
): Promise<Array<ServiceLevelObjectiveBurnRateRule>> {
|
|
1013
|
+
// The rules actually written, for the SLO's "created" feed item.
|
|
1014
|
+
const seededRules: Array<ServiceLevelObjectiveBurnRateRule> = [];
|
|
1015
|
+
|
|
599
1016
|
if (!createdItem.id || !createdItem.projectId) {
|
|
600
|
-
return;
|
|
1017
|
+
return seededRules;
|
|
601
1018
|
}
|
|
602
1019
|
|
|
603
1020
|
const windowHours: number =
|
|
@@ -678,6 +1095,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
678
1095
|
isRoot: true,
|
|
679
1096
|
},
|
|
680
1097
|
});
|
|
1098
|
+
|
|
1099
|
+
seededRules.push(rule);
|
|
681
1100
|
} catch (err) {
|
|
682
1101
|
logger.error(
|
|
683
1102
|
`Error seeding default burn rate rule "${defaultRule.name}" for SLO ${createdItem.id?.toString()}: ${err}`,
|
|
@@ -685,6 +1104,887 @@ export class Service extends DatabaseService<Model> {
|
|
|
685
1104
|
);
|
|
686
1105
|
}
|
|
687
1106
|
}
|
|
1107
|
+
|
|
1108
|
+
return seededRules;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
/*
|
|
1112
|
+
* The SLO's "created" feed item: who created it, what it promises, and the
|
|
1113
|
+
* default burn rate rules that came with it (folded in here rather than
|
|
1114
|
+
* posted as two more items underneath).
|
|
1115
|
+
*/
|
|
1116
|
+
private async writeSloCreatedFeed(data: {
|
|
1117
|
+
onCreate: OnCreate<Model>;
|
|
1118
|
+
createdItem: Model;
|
|
1119
|
+
seededBurnRateRules: Array<ServiceLevelObjectiveBurnRateRule>;
|
|
1120
|
+
postedAt: Date;
|
|
1121
|
+
}): Promise<void> {
|
|
1122
|
+
const sloId: ObjectID | undefined = data.createdItem.id || undefined;
|
|
1123
|
+
const projectId: ObjectID | undefined = data.createdItem.projectId;
|
|
1124
|
+
|
|
1125
|
+
if (!sloId || !projectId) {
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/*
|
|
1130
|
+
* A dashboard, API-key or Terraform create carries an acting user; a
|
|
1131
|
+
* workflow or other automation creating as root does not, and the item
|
|
1132
|
+
* then says so instead of naming somebody.
|
|
1133
|
+
*/
|
|
1134
|
+
const createdByUserId: ObjectID | undefined =
|
|
1135
|
+
data.createdItem.createdByUserId ||
|
|
1136
|
+
data.onCreate.createBy.props.userId ||
|
|
1137
|
+
undefined;
|
|
1138
|
+
|
|
1139
|
+
const createdByUserMarkdown: string | null =
|
|
1140
|
+
await SloFeedUtil.getUserMarkdown({
|
|
1141
|
+
userId: createdByUserId,
|
|
1142
|
+
projectId: projectId,
|
|
1143
|
+
});
|
|
1144
|
+
|
|
1145
|
+
const markdown: SloFeedMarkdown = getSloCreatedFeedMarkdown({
|
|
1146
|
+
sloMarkdownLink: await this.getSloMarkdownLink({
|
|
1147
|
+
projectId: projectId,
|
|
1148
|
+
sloId: sloId,
|
|
1149
|
+
sloName: data.createdItem.name || "",
|
|
1150
|
+
}),
|
|
1151
|
+
createdByUserMarkdown: createdByUserMarkdown,
|
|
1152
|
+
targetPercentage: data.createdItem.targetPercentage,
|
|
1153
|
+
windowType: data.createdItem.windowType,
|
|
1154
|
+
windowDays: data.createdItem.windowDays,
|
|
1155
|
+
timezone: data.createdItem.timezone,
|
|
1156
|
+
sliType: data.createdItem.sliType,
|
|
1157
|
+
atRiskThresholdPercentage: data.createdItem.atRiskThresholdPercentage,
|
|
1158
|
+
description: data.createdItem.description,
|
|
1159
|
+
defaultBurnRateRules: data.seededBurnRateRules,
|
|
1160
|
+
});
|
|
1161
|
+
|
|
1162
|
+
await ServiceLevelObjectiveFeedService.createServiceLevelObjectiveFeedItem({
|
|
1163
|
+
serviceLevelObjectiveId: sloId,
|
|
1164
|
+
projectId: projectId,
|
|
1165
|
+
serviceLevelObjectiveFeedEventType:
|
|
1166
|
+
ServiceLevelObjectiveFeedEventType.ServiceLevelObjectiveCreated,
|
|
1167
|
+
displayColor: Green500,
|
|
1168
|
+
feedInfoInMarkdown: markdown.feedInfoInMarkdown,
|
|
1169
|
+
moreInformationInMarkdown: markdown.moreInformationInMarkdown,
|
|
1170
|
+
// Only a user who still exists gets the avatar; otherwise "no user".
|
|
1171
|
+
userId: createdByUserMarkdown ? createdByUserId : undefined,
|
|
1172
|
+
postedAt: data.postedAt,
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
/*
|
|
1177
|
+
* The before-half of the feed's change detection: the watched columns this
|
|
1178
|
+
* payload writes, and every matched SLO as it is before the write.
|
|
1179
|
+
*
|
|
1180
|
+
* Two rules keep this off the hot paths:
|
|
1181
|
+
*
|
|
1182
|
+
* - It reads ONLY when the payload writes a watched column, and that is
|
|
1183
|
+
* checked before any query. The evaluation worker writes this row on
|
|
1184
|
+
* every tick (SLI, budget, burn rate, status) and the cadence stamps go
|
|
1185
|
+
* through here too; none of those columns is watched, so they cost
|
|
1186
|
+
* nothing.
|
|
1187
|
+
*
|
|
1188
|
+
* - A root write of `monitors` is the monitor rule engine keeping
|
|
1189
|
+
* rule-owned monitors in sync. The engine posts its own attach/detach
|
|
1190
|
+
* items, so `monitors` is only watched on a non-root (hand-made) edit -
|
|
1191
|
+
* which also spares every engine sync a read.
|
|
1192
|
+
*
|
|
1193
|
+
* A failed read never blocks the update; the feed just does not describe it.
|
|
1194
|
+
*/
|
|
1195
|
+
private async readFeedSnapshotBeforeUpdate(
|
|
1196
|
+
updateBy: UpdateBy<Model>,
|
|
1197
|
+
): Promise<SloFeedUpdateSnapshot | null> {
|
|
1198
|
+
const columns: Array<SloFeedColumn> = getSloFeedWatchedColumns({
|
|
1199
|
+
payload: updateBy.data,
|
|
1200
|
+
includeMonitors: !updateBy.props.isRoot,
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
if (columns.length === 0) {
|
|
1204
|
+
return null;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
try {
|
|
1208
|
+
const rows: Array<Model> = await this.findBy({
|
|
1209
|
+
// Pinned: this hook runs before DatabaseService applies permissions.
|
|
1210
|
+
query: SloFeedUtil.getTenantPinnedQuery({
|
|
1211
|
+
query: updateBy.query,
|
|
1212
|
+
tenantId: updateBy.props.tenantId,
|
|
1213
|
+
}),
|
|
1214
|
+
select: this.getFeedSelect(columns),
|
|
1215
|
+
limit: updateBy.limit,
|
|
1216
|
+
skip: updateBy.skip,
|
|
1217
|
+
props: {
|
|
1218
|
+
isRoot: true,
|
|
1219
|
+
},
|
|
1220
|
+
});
|
|
1221
|
+
|
|
1222
|
+
const rowsById: Dictionary<Model> = {};
|
|
1223
|
+
|
|
1224
|
+
for (const row of rows) {
|
|
1225
|
+
if (row.id) {
|
|
1226
|
+
rowsById[row.id.toString()] = row;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
return {
|
|
1231
|
+
columns: columns,
|
|
1232
|
+
rowsById: rowsById,
|
|
1233
|
+
};
|
|
1234
|
+
} catch (err) {
|
|
1235
|
+
logger.error(
|
|
1236
|
+
`Error reading SLOs before an update for the SLO feed: ${err}`,
|
|
1237
|
+
);
|
|
1238
|
+
return null;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
private getFeedSelect(columns: Array<SloFeedColumn>): Select<Model> {
|
|
1243
|
+
return {
|
|
1244
|
+
_id: true,
|
|
1245
|
+
projectId: true,
|
|
1246
|
+
name: true,
|
|
1247
|
+
// Both flags word the enable / archive items, whichever one changed.
|
|
1248
|
+
isEnabled: true,
|
|
1249
|
+
isArchived: true,
|
|
1250
|
+
...getSloFeedSelect(columns),
|
|
1251
|
+
} as Select<Model>;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
private async writeSloUpdatedFeed(data: {
|
|
1255
|
+
onUpdate: OnUpdate<Model>;
|
|
1256
|
+
updatedItemIds: Array<ObjectID>;
|
|
1257
|
+
postedAt: Date;
|
|
1258
|
+
}): Promise<void> {
|
|
1259
|
+
const snapshot: SloFeedUpdateSnapshot | null =
|
|
1260
|
+
(data.onUpdate.carryForward?.feedSnapshot as
|
|
1261
|
+
| SloFeedUpdateSnapshot
|
|
1262
|
+
| null
|
|
1263
|
+
| undefined) || null;
|
|
1264
|
+
|
|
1265
|
+
if (
|
|
1266
|
+
!snapshot ||
|
|
1267
|
+
snapshot.columns.length === 0 ||
|
|
1268
|
+
data.updatedItemIds.length === 0
|
|
1269
|
+
) {
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
for (const sloId of data.updatedItemIds) {
|
|
1274
|
+
const before: Model | undefined = snapshot.rowsById[sloId.toString()];
|
|
1275
|
+
|
|
1276
|
+
// Not in the snapshot means there is nothing to compare against.
|
|
1277
|
+
if (!before) {
|
|
1278
|
+
continue;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
try {
|
|
1282
|
+
await this.writeFeedItemsForUpdatedSlo({
|
|
1283
|
+
sloId: sloId,
|
|
1284
|
+
before: before,
|
|
1285
|
+
columns: snapshot.columns,
|
|
1286
|
+
payload: data.onUpdate.updateBy.data as unknown as Record<
|
|
1287
|
+
string,
|
|
1288
|
+
unknown
|
|
1289
|
+
>,
|
|
1290
|
+
userId: data.onUpdate.updateBy.props.userId || undefined,
|
|
1291
|
+
postedAt: data.postedAt,
|
|
1292
|
+
});
|
|
1293
|
+
} catch (err) {
|
|
1294
|
+
logger.error(
|
|
1295
|
+
`Error writing feed items for updated SLO ${sloId.toString()}: ${err}`,
|
|
1296
|
+
{ projectId: before.projectId?.toString() } as LogAttributes,
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
/*
|
|
1303
|
+
* Compares one SLO before and after the write and posts what really
|
|
1304
|
+
* changed: archive / restore, enable / disable, an "updated" item with old
|
|
1305
|
+
* and new values, and hand-made monitor attaches and detaches. A form that
|
|
1306
|
+
* re-submits every field it shows posts nothing for the fields it did not
|
|
1307
|
+
* change.
|
|
1308
|
+
*/
|
|
1309
|
+
private async writeFeedItemsForUpdatedSlo(data: {
|
|
1310
|
+
sloId: ObjectID;
|
|
1311
|
+
before: Model;
|
|
1312
|
+
columns: Array<SloFeedColumn>;
|
|
1313
|
+
payload: Record<string, unknown>;
|
|
1314
|
+
userId: ObjectID | undefined;
|
|
1315
|
+
postedAt: Date;
|
|
1316
|
+
}): Promise<void> {
|
|
1317
|
+
const projectId: ObjectID | undefined = data.before.projectId;
|
|
1318
|
+
|
|
1319
|
+
if (!projectId) {
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
const after: Model | null = await this.findOneById({
|
|
1324
|
+
id: data.sloId,
|
|
1325
|
+
select: this.getFeedSelect(data.columns),
|
|
1326
|
+
props: {
|
|
1327
|
+
isRoot: true,
|
|
1328
|
+
},
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
if (!after) {
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
type IsWatchedFunction = (column: SloFeedColumn) => boolean;
|
|
1336
|
+
|
|
1337
|
+
const isWatched: IsWatchedFunction = (column: SloFeedColumn): boolean => {
|
|
1338
|
+
return data.columns.some((watched: SloFeedColumn): boolean => {
|
|
1339
|
+
return watched.column === column.column;
|
|
1340
|
+
});
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
const beforeRow: SloFeedRow = data.before as unknown as SloFeedRow;
|
|
1344
|
+
const afterRow: SloFeedRow = after as unknown as SloFeedRow;
|
|
1345
|
+
|
|
1346
|
+
// Unset reads as the column defaults: enabled, not archived.
|
|
1347
|
+
const isEnabled: boolean =
|
|
1348
|
+
normalizeSloFeedBoolean(after.isEnabled) !== false;
|
|
1349
|
+
const isArchived: boolean =
|
|
1350
|
+
normalizeSloFeedBoolean(after.isArchived) === true;
|
|
1351
|
+
|
|
1352
|
+
const pendingItems: Array<SloFeedPendingItem> = [];
|
|
1353
|
+
|
|
1354
|
+
if (
|
|
1355
|
+
isWatched(SLO_FEED_IS_ARCHIVED_COLUMN) &&
|
|
1356
|
+
!isSloFeedValueEqual(SLO_FEED_IS_ARCHIVED_COLUMN, beforeRow, afterRow)
|
|
1357
|
+
) {
|
|
1358
|
+
pendingItems.push({
|
|
1359
|
+
eventType: isArchived
|
|
1360
|
+
? ServiceLevelObjectiveFeedEventType.ServiceLevelObjectiveArchived
|
|
1361
|
+
: ServiceLevelObjectiveFeedEventType.ServiceLevelObjectiveRestored,
|
|
1362
|
+
displayColor: isArchived ? Yellow500 : Blue500,
|
|
1363
|
+
getMarkdown: (sloMarkdownLink: string): SloFeedMarkdown => {
|
|
1364
|
+
return getSloArchivedFeedMarkdown({
|
|
1365
|
+
sloMarkdownLink: sloMarkdownLink,
|
|
1366
|
+
isArchived: isArchived,
|
|
1367
|
+
isEnabled: isEnabled,
|
|
1368
|
+
});
|
|
1369
|
+
},
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
if (
|
|
1374
|
+
isWatched(SLO_FEED_IS_ENABLED_COLUMN) &&
|
|
1375
|
+
!isSloFeedValueEqual(SLO_FEED_IS_ENABLED_COLUMN, beforeRow, afterRow)
|
|
1376
|
+
) {
|
|
1377
|
+
pendingItems.push({
|
|
1378
|
+
eventType: isEnabled
|
|
1379
|
+
? ServiceLevelObjectiveFeedEventType.ServiceLevelObjectiveEnabled
|
|
1380
|
+
: ServiceLevelObjectiveFeedEventType.ServiceLevelObjectiveDisabled,
|
|
1381
|
+
displayColor: isEnabled ? Green500 : Gray500,
|
|
1382
|
+
getMarkdown: (sloMarkdownLink: string): SloFeedMarkdown => {
|
|
1383
|
+
return getSloEnabledFeedMarkdown({
|
|
1384
|
+
sloMarkdownLink: sloMarkdownLink,
|
|
1385
|
+
isEnabled: isEnabled,
|
|
1386
|
+
isArchived: isArchived,
|
|
1387
|
+
});
|
|
1388
|
+
},
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
const changes: Array<SloFeedColumnChange> = getSloFeedColumnChanges({
|
|
1393
|
+
columns: data.columns.filter((column: SloFeedColumn): boolean => {
|
|
1394
|
+
return SLO_FEED_UPDATE_COLUMNS.some(
|
|
1395
|
+
(updateColumn: SloFeedColumn): boolean => {
|
|
1396
|
+
return updateColumn.column === column.column;
|
|
1397
|
+
},
|
|
1398
|
+
);
|
|
1399
|
+
}),
|
|
1400
|
+
before: beforeRow,
|
|
1401
|
+
after: afterRow,
|
|
1402
|
+
});
|
|
1403
|
+
|
|
1404
|
+
if (changes.length > 0) {
|
|
1405
|
+
pendingItems.push({
|
|
1406
|
+
eventType:
|
|
1407
|
+
ServiceLevelObjectiveFeedEventType.ServiceLevelObjectiveUpdated,
|
|
1408
|
+
displayColor: Gray500,
|
|
1409
|
+
getMarkdown: (sloMarkdownLink: string): SloFeedMarkdown => {
|
|
1410
|
+
return getSloUpdatedFeedMarkdown({
|
|
1411
|
+
sloMarkdownLink: sloMarkdownLink,
|
|
1412
|
+
changes: changes,
|
|
1413
|
+
});
|
|
1414
|
+
},
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
if (isWatched(SLO_FEED_MONITORS_COLUMN)) {
|
|
1419
|
+
pendingItems.push(
|
|
1420
|
+
...(await this.getManualMonitorFeedItems({
|
|
1421
|
+
projectId: projectId,
|
|
1422
|
+
before: data.before,
|
|
1423
|
+
after: after,
|
|
1424
|
+
writtenMonitors: data.payload["monitors"],
|
|
1425
|
+
})),
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
if (pendingItems.length === 0) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
const sloMarkdownLink: string = await this.getSloMarkdownLink({
|
|
1434
|
+
projectId: projectId,
|
|
1435
|
+
sloId: data.sloId,
|
|
1436
|
+
sloName: after.name || data.before.name || "",
|
|
1437
|
+
});
|
|
1438
|
+
|
|
1439
|
+
for (const pendingItem of pendingItems) {
|
|
1440
|
+
const markdown: SloFeedMarkdown =
|
|
1441
|
+
pendingItem.getMarkdown(sloMarkdownLink);
|
|
1442
|
+
|
|
1443
|
+
await ServiceLevelObjectiveFeedService.createServiceLevelObjectiveFeedItem(
|
|
1444
|
+
{
|
|
1445
|
+
serviceLevelObjectiveId: data.sloId,
|
|
1446
|
+
projectId: projectId,
|
|
1447
|
+
serviceLevelObjectiveFeedEventType: pendingItem.eventType,
|
|
1448
|
+
displayColor: pendingItem.displayColor,
|
|
1449
|
+
feedInfoInMarkdown: markdown.feedInfoInMarkdown,
|
|
1450
|
+
moreInformationInMarkdown: markdown.moreInformationInMarkdown,
|
|
1451
|
+
userId: data.userId,
|
|
1452
|
+
postedAt: data.postedAt,
|
|
1453
|
+
},
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/*
|
|
1459
|
+
* MonitorsAttached / MonitorsDetached for a hand-made edit of the monitor
|
|
1460
|
+
* set (the rule engine's root writes never get here - see
|
|
1461
|
+
* readFeedSnapshotBeforeUpdate).
|
|
1462
|
+
*
|
|
1463
|
+
* The new set is taken from the PAYLOAD, not from the re-read row: this
|
|
1464
|
+
* writer runs after the request, and by then a rule sync may already have
|
|
1465
|
+
* written the SLO's monitors again. Diffing against that would re-describe
|
|
1466
|
+
* the engine's own changes, which the engine posts itself. The re-read is
|
|
1467
|
+
* used only to put names on the monitors that were attached.
|
|
1468
|
+
*/
|
|
1469
|
+
private async getManualMonitorFeedItems(data: {
|
|
1470
|
+
projectId: ObjectID;
|
|
1471
|
+
before: Model;
|
|
1472
|
+
after: Model;
|
|
1473
|
+
writtenMonitors: unknown;
|
|
1474
|
+
}): Promise<Array<SloFeedPendingItem>> {
|
|
1475
|
+
const beforeIds: Set<string> = new Set<string>(
|
|
1476
|
+
getSloFeedEntityIds(data.before.monitors),
|
|
1477
|
+
);
|
|
1478
|
+
const writtenIds: Set<string> = new Set<string>(
|
|
1479
|
+
getSloFeedEntityIds(data.writtenMonitors),
|
|
1480
|
+
);
|
|
1481
|
+
|
|
1482
|
+
const attachedIds: Array<string> = Array.from(writtenIds).filter(
|
|
1483
|
+
(id: string): boolean => {
|
|
1484
|
+
return !beforeIds.has(id);
|
|
1485
|
+
},
|
|
1486
|
+
);
|
|
1487
|
+
const detachedIds: Array<string> = Array.from(beforeIds).filter(
|
|
1488
|
+
(id: string): boolean => {
|
|
1489
|
+
return !writtenIds.has(id);
|
|
1490
|
+
},
|
|
1491
|
+
);
|
|
1492
|
+
|
|
1493
|
+
if (attachedIds.length === 0 && detachedIds.length === 0) {
|
|
1494
|
+
return [];
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
const nameById: Dictionary<string> = {};
|
|
1498
|
+
|
|
1499
|
+
for (const monitor of [
|
|
1500
|
+
...(data.before.monitors || []),
|
|
1501
|
+
...(data.after.monitors || []),
|
|
1502
|
+
] as Array<Monitor>) {
|
|
1503
|
+
const id: string | undefined = getSloFeedEntityIds([monitor])[0];
|
|
1504
|
+
|
|
1505
|
+
if (id && monitor.name) {
|
|
1506
|
+
nameById[id] = monitor.name;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
|
|
1511
|
+
|
|
1512
|
+
type ToReferencesFunction = (
|
|
1513
|
+
ids: Array<string>,
|
|
1514
|
+
) => Array<SloFeedMonitorReference>;
|
|
1515
|
+
|
|
1516
|
+
const toReferences: ToReferencesFunction = (
|
|
1517
|
+
ids: Array<string>,
|
|
1518
|
+
): Array<SloFeedMonitorReference> => {
|
|
1519
|
+
return ids.map((id: string): SloFeedMonitorReference => {
|
|
1520
|
+
return {
|
|
1521
|
+
name: nameById[id] || "",
|
|
1522
|
+
link: SloFeedUtil.getMonitorLinkInDashboard({
|
|
1523
|
+
dashboardUrl: dashboardUrl,
|
|
1524
|
+
projectId: data.projectId,
|
|
1525
|
+
monitorId: id,
|
|
1526
|
+
}),
|
|
1527
|
+
};
|
|
1528
|
+
});
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1531
|
+
const items: Array<SloFeedPendingItem> = [];
|
|
1532
|
+
|
|
1533
|
+
if (attachedIds.length > 0) {
|
|
1534
|
+
const attached: Array<SloFeedMonitorReference> =
|
|
1535
|
+
toReferences(attachedIds);
|
|
1536
|
+
|
|
1537
|
+
items.push({
|
|
1538
|
+
eventType: ServiceLevelObjectiveFeedEventType.MonitorsAttached,
|
|
1539
|
+
displayColor: Blue500,
|
|
1540
|
+
getMarkdown: (sloMarkdownLink: string): SloFeedMarkdown => {
|
|
1541
|
+
return getSloMonitorsChangedFeedMarkdown({
|
|
1542
|
+
sloMarkdownLink: sloMarkdownLink,
|
|
1543
|
+
monitors: attached,
|
|
1544
|
+
change: "attached",
|
|
1545
|
+
});
|
|
1546
|
+
},
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
if (detachedIds.length > 0) {
|
|
1551
|
+
const detached: Array<SloFeedMonitorReference> =
|
|
1552
|
+
toReferences(detachedIds);
|
|
1553
|
+
|
|
1554
|
+
items.push({
|
|
1555
|
+
eventType: ServiceLevelObjectiveFeedEventType.MonitorsDetached,
|
|
1556
|
+
displayColor: Orange500,
|
|
1557
|
+
getMarkdown: (sloMarkdownLink: string): SloFeedMarkdown => {
|
|
1558
|
+
return getSloMonitorsChangedFeedMarkdown({
|
|
1559
|
+
sloMarkdownLink: sloMarkdownLink,
|
|
1560
|
+
monitors: detached,
|
|
1561
|
+
change: "detached",
|
|
1562
|
+
});
|
|
1563
|
+
},
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
return items;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
/*
|
|
1571
|
+
* What a write of the deprecated "Auto-Add Monitors With Labels" list
|
|
1572
|
+
* (ServiceLevelObjective.monitorLabels) does on this release.
|
|
1573
|
+
*
|
|
1574
|
+
* The column stays in the API so upgrades do not break, and it is still
|
|
1575
|
+
* written: a dashboard tab opened before the upgrade sends it with every
|
|
1576
|
+
* save of the SLO form, and so can an API client or a workflow written
|
|
1577
|
+
* against the previous release. Workflows write as root, which is why every
|
|
1578
|
+
* caller is handled here, not only users - nothing on this release writes
|
|
1579
|
+
* the column for its own reasons. Nothing else on this release reads it
|
|
1580
|
+
* either, so storing it and moving on left the SLO measuring something other
|
|
1581
|
+
* than what the caller had just saved. It is applied instead, the way this
|
|
1582
|
+
* release applies labels - as a monitor rule:
|
|
1583
|
+
*
|
|
1584
|
+
* - An SLO with no monitor rule row gets the list as a rule
|
|
1585
|
+
* (SloLegacyMonitorLabelAdoption) and is re-synced straight away, so its
|
|
1586
|
+
* monitors reflect the list at once. A list cleared to empty has nothing
|
|
1587
|
+
* to adopt, and the sync releases the monitors it attached - both what
|
|
1588
|
+
* the previous release did.
|
|
1589
|
+
* - An SLO that already has monitor rules, enabled or disabled, IGNORES
|
|
1590
|
+
* the list, with a warning in the log when the list changed. Its rules
|
|
1591
|
+
* are what it measures and what its Monitor Rules page shows. Folding the
|
|
1592
|
+
* list into one of them was rejected: the form that sends it cannot show
|
|
1593
|
+
* rules and re-submits the list it loaded, so it would undo edits made on
|
|
1594
|
+
* the Monitor Rules page, and once the converted rule has been renamed,
|
|
1595
|
+
* edited or deleted there is no rule the list reliably "is".
|
|
1596
|
+
*
|
|
1597
|
+
* Only a CHANGED list is adopted without evidence. The same list re-submitted
|
|
1598
|
+
* by an out-of-date form is adopted only while monitors are still attached
|
|
1599
|
+
* by it (the previous release's engine attached them), so re-saving that
|
|
1600
|
+
* form cannot bring back a converted rule the user deleted. See
|
|
1601
|
+
* readDeprecatedMonitorLabelsBeforeUpdate.
|
|
1602
|
+
*
|
|
1603
|
+
* Never throws: the write has landed, and a failure here must not fail the
|
|
1604
|
+
* request. An SLO whose adoption failed is not synced this time, because a
|
|
1605
|
+
* sync without its rule would release the monitors the list attached.
|
|
1606
|
+
*/
|
|
1607
|
+
private async applyDeprecatedMonitorLabelWrite(data: {
|
|
1608
|
+
serviceLevelObjectiveIds: Array<ObjectID>;
|
|
1609
|
+
writtenMonitorLabels: unknown;
|
|
1610
|
+
labelIdsBeforeUpdateBySloId: Dictionary<Array<string>>;
|
|
1611
|
+
}): Promise<void> {
|
|
1612
|
+
// One adoption call per project, and per answer to "is evidence needed".
|
|
1613
|
+
interface AdoptionGroup {
|
|
1614
|
+
projectId: ObjectID;
|
|
1615
|
+
requireRuleAttachedMonitors: boolean;
|
|
1616
|
+
serviceLevelObjectiveIds: Array<string>;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
try {
|
|
1620
|
+
// Sorted, de-duplicated and lower-case, so two lists compare joined.
|
|
1621
|
+
const writtenLabelIds: Array<string> = getSloFeedEntityIds(
|
|
1622
|
+
data.writtenMonitorLabels,
|
|
1623
|
+
);
|
|
1624
|
+
|
|
1625
|
+
// Root, by id: these are the rows the permission-checked write changed.
|
|
1626
|
+
const slos: Array<Model> = await this.findBy({
|
|
1627
|
+
query: {
|
|
1628
|
+
_id: QueryHelper.any(data.serviceLevelObjectiveIds),
|
|
1629
|
+
},
|
|
1630
|
+
select: {
|
|
1631
|
+
_id: true,
|
|
1632
|
+
projectId: true,
|
|
1633
|
+
},
|
|
1634
|
+
limit: data.serviceLevelObjectiveIds.length,
|
|
1635
|
+
skip: 0,
|
|
1636
|
+
props: {
|
|
1637
|
+
isRoot: true,
|
|
1638
|
+
},
|
|
1639
|
+
});
|
|
1640
|
+
|
|
1641
|
+
const sloIdsWithRules: Set<string> =
|
|
1642
|
+
await ServiceLevelObjectiveMonitorRuleService.findServiceLevelObjectiveIdsWithAnyRule(
|
|
1643
|
+
slos
|
|
1644
|
+
.map((slo: Model): ObjectID | null => {
|
|
1645
|
+
return slo.id;
|
|
1646
|
+
})
|
|
1647
|
+
.filter((id: ObjectID | null): id is ObjectID => {
|
|
1648
|
+
return Boolean(id);
|
|
1649
|
+
}),
|
|
1650
|
+
);
|
|
1651
|
+
|
|
1652
|
+
const adoptionGroups: Map<string, AdoptionGroup> = new Map<
|
|
1653
|
+
string,
|
|
1654
|
+
AdoptionGroup
|
|
1655
|
+
>();
|
|
1656
|
+
const sloIdsToSync: Array<string> = [];
|
|
1657
|
+
|
|
1658
|
+
for (const slo of slos) {
|
|
1659
|
+
if (!slo.id || !slo.projectId) {
|
|
1660
|
+
continue;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
const sloId: string = slo.id.toString().toLowerCase();
|
|
1664
|
+
|
|
1665
|
+
const labelIdsBeforeUpdate: Array<string> | undefined =
|
|
1666
|
+
data.labelIdsBeforeUpdateBySloId[sloId];
|
|
1667
|
+
|
|
1668
|
+
// Unknown (the read before the write failed) counts as re-submitted.
|
|
1669
|
+
const isListChanged: boolean =
|
|
1670
|
+
labelIdsBeforeUpdate !== undefined &&
|
|
1671
|
+
labelIdsBeforeUpdate.join(",") !== writtenLabelIds.join(",");
|
|
1672
|
+
|
|
1673
|
+
if (sloIdsWithRules.has(sloId)) {
|
|
1674
|
+
if (isListChanged) {
|
|
1675
|
+
logger.warn(
|
|
1676
|
+
`Ignored a change to the deprecated "Auto-Add Monitors With Labels" list of SLO ${sloId}: the SLO has monitor rules, and they decide which monitors it measures. Change its monitor rules instead.`,
|
|
1677
|
+
{
|
|
1678
|
+
projectId: slo.projectId.toString(),
|
|
1679
|
+
serviceLevelObjectiveId: sloId,
|
|
1680
|
+
} as LogAttributes,
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
continue;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
sloIdsToSync.push(sloId);
|
|
1688
|
+
|
|
1689
|
+
// An empty list has nothing to adopt; the sync alone releases it.
|
|
1690
|
+
if (writtenLabelIds.length === 0) {
|
|
1691
|
+
continue;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
const groupKey: string = `${slo.projectId.toString()}|${isListChanged}`;
|
|
1695
|
+
|
|
1696
|
+
const group: AdoptionGroup = adoptionGroups.get(groupKey) || {
|
|
1697
|
+
projectId: slo.projectId,
|
|
1698
|
+
requireRuleAttachedMonitors: !isListChanged,
|
|
1699
|
+
serviceLevelObjectiveIds: [],
|
|
1700
|
+
};
|
|
1701
|
+
|
|
1702
|
+
group.serviceLevelObjectiveIds.push(sloId);
|
|
1703
|
+
adoptionGroups.set(groupKey, group);
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
const sloIdsNotToSync: Set<string> = new Set<string>();
|
|
1707
|
+
|
|
1708
|
+
for (const group of adoptionGroups.values()) {
|
|
1709
|
+
try {
|
|
1710
|
+
await SloLegacyMonitorLabelAdoption.adoptLegacyMonitorLabels({
|
|
1711
|
+
projectId: group.projectId,
|
|
1712
|
+
serviceLevelObjectiveIds: group.serviceLevelObjectiveIds,
|
|
1713
|
+
requireRuleAttachedMonitors: group.requireRuleAttachedMonitors,
|
|
1714
|
+
});
|
|
1715
|
+
} catch (err) {
|
|
1716
|
+
logger.error(
|
|
1717
|
+
`Error converting the deprecated monitor label list of SLOs ${group.serviceLevelObjectiveIds.join(", ")} into monitor rules; not re-syncing their monitors this time: ${err}`,
|
|
1718
|
+
{ projectId: group.projectId.toString() } as LogAttributes,
|
|
1719
|
+
);
|
|
1720
|
+
|
|
1721
|
+
for (const sloId of group.serviceLevelObjectiveIds) {
|
|
1722
|
+
sloIdsNotToSync.add(sloId);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
for (const sloId of sloIdsToSync) {
|
|
1728
|
+
if (sloIdsNotToSync.has(sloId)) {
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
try {
|
|
1733
|
+
await ServiceLevelObjectiveMonitorRuleEngineService.syncMonitorsForSlo(
|
|
1734
|
+
{
|
|
1735
|
+
serviceLevelObjectiveId: new ObjectID(sloId),
|
|
1736
|
+
},
|
|
1737
|
+
);
|
|
1738
|
+
} catch (err) {
|
|
1739
|
+
// One SLO failing must not cost the others their sync.
|
|
1740
|
+
logger.error(
|
|
1741
|
+
`Error applying the monitor rules of SLO ${sloId} after its deprecated monitor label list was written: ${err}`,
|
|
1742
|
+
);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
} catch (err) {
|
|
1746
|
+
logger.error(
|
|
1747
|
+
`Error applying a write of the deprecated SLO monitor label list: ${err}`,
|
|
1748
|
+
);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
/*
|
|
1753
|
+
* The create half of applyDeprecatedMonitorLabelWrite: a create carrying a
|
|
1754
|
+
* non-empty deprecated label list gets it as a monitor rule before
|
|
1755
|
+
* onCreateSuccess syncs the SLO's monitors. No evidence is asked for - a
|
|
1756
|
+
* brand-new SLO has attached nothing and has no deleted rule to bring back -
|
|
1757
|
+
* and it cannot have rules yet, so there is nothing to ignore it for.
|
|
1758
|
+
*
|
|
1759
|
+
* Never throws. A failed adoption is logged and leaves the SLO without the
|
|
1760
|
+
* rule; the sync after it releases nothing, because nothing is attached yet.
|
|
1761
|
+
*/
|
|
1762
|
+
private async adoptDeprecatedMonitorLabelsWrittenOnCreate(
|
|
1763
|
+
createdItem: Model,
|
|
1764
|
+
): Promise<void> {
|
|
1765
|
+
if (
|
|
1766
|
+
!createdItem.id ||
|
|
1767
|
+
!createdItem.projectId ||
|
|
1768
|
+
getSloFeedEntityIds(createdItem.monitorLabels).length === 0
|
|
1769
|
+
) {
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
try {
|
|
1774
|
+
await SloLegacyMonitorLabelAdoption.adoptLegacyMonitorLabels({
|
|
1775
|
+
projectId: createdItem.projectId,
|
|
1776
|
+
serviceLevelObjectiveIds: [createdItem.id],
|
|
1777
|
+
requireRuleAttachedMonitors: false,
|
|
1778
|
+
});
|
|
1779
|
+
} catch (err) {
|
|
1780
|
+
logger.error(
|
|
1781
|
+
`Error converting the deprecated monitor label list of new SLO ${createdItem.id.toString()} into a monitor rule: ${err}`,
|
|
1782
|
+
{ projectId: createdItem.projectId.toString() } as LogAttributes,
|
|
1783
|
+
);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
/*
|
|
1788
|
+
* The deprecated label list of every SLO this update may write, as it is
|
|
1789
|
+
* BEFORE the write, keyed by lower-case SLO id - or null when the payload
|
|
1790
|
+
* does not write that list, which is every update this release's own
|
|
1791
|
+
* clients make, so they pay nothing.
|
|
1792
|
+
*
|
|
1793
|
+
* applyDeprecatedMonitorLabelWrite compares it with the written list,
|
|
1794
|
+
* because only a CHANGED list is somebody asking for something: an
|
|
1795
|
+
* out-of-date SLO form re-sends every field it loaded, labels included, on
|
|
1796
|
+
* every save.
|
|
1797
|
+
*
|
|
1798
|
+
* Pinned to the caller's tenant like the feed snapshot, since this runs
|
|
1799
|
+
* before DatabaseService applies the update's permissions. A failed read
|
|
1800
|
+
* never blocks the update; its SLOs then count as re-submitting their list,
|
|
1801
|
+
* the reading that can never bring a deleted rule back.
|
|
1802
|
+
*/
|
|
1803
|
+
private async readDeprecatedMonitorLabelsBeforeUpdate(
|
|
1804
|
+
updateBy: UpdateBy<Model>,
|
|
1805
|
+
): Promise<Dictionary<Array<string>> | null> {
|
|
1806
|
+
if ((updateBy.data.monitorLabels as unknown) === undefined) {
|
|
1807
|
+
return null;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
const labelIdsBySloId: Dictionary<Array<string>> = {};
|
|
1811
|
+
|
|
1812
|
+
try {
|
|
1813
|
+
const rows: Array<Model> = await this.findBy({
|
|
1814
|
+
query: SloFeedUtil.getTenantPinnedQuery({
|
|
1815
|
+
query: updateBy.query,
|
|
1816
|
+
tenantId: updateBy.props.tenantId,
|
|
1817
|
+
}),
|
|
1818
|
+
select: {
|
|
1819
|
+
_id: true,
|
|
1820
|
+
monitorLabels: {
|
|
1821
|
+
_id: true,
|
|
1822
|
+
},
|
|
1823
|
+
},
|
|
1824
|
+
limit: updateBy.limit,
|
|
1825
|
+
skip: updateBy.skip,
|
|
1826
|
+
props: {
|
|
1827
|
+
isRoot: true,
|
|
1828
|
+
},
|
|
1829
|
+
});
|
|
1830
|
+
|
|
1831
|
+
for (const row of rows) {
|
|
1832
|
+
if (row.id) {
|
|
1833
|
+
labelIdsBySloId[row.id.toString().toLowerCase()] =
|
|
1834
|
+
getSloFeedEntityIds(row.monitorLabels);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
} catch (err) {
|
|
1838
|
+
logger.error(
|
|
1839
|
+
`Error reading SLO monitor label lists before an update: ${err}`,
|
|
1840
|
+
);
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
return labelIdsBySloId;
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
/*
|
|
1847
|
+
* The manual-add guard. While an SLO has at least one ENABLED monitor rule,
|
|
1848
|
+
* its monitor list belongs to those rules, so a hand-edit may only take away
|
|
1849
|
+
* monitors a person attached:
|
|
1850
|
+
*
|
|
1851
|
+
* - adding a monitor that is not already attached is refused - the rules
|
|
1852
|
+
* decide what is measured, and the Monitors page says so;
|
|
1853
|
+
* - removing a monitor a rule attached is refused too - it would not
|
|
1854
|
+
* stick: it stays recorded in autoAddedMonitors and the next sync would
|
|
1855
|
+
* attach it again, which reads as the edit silently failing;
|
|
1856
|
+
* - removing a monitor attached by hand (before the rules were enabled)
|
|
1857
|
+
* stays allowed.
|
|
1858
|
+
*
|
|
1859
|
+
* Root writes pass untouched: the rule engine itself writes `monitors` as
|
|
1860
|
+
* root, and it must never be refused by the guard that protects its output.
|
|
1861
|
+
*
|
|
1862
|
+
* This hook runs before DatabaseService's update permission check, so the
|
|
1863
|
+
* caller's raw query is pinned to the caller's tenant before anything is
|
|
1864
|
+
* read - a validation read must not answer questions about another
|
|
1865
|
+
* project's SLOs.
|
|
1866
|
+
*/
|
|
1867
|
+
private async assertMonitorEditRespectsMonitorRules(
|
|
1868
|
+
updateBy: UpdateBy<Model>,
|
|
1869
|
+
): Promise<void> {
|
|
1870
|
+
const nextMonitors: unknown = updateBy.data.monitors as unknown;
|
|
1871
|
+
|
|
1872
|
+
if (nextMonitors === undefined || updateBy.props.isRoot) {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
const query: Record<string, unknown> = {
|
|
1877
|
+
...(updateBy.query as Record<string, unknown>),
|
|
1878
|
+
};
|
|
1879
|
+
|
|
1880
|
+
if (updateBy.props.tenantId) {
|
|
1881
|
+
query["projectId"] = updateBy.props.tenantId;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
const slos: Array<Model> = await this.findBy({
|
|
1885
|
+
query: query as UpdateBy<Model>["query"],
|
|
1886
|
+
select: {
|
|
1887
|
+
_id: true,
|
|
1888
|
+
monitors: {
|
|
1889
|
+
_id: true,
|
|
1890
|
+
},
|
|
1891
|
+
autoAddedMonitors: {
|
|
1892
|
+
_id: true,
|
|
1893
|
+
},
|
|
1894
|
+
},
|
|
1895
|
+
limit: LIMIT_PER_PROJECT,
|
|
1896
|
+
skip: 0,
|
|
1897
|
+
props: {
|
|
1898
|
+
isRoot: true,
|
|
1899
|
+
},
|
|
1900
|
+
});
|
|
1901
|
+
|
|
1902
|
+
const sloIds: Array<ObjectID> = slos
|
|
1903
|
+
.map((slo: Model): ObjectID | null => {
|
|
1904
|
+
return slo.id;
|
|
1905
|
+
})
|
|
1906
|
+
.filter((id: ObjectID | null): id is ObjectID => {
|
|
1907
|
+
return Boolean(id);
|
|
1908
|
+
});
|
|
1909
|
+
|
|
1910
|
+
if (sloIds.length === 0) {
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
const sloIdsWithEnabledRules: Set<string> =
|
|
1915
|
+
await ServiceLevelObjectiveMonitorRuleService.findServiceLevelObjectiveIdsWithEnabledRules(
|
|
1916
|
+
sloIds,
|
|
1917
|
+
);
|
|
1918
|
+
|
|
1919
|
+
if (sloIdsWithEnabledRules.size === 0) {
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
const nextMonitorIds: Set<string> = this.toMonitorIdSet(nextMonitors);
|
|
1924
|
+
|
|
1925
|
+
for (const slo of slos) {
|
|
1926
|
+
if (
|
|
1927
|
+
!slo.id ||
|
|
1928
|
+
!sloIdsWithEnabledRules.has(slo.id.toString().toLowerCase())
|
|
1929
|
+
) {
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
const attachedMonitorIds: Set<string> = this.toMonitorIdSet(slo.monitors);
|
|
1934
|
+
|
|
1935
|
+
const isAddingMonitors: boolean = Array.from(nextMonitorIds).some(
|
|
1936
|
+
(monitorId: string): boolean => {
|
|
1937
|
+
return !attachedMonitorIds.has(monitorId);
|
|
1938
|
+
},
|
|
1939
|
+
);
|
|
1940
|
+
|
|
1941
|
+
if (isAddingMonitors) {
|
|
1942
|
+
throw new BadDataException(
|
|
1943
|
+
"This SLO's monitors are managed by its monitor rules. Disable the rules to add monitors by hand.",
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
const isRemovingRuleAttachedMonitors: boolean = Array.from(
|
|
1948
|
+
this.toMonitorIdSet(slo.autoAddedMonitors),
|
|
1949
|
+
).some((monitorId: string): boolean => {
|
|
1950
|
+
return (
|
|
1951
|
+
attachedMonitorIds.has(monitorId) && !nextMonitorIds.has(monitorId)
|
|
1952
|
+
);
|
|
1953
|
+
});
|
|
1954
|
+
|
|
1955
|
+
if (isRemovingRuleAttachedMonitors) {
|
|
1956
|
+
throw new BadDataException(
|
|
1957
|
+
"A monitor rule attached this monitor, so removing it by hand would not stick: the rule would attach it again. Change or disable the rule to detach it.",
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
/*
|
|
1964
|
+
* Monitor ids from any shape they reach this service in: Monitor rows from
|
|
1965
|
+
* a read, `{ _id }` stubs or bare uuid strings from an API payload (which
|
|
1966
|
+
* DatabaseService only turns into entities after onBeforeUpdate). Lower-case,
|
|
1967
|
+
* because Postgres renders a uuid lower-case whatever case it was written in.
|
|
1968
|
+
*/
|
|
1969
|
+
private toMonitorIdSet(value: unknown): Set<string> {
|
|
1970
|
+
const items: Array<unknown> = Array.isArray(value)
|
|
1971
|
+
? value
|
|
1972
|
+
: value === null || value === undefined
|
|
1973
|
+
? []
|
|
1974
|
+
: [value];
|
|
1975
|
+
|
|
1976
|
+
const ids: Set<string> = new Set<string>();
|
|
1977
|
+
|
|
1978
|
+
for (const item of items) {
|
|
1979
|
+
const id: string =
|
|
1980
|
+
resolveReferenceId(item)?.toString().trim().toLowerCase() || "";
|
|
1981
|
+
|
|
1982
|
+
if (id) {
|
|
1983
|
+
ids.add(id);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
return ids;
|
|
688
1988
|
}
|
|
689
1989
|
|
|
690
1990
|
private roundToTwoDecimals(value: number): number {
|