@oneuptime/common 11.7.2 → 11.7.4
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/KubernetesCostAllocation.ts +103 -0
- package/Models/DatabaseModels/AlertEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/AlertStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/Index.ts +5 -0
- package/Models/DatabaseModels/LogDropFilter.ts +89 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +13 -3
- package/Models/DatabaseModels/RecommendationDismissal.ts +463 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/StatusPageGroup.ts +95 -0
- package/Models/DatabaseModels/TableView.ts +40 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +89 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +5 -1
- package/Server/API/AlertAPI.ts +32 -17
- package/Server/API/BaseAPI.ts +31 -2
- package/Server/API/BaseAnalyticsAPI.ts +36 -2
- package/Server/API/CommonAPI.ts +57 -0
- package/Server/API/IncidentAPI.ts +60 -33
- package/Server/API/IncidentEpisodeAPI.ts +31 -16
- package/Server/API/MonitorAPI.ts +30 -0
- package/Server/API/MonitorTemplateAPI.ts +8 -0
- package/Server/API/ProbeAPI.ts +196 -15
- package/Server/API/ProjectAPI.ts +79 -1
- package/Server/API/ScheduledMaintenanceAPI.ts +33 -18
- package/Server/API/StatusPageAPI.ts +74 -37
- package/Server/API/WorkspaceNotificationRuleAPI.ts +34 -4
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.ts +13 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.ts +527 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.ts +53 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AlertEpisodeService.ts +47 -0
- package/Server/Services/AlertService.ts +125 -0
- package/Server/Services/BillingService.ts +98 -0
- package/Server/Services/DatabaseService.ts +184 -20
- package/Server/Services/IncidentEpisodeService.ts +47 -0
- package/Server/Services/IncidentService.ts +123 -0
- package/Server/Services/IncidentTemplateService.ts +123 -1
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/LogDropFilterService.ts +133 -0
- package/Server/Services/MonitorProbeService.ts +94 -4
- package/Server/Services/MonitorService.ts +48 -43
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +70 -0
- package/Server/Services/ProbeService.ts +66 -0
- package/Server/Services/ProjectService.ts +131 -7
- package/Server/Services/RecommendationDismissalService.ts +52 -0
- package/Server/Services/RunbookAgentJobService.ts +68 -7
- package/Server/Services/ScheduledMaintenanceService.ts +103 -0
- package/Server/Services/ScheduledMaintenanceTemplateService.ts +90 -0
- package/Server/Services/StatusPageGroupService.ts +186 -0
- package/Server/Services/TraceDropFilterService.ts +133 -0
- package/Server/Types/Workflow/Components/API/Delete.ts +12 -0
- package/Server/Types/Workflow/Components/API/Get.ts +12 -0
- package/Server/Types/Workflow/Components/API/Patch.ts +12 -0
- package/Server/Types/Workflow/Components/API/Post.ts +12 -0
- package/Server/Types/Workflow/Components/API/Put.ts +13 -0
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +212 -0
- package/Server/Utils/DropFilterValidation.ts +127 -0
- package/Server/Utils/Errors.ts +5 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
- package/Server/Utils/Monitor/MonitorIncident.ts +31 -2
- package/Server/Utils/Telemetry/AppMetrics.ts +31 -0
- package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
- package/Tests/Models/DatabaseModels/MonitorProbeColumnAccessControl.test.ts +196 -0
- package/Tests/Models/RecommendationDismissalModel.test.ts +269 -0
- package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +320 -0
- package/Tests/Server/API/BaseAnalyticsAPIUpdatePayloadValidation.test.ts +293 -0
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +164 -0
- package/Tests/Server/API/ProbeAPI.test.ts +422 -53
- package/Tests/Server/API/ProjectAPI.test.ts +180 -0
- package/Tests/Server/API/ProjectAPIExtendTrialBillingDisabled.test.ts +138 -0
- package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +458 -0
- package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +359 -0
- package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +427 -0
- package/Tests/Server/Services/BillingServiceExtendTrial.test.ts +439 -0
- package/Tests/Server/Services/CrossProjectReferenceWriteGuard.test.ts +810 -0
- package/Tests/Server/Services/DatabaseServiceAtomicAddToColumns.test.ts +269 -0
- package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +277 -0
- package/Tests/Server/Services/DatabaseServiceSortColumnSelect.test.ts +201 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +81 -23
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +398 -0
- package/Tests/Server/Services/MonitorProbeDeleteHooks.test.ts +280 -0
- package/Tests/Server/Services/MonitorProbeServiceProbeTenancy.test.ts +304 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +262 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +614 -0
- package/Tests/Server/Services/RecommendationDismissalService.test.ts +306 -0
- package/Tests/Server/Services/RepairCrossProjectIncidentReferencesMigration.test.ts +528 -0
- package/Tests/Server/Services/StatusPageGroupNesting.test.ts +395 -0
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +26 -21
- package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +227 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +285 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +463 -0
- package/Tests/Server/Utils/DropFilterValidation.test.ts +269 -0
- package/Tests/Server/Utils/Telemetry/SpanUtil.test.ts +94 -0
- package/Tests/Types/DateUserTimezone.test.ts +52 -0
- package/Tests/Types/JSONFunctions.test.ts +103 -1
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +177 -9
- package/Tests/Types/Monitor/MonitorStepDnsMonitor.test.ts +105 -0
- package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +131 -0
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +60 -0
- package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +82 -0
- package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +268 -0
- package/Tests/Types/Monitor/MonitorStepMetricMonitor.test.ts +386 -0
- package/Tests/Types/Monitor/MonitorStepProfileMonitor.test.ts +185 -0
- package/Tests/Types/Monitor/MonitorStepSnmpMonitor.test.ts +156 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +371 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +901 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +607 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +754 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +960 -0
- package/Tests/Types/RollingTime/RollingTimeUtil.test.ts +186 -0
- package/Tests/Types/Runbook/RunbookStepTimeout.test.ts +410 -0
- package/Tests/Types/Telemetry/DropFilterSampling.test.ts +241 -0
- package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +353 -0
- package/Tests/Types/Workspace/NotificationRuleUtil.test.ts +566 -0
- package/Tests/UI/Components/CodeEditor.test.tsx +174 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +555 -24
- package/Tests/UI/Components/InfoCard.test.tsx +358 -0
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +138 -0
- package/Tests/UI/Components/Modal.test.tsx +43 -5
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +397 -0
- package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +999 -0
- package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -0
- package/Tests/UI/Components/Runbook/StepTimeoutInput.test.tsx +386 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +671 -0
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +404 -0
- package/Tests/UI/Utils/DropdownAlignment.test.ts +306 -0
- package/Tests/UI/Utils/TableFilterUrlState.test.ts +292 -0
- package/Tests/Utils/Monitor/MonitorSummaryProbeUtil.test.ts +263 -0
- package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +583 -0
- package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +1072 -0
- package/Tests/Utils/StatusPage/GroupTree.test.ts +583 -0
- package/Tests/Utils/StatusPage/ResourceUptime.test.ts +411 -0
- package/Tests/Utils/UserPreferences.test.ts +563 -0
- package/Types/Date.ts +15 -6
- package/Types/JSONFunctions.ts +7 -2
- package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
- package/Types/Monitor/KubernetesAlertTemplates.ts +205 -0
- package/Types/Monitor/MonitorStep.ts +10 -1
- package/Types/Monitor/MonitorStepMetricMonitor.ts +46 -1
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +413 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +168 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +175 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +743 -0
- package/Types/Permission.ts +45 -0
- package/Types/Recommendation/RecommendationType.ts +20 -0
- package/Types/Runbook/RunbookExecutionDeadline.ts +129 -0
- package/Types/Runbook/RunbookStepTimeout.ts +202 -0
- package/Types/Telemetry/DropFilterSampling.ts +92 -0
- package/UI/Components/AI/GenerateFromAIModal.tsx +0 -2
- package/UI/Components/Accordion/Accordion.tsx +10 -2
- package/UI/Components/BulkUpdate/BulkLabelActions.tsx +0 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +34 -20
- package/UI/Components/Date/RangeStartAndEndDateView.tsx +0 -1
- package/UI/Components/EditionLabel/EditionLabel.tsx +1 -27
- package/UI/Components/Error/PageError.tsx +0 -4
- package/UI/Components/ErrorBoundary.tsx +252 -15
- package/UI/Components/InfoCard/InfoCard.tsx +58 -1
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +34 -1
- package/UI/Components/MasterPage/MasterPage.tsx +65 -0
- package/UI/Components/Modal/Modal.tsx +16 -60
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +0 -8
- package/UI/Components/ModelTable/BaseModelTable.tsx +503 -71
- package/UI/Components/ModelTable/Column.ts +17 -0
- package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +523 -0
- package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
- package/UI/Components/ModelTable/TableView.tsx +24 -2
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
- package/UI/Components/Runbook/StepTimeoutInput.tsx +173 -0
- package/UI/Components/SideMenu/SideMenu.tsx +24 -4
- package/UI/Components/StatusPage/ResourceGroupSection.tsx +231 -0
- package/UI/Components/Table/Table.tsx +14 -1
- package/UI/Components/Table/TableRow.tsx +180 -175
- package/UI/Components/Table/Types/Column.ts +2 -0
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +34 -1
- package/UI/Utils/DropdownAlignment.ts +162 -0
- package/UI/Utils/TableFilterUrlState.ts +59 -20
- package/Utils/API.ts +106 -2
- package/Utils/Monitor/MonitorSummaryProbeUtil.ts +130 -0
- package/Utils/NetworkDiscovery/ScanTargetUtil.ts +434 -0
- package/Utils/StatusPage/GroupNestingLayout.ts +343 -0
- package/Utils/StatusPage/GroupTree.ts +307 -0
- package/Utils/StatusPage/ResourceUptime.ts +90 -17
- package/Utils/UserPreferences.ts +53 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +91 -0
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +14 -4
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RecommendationDismissal.js +484 -0
- package/build/dist/Models/DatabaseModels/RecommendationDismissal.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageGroup.js +94 -0
- package/build/dist/Models/DatabaseModels/StatusPageGroup.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TableView.js +40 -0
- package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +91 -0
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +5 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +22 -13
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +22 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js +24 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +42 -0
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +43 -26
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +21 -12
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/MonitorAPI.js +23 -0
- package/build/dist/Server/API/MonitorAPI.js.map +1 -1
- package/build/dist/Server/API/MonitorTemplateAPI.js +4 -0
- package/build/dist/Server/API/MonitorTemplateAPI.js.map +1 -1
- package/build/dist/Server/API/ProbeAPI.js +131 -15
- package/build/dist/Server/API/ProbeAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +62 -3
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +23 -14
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +61 -33
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js +26 -2
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js +397 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeService.js +39 -0
- package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +95 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +71 -0
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +140 -17
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +39 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +100 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +97 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/LogDropFilterService.js +93 -0
- package/build/dist/Server/Services/LogDropFilterService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +73 -5
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +34 -39
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +71 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +64 -0
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +103 -7
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RecommendationDismissalService.js +50 -0
- package/build/dist/Server/Services/RecommendationDismissalService.js.map +1 -0
- package/build/dist/Server/Services/RunbookAgentJobService.js +63 -5
- package/build/dist/Server/Services/RunbookAgentJobService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +83 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +65 -0
- package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageGroupService.js +136 -0
- package/build/dist/Server/Services/StatusPageGroupService.js.map +1 -1
- package/build/dist/Server/Services/TraceDropFilterService.js +93 -0
- package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +12 -0
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +132 -0
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/DropFilterValidation.js +80 -0
- package/build/dist/Server/Utils/DropFilterValidation.js.map +1 -0
- package/build/dist/Server/Utils/Errors.js +3 -0
- package/build/dist/Server/Utils/Errors.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +30 -12
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +38 -18
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js +26 -0
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
- package/build/dist/Types/Date.js +14 -4
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +8 -3
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +192 -0
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +6 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +32 -1
- package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +294 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +110 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +58 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +451 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -0
- package/build/dist/Types/Permission.js +40 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Recommendation/RecommendationType.js +21 -0
- package/build/dist/Types/Recommendation/RecommendationType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookExecutionDeadline.js +93 -0
- package/build/dist/Types/Runbook/RunbookExecutionDeadline.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepTimeout.js +142 -0
- package/build/dist/Types/Runbook/RunbookStepTimeout.js.map +1 -0
- package/build/dist/Types/Telemetry/DropFilterSampling.js +75 -0
- package/build/dist/Types/Telemetry/DropFilterSampling.js.map +1 -0
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -2
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
- package/build/dist/UI/Components/Accordion/Accordion.js +9 -2
- package/build/dist/UI/Components/Accordion/Accordion.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +27 -14
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js +1 -1
- package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +2 -20
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Error/PageError.js +1 -3
- package/build/dist/UI/Components/Error/PageError.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +145 -11
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js +28 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +13 -2
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +4 -32
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +308 -40
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +230 -0
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/TableView.js +13 -2
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -0
- package/build/dist/UI/Components/Runbook/StepTimeoutInput.js +101 -0
- package/build/dist/UI/Components/Runbook/StepTimeoutInput.js.map +1 -0
- package/build/dist/UI/Components/SideMenu/SideMenu.js +15 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +73 -0
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +15 -2
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +11 -6
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +13 -2
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Utils/DropdownAlignment.js +98 -0
- package/build/dist/UI/Utils/DropdownAlignment.js.map +1 -0
- package/build/dist/UI/Utils/TableFilterUrlState.js +48 -15
- package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
- package/build/dist/Utils/API.js +39 -2
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js +97 -0
- package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +330 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js +280 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -0
- package/build/dist/Utils/StatusPage/GroupTree.js +214 -0
- package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceUptime.js +60 -16
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/UserPreferences.js +33 -0
- package/build/dist/Utils/UserPreferences.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,754 @@
|
|
|
1
|
+
import MonitorRecommendationSeverityMapper, {
|
|
2
|
+
MonitorRecommendationSeverityOption,
|
|
3
|
+
} from "../../../../Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper";
|
|
4
|
+
import MonitorRecommendationCatalog from "../../../../Types/Monitor/Recommendation/MonitorRecommendationCatalog";
|
|
5
|
+
import MonitorRecommendationUtil from "../../../../Types/Monitor/Recommendation/MonitorRecommendationUtil";
|
|
6
|
+
import {
|
|
7
|
+
MonitorRecommendation,
|
|
8
|
+
MonitorRecommendationArgs,
|
|
9
|
+
MonitorRecommendationSeverity,
|
|
10
|
+
MonitorRecommendationSeverityMap,
|
|
11
|
+
} from "../../../../Types/Monitor/Recommendation/MonitorRecommendationTypes";
|
|
12
|
+
import MonitorStep from "../../../../Types/Monitor/MonitorStep";
|
|
13
|
+
import MonitorCriteriaInstance from "../../../../Types/Monitor/MonitorCriteriaInstance";
|
|
14
|
+
import { CriteriaIncident } from "../../../../Types/Monitor/CriteriaIncident";
|
|
15
|
+
import { CriteriaAlert } from "../../../../Types/Monitor/CriteriaAlert";
|
|
16
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* This mapper is the only thing standing between "the card said Warning" and
|
|
20
|
+
* "the incident it opened said Critical".
|
|
21
|
+
*
|
|
22
|
+
* Before it existed, `MonitorRecommendationArgs` carried a single
|
|
23
|
+
* `defaultIncidentSeverityId` that the page filled with the project's first
|
|
24
|
+
* severity, so every template — Critical and Warning alike — opened the same
|
|
25
|
+
* severity of incident. That failure is invisible in every obvious place: the
|
|
26
|
+
* page renders correctly, the monitor is created successfully, the criteria
|
|
27
|
+
* validate, and the mis-signal only shows up weeks later when someone is paged
|
|
28
|
+
* at 3am for a replica-count drift. Nothing but these tests notices.
|
|
29
|
+
*
|
|
30
|
+
* Two properties are worth naming up front because they are easy to "clean up"
|
|
31
|
+
* into bugs:
|
|
32
|
+
*
|
|
33
|
+
* 1. Rank comes from `order`, never from array position and never from the
|
|
34
|
+
* severity NAME. Severities are user-renameable and user-reorderable
|
|
35
|
+
* ("Sev1", "P0", localized names), so name matching works for the default
|
|
36
|
+
* seed and for no other project on the planet.
|
|
37
|
+
*
|
|
38
|
+
* 2. A row with no `order` is UNRANKED, not rank zero. Coercing it to zero
|
|
39
|
+
* (which `a.order || MAX` quietly does, and which is the natural way to
|
|
40
|
+
* write this) promotes a legacy row to most-severe and maps every
|
|
41
|
+
* Critical recommendation onto it.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
* The real default-project seed, from ProjectService.addDefaultIncidentSeverity
|
|
46
|
+
* and addDefaultAlertSeverity. Written out rather than imported because the
|
|
47
|
+
* mapper deliberately takes a structural slice — the point of these tests is
|
|
48
|
+
* that the mapper produces the right answer for the shape the overwhelming
|
|
49
|
+
* majority of real projects actually have.
|
|
50
|
+
*/
|
|
51
|
+
const CRITICAL_INCIDENT_ID: ObjectID = ObjectID.generate();
|
|
52
|
+
const MAJOR_INCIDENT_ID: ObjectID = ObjectID.generate();
|
|
53
|
+
const MINOR_INCIDENT_ID: ObjectID = ObjectID.generate();
|
|
54
|
+
|
|
55
|
+
const HIGH_ALERT_ID: ObjectID = ObjectID.generate();
|
|
56
|
+
const LOW_ALERT_ID: ObjectID = ObjectID.generate();
|
|
57
|
+
|
|
58
|
+
const DEFAULT_INCIDENT_SEVERITIES: Array<MonitorRecommendationSeverityOption> =
|
|
59
|
+
[
|
|
60
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
61
|
+
{ id: MAJOR_INCIDENT_ID, name: "Major Incident", order: 2 },
|
|
62
|
+
{ id: MINOR_INCIDENT_ID, name: "Minor Incident", order: 3 },
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const DEFAULT_ALERT_SEVERITIES: Array<MonitorRecommendationSeverityOption> = [
|
|
66
|
+
{ id: HIGH_ALERT_ID, name: "High", order: 1 },
|
|
67
|
+
{ id: LOW_ALERT_ID, name: "Low", order: 2 },
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
function getNames(
|
|
71
|
+
options: Array<MonitorRecommendationSeverityOption>,
|
|
72
|
+
): Array<string> {
|
|
73
|
+
return options.map((option: MonitorRecommendationSeverityOption) => {
|
|
74
|
+
return option.name;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function idString(id: ObjectID | undefined): string | undefined {
|
|
79
|
+
return id ? id.toString() : undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
describe("MonitorRecommendationSeverityMapper", () => {
|
|
83
|
+
describe("rankSeverities", () => {
|
|
84
|
+
it("sorts by order ascending regardless of array position", () => {
|
|
85
|
+
const ranked: Array<MonitorRecommendationSeverityOption> =
|
|
86
|
+
MonitorRecommendationSeverityMapper.rankSeverities([
|
|
87
|
+
{ id: MINOR_INCIDENT_ID, name: "Minor Incident", order: 3 },
|
|
88
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
89
|
+
{ id: MAJOR_INCIDENT_ID, name: "Major Incident", order: 2 },
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
expect(getNames(ranked)).toEqual([
|
|
93
|
+
"Critical Incident",
|
|
94
|
+
"Major Incident",
|
|
95
|
+
"Minor Incident",
|
|
96
|
+
]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("pushes rows with no order to the very end", () => {
|
|
100
|
+
/*
|
|
101
|
+
* The unranked row is placed FIRST in the input on purpose: an
|
|
102
|
+
* implementation that treats a missing order as 0 — or that simply
|
|
103
|
+
* leaves unsortable rows where they were — leaves it at index 0, where
|
|
104
|
+
* `getDefaultSeverityMapping` reads it as the project's most severe.
|
|
105
|
+
*/
|
|
106
|
+
const ranked: Array<MonitorRecommendationSeverityOption> =
|
|
107
|
+
MonitorRecommendationSeverityMapper.rankSeverities([
|
|
108
|
+
{ id: ObjectID.generate(), name: "Legacy Unranked" },
|
|
109
|
+
{ id: MAJOR_INCIDENT_ID, name: "Major Incident", order: 2 },
|
|
110
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
expect(getNames(ranked)).toEqual([
|
|
114
|
+
"Critical Incident",
|
|
115
|
+
"Major Incident",
|
|
116
|
+
"Legacy Unranked",
|
|
117
|
+
]);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("treats an explicitly undefined order the same as an absent one", () => {
|
|
121
|
+
// `{ order: undefined }` and `{}` are different objects to `in`/hasOwnProperty.
|
|
122
|
+
const ranked: Array<MonitorRecommendationSeverityOption> =
|
|
123
|
+
MonitorRecommendationSeverityMapper.rankSeverities([
|
|
124
|
+
{
|
|
125
|
+
id: ObjectID.generate(),
|
|
126
|
+
name: "Legacy Unranked",
|
|
127
|
+
order: undefined,
|
|
128
|
+
},
|
|
129
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
expect(getNames(ranked)).toEqual([
|
|
133
|
+
"Critical Incident",
|
|
134
|
+
"Legacy Unranked",
|
|
135
|
+
]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("keeps order 0 as the most severe rather than treating it as unset", () => {
|
|
139
|
+
/*
|
|
140
|
+
* Zero is a legitimate order and the exact value a truthiness check
|
|
141
|
+
* (`a.order || MAX_SAFE_INTEGER`) mangles: it would demote the project's
|
|
142
|
+
* most severe row to last and hand Critical to whatever came next.
|
|
143
|
+
*/
|
|
144
|
+
const zeroOrderId: ObjectID = ObjectID.generate();
|
|
145
|
+
|
|
146
|
+
const ranked: Array<MonitorRecommendationSeverityOption> =
|
|
147
|
+
MonitorRecommendationSeverityMapper.rankSeverities([
|
|
148
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
149
|
+
{ id: zeroOrderId, name: "Sev0", order: 0 },
|
|
150
|
+
]);
|
|
151
|
+
|
|
152
|
+
expect(getNames(ranked)).toEqual(["Sev0", "Critical Incident"]);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("does not mutate the array it was given", () => {
|
|
156
|
+
/*
|
|
157
|
+
* Callers pass the API's own severity list straight in and keep using it
|
|
158
|
+
* to render the dropdown. Sorting it in place would silently reorder the
|
|
159
|
+
* form's options as a side effect of computing the mapping.
|
|
160
|
+
*/
|
|
161
|
+
const input: Array<MonitorRecommendationSeverityOption> = [
|
|
162
|
+
{ id: MINOR_INCIDENT_ID, name: "Minor Incident", order: 3 },
|
|
163
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
const ranked: Array<MonitorRecommendationSeverityOption> =
|
|
167
|
+
MonitorRecommendationSeverityMapper.rankSeverities(input);
|
|
168
|
+
|
|
169
|
+
expect(getNames(input)).toEqual(["Minor Incident", "Critical Incident"]);
|
|
170
|
+
expect(ranked).not.toBe(input);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("keeps the input order for severities that share an order", () => {
|
|
174
|
+
/*
|
|
175
|
+
* The product permits two severities with the same order. An unstable
|
|
176
|
+
* tiebreak would mean the mapping shown in the create form and the
|
|
177
|
+
* mapping written onto the monitor could disagree between two calls with
|
|
178
|
+
* identical input.
|
|
179
|
+
*/
|
|
180
|
+
const firstTiedId: ObjectID = ObjectID.generate();
|
|
181
|
+
const secondTiedId: ObjectID = ObjectID.generate();
|
|
182
|
+
|
|
183
|
+
const input: Array<MonitorRecommendationSeverityOption> = [
|
|
184
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
185
|
+
{ id: firstTiedId, name: "Tied A", order: 2 },
|
|
186
|
+
{ id: secondTiedId, name: "Tied B", order: 2 },
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
expect(
|
|
190
|
+
getNames(MonitorRecommendationSeverityMapper.rankSeverities(input)),
|
|
191
|
+
).toEqual(["Critical Incident", "Tied A", "Tied B"]);
|
|
192
|
+
|
|
193
|
+
expect(
|
|
194
|
+
getNames(MonitorRecommendationSeverityMapper.rankSeverities(input)),
|
|
195
|
+
).toEqual(["Critical Incident", "Tied A", "Tied B"]);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("keeps the input order among several unranked rows", () => {
|
|
199
|
+
const input: Array<MonitorRecommendationSeverityOption> = [
|
|
200
|
+
{ id: ObjectID.generate(), name: "Unranked A" },
|
|
201
|
+
{ id: ObjectID.generate(), name: "Unranked B" },
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
expect(
|
|
205
|
+
getNames(MonitorRecommendationSeverityMapper.rankSeverities(input)),
|
|
206
|
+
).toEqual(["Unranked A", "Unranked B"]);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("returns an empty array for empty input", () => {
|
|
210
|
+
expect(MonitorRecommendationSeverityMapper.rankSeverities([])).toEqual(
|
|
211
|
+
[],
|
|
212
|
+
);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe("getDefaultSeverityMapping", () => {
|
|
217
|
+
it("maps Critical to Critical Incident and Warning to Major Incident on the default seed", () => {
|
|
218
|
+
const map: MonitorRecommendationSeverityMap =
|
|
219
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(
|
|
220
|
+
DEFAULT_INCIDENT_SEVERITIES,
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
expect(idString(map.Critical)).toBe(CRITICAL_INCIDENT_ID.toString());
|
|
224
|
+
expect(idString(map.Warning)).toBe(MAJOR_INCIDENT_ID.toString());
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("maps Critical to High and Warning to Low on the default alert seed", () => {
|
|
228
|
+
const map: MonitorRecommendationSeverityMap =
|
|
229
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(
|
|
230
|
+
DEFAULT_ALERT_SEVERITIES,
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
expect(idString(map.Critical)).toBe(HIGH_ALERT_ID.toString());
|
|
234
|
+
expect(idString(map.Warning)).toBe(LOW_ALERT_ID.toString());
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("never maps Critical and Warning to the same severity when the project has more than one", () => {
|
|
238
|
+
/*
|
|
239
|
+
* The single assertion that the whole feature reduces to. If these two
|
|
240
|
+
* ever collapse back to one id, every recommendation pages identically
|
|
241
|
+
* again and the Critical/Warning badge on each card describes nothing.
|
|
242
|
+
*/
|
|
243
|
+
const map: MonitorRecommendationSeverityMap =
|
|
244
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(
|
|
245
|
+
DEFAULT_INCIDENT_SEVERITIES,
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
expect(idString(map.Critical)).not.toBe(idString(map.Warning));
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("maps by order, not by position in the array it was handed", () => {
|
|
252
|
+
/*
|
|
253
|
+
* The API sorts severities today, so an implementation that just took
|
|
254
|
+
* `options[0]` and `options[1]` would pass every other test here and
|
|
255
|
+
* break the day the API's sort changes or a caller passes an unsorted
|
|
256
|
+
* list from a cache.
|
|
257
|
+
*/
|
|
258
|
+
const map: MonitorRecommendationSeverityMap =
|
|
259
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping([
|
|
260
|
+
{ id: MINOR_INCIDENT_ID, name: "Minor Incident", order: 3 },
|
|
261
|
+
{ id: MAJOR_INCIDENT_ID, name: "Major Incident", order: 2 },
|
|
262
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
263
|
+
]);
|
|
264
|
+
|
|
265
|
+
expect(idString(map.Critical)).toBe(CRITICAL_INCIDENT_ID.toString());
|
|
266
|
+
expect(idString(map.Warning)).toBe(MAJOR_INCIDENT_ID.toString());
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it("does not hand Critical to an unranked legacy severity", () => {
|
|
270
|
+
/*
|
|
271
|
+
* The end-to-end consequence of the rankSeverities ordering rule: a
|
|
272
|
+
* project carrying one severity row with no order (created before the
|
|
273
|
+
* field existed, or through an import) must not have every Critical
|
|
274
|
+
* recommendation silently routed to it.
|
|
275
|
+
*/
|
|
276
|
+
const unrankedId: ObjectID = ObjectID.generate();
|
|
277
|
+
|
|
278
|
+
const map: MonitorRecommendationSeverityMap =
|
|
279
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping([
|
|
280
|
+
{ id: unrankedId, name: "Imported Severity" },
|
|
281
|
+
...DEFAULT_INCIDENT_SEVERITIES,
|
|
282
|
+
]);
|
|
283
|
+
|
|
284
|
+
expect(idString(map.Critical)).toBe(CRITICAL_INCIDENT_ID.toString());
|
|
285
|
+
expect(idString(map.Warning)).toBe(MAJOR_INCIDENT_ID.toString());
|
|
286
|
+
expect(idString(map.Critical)).not.toBe(unrankedId.toString());
|
|
287
|
+
expect(idString(map.Warning)).not.toBe(unrankedId.toString());
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("maps both Critical and Warning to the only severity a one-severity project has", () => {
|
|
291
|
+
/*
|
|
292
|
+
* A project with one severity cannot express the distinction, and
|
|
293
|
+
* leaving Warning unmapped would drop those monitors back onto the
|
|
294
|
+
* template's own `defaultIncidentSeverityId` — the pre-fix behaviour
|
|
295
|
+
* this class exists to replace. Mapping both is the deliberate choice.
|
|
296
|
+
*/
|
|
297
|
+
const onlyId: ObjectID = ObjectID.generate();
|
|
298
|
+
|
|
299
|
+
const map: MonitorRecommendationSeverityMap =
|
|
300
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping([
|
|
301
|
+
{ id: onlyId, name: "Sev1", order: 1 },
|
|
302
|
+
]);
|
|
303
|
+
|
|
304
|
+
expect(idString(map.Critical)).toBe(onlyId.toString());
|
|
305
|
+
expect(idString(map.Warning)).toBe(onlyId.toString());
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it("returns an empty map when the project has no severities at all", () => {
|
|
309
|
+
/*
|
|
310
|
+
* Empty rather than a map onto undefined ids: `resolveSeverityId` returns
|
|
311
|
+
* undefined for a missing entry, and the util reads that as "leave the
|
|
312
|
+
* template's severity alone". A map containing `Critical: undefined`
|
|
313
|
+
* would travel the same path, but an empty object says so unambiguously
|
|
314
|
+
* and keeps `describeMapping` from rendering half a row.
|
|
315
|
+
*/
|
|
316
|
+
expect(
|
|
317
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping([]),
|
|
318
|
+
).toEqual({});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("gives Warning the SECOND severity, not the least severe one", () => {
|
|
322
|
+
/*
|
|
323
|
+
* Pinned because it is a judgement call that the default three-severity
|
|
324
|
+
* seed hides completely: there, second and last-but-one are the same row.
|
|
325
|
+
* On a five-severity project the two answers diverge, and the intended
|
|
326
|
+
* one is second — a recommendation the catalog calls Warning ("Disk Will
|
|
327
|
+
* Fill In 24h", "Deployment Replica Mismatch") is a real production
|
|
328
|
+
* problem, not the bottom of the scale.
|
|
329
|
+
*
|
|
330
|
+
* If someone deliberately changes this to "least severe", this test is
|
|
331
|
+
* where that decision gets recorded.
|
|
332
|
+
*/
|
|
333
|
+
const sev1: ObjectID = ObjectID.generate();
|
|
334
|
+
const sev2: ObjectID = ObjectID.generate();
|
|
335
|
+
const sev5: ObjectID = ObjectID.generate();
|
|
336
|
+
|
|
337
|
+
const map: MonitorRecommendationSeverityMap =
|
|
338
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping([
|
|
339
|
+
{ id: sev1, name: "Sev1", order: 1 },
|
|
340
|
+
{ id: sev2, name: "Sev2", order: 2 },
|
|
341
|
+
{ id: ObjectID.generate(), name: "Sev3", order: 3 },
|
|
342
|
+
{ id: ObjectID.generate(), name: "Sev4", order: 4 },
|
|
343
|
+
{ id: sev5, name: "Sev5", order: 5 },
|
|
344
|
+
]);
|
|
345
|
+
|
|
346
|
+
expect(idString(map.Critical)).toBe(sev1.toString());
|
|
347
|
+
expect(idString(map.Warning)).toBe(sev2.toString());
|
|
348
|
+
expect(idString(map.Warning)).not.toBe(sev5.toString());
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it("does not mutate the options array it was given", () => {
|
|
352
|
+
const input: Array<MonitorRecommendationSeverityOption> = [
|
|
353
|
+
{ id: MINOR_INCIDENT_ID, name: "Minor Incident", order: 3 },
|
|
354
|
+
{ id: CRITICAL_INCIDENT_ID, name: "Critical Incident", order: 1 },
|
|
355
|
+
];
|
|
356
|
+
|
|
357
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(input);
|
|
358
|
+
|
|
359
|
+
expect(getNames(input)).toEqual(["Minor Incident", "Critical Incident"]);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe("resolveSeverityId", () => {
|
|
364
|
+
it("returns the id the map holds for that severity", () => {
|
|
365
|
+
const map: MonitorRecommendationSeverityMap = {
|
|
366
|
+
Critical: CRITICAL_INCIDENT_ID,
|
|
367
|
+
Warning: MAJOR_INCIDENT_ID,
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
expect(
|
|
371
|
+
idString(
|
|
372
|
+
MonitorRecommendationSeverityMapper.resolveSeverityId({
|
|
373
|
+
severity: "Critical",
|
|
374
|
+
severityMap: map,
|
|
375
|
+
}),
|
|
376
|
+
),
|
|
377
|
+
).toBe(CRITICAL_INCIDENT_ID.toString());
|
|
378
|
+
|
|
379
|
+
expect(
|
|
380
|
+
idString(
|
|
381
|
+
MonitorRecommendationSeverityMapper.resolveSeverityId({
|
|
382
|
+
severity: "Warning",
|
|
383
|
+
severityMap: map,
|
|
384
|
+
}),
|
|
385
|
+
),
|
|
386
|
+
).toBe(MAJOR_INCIDENT_ID.toString());
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it("returns undefined when there is no map", () => {
|
|
390
|
+
/*
|
|
391
|
+
* "No map" is the state of every caller that predates this feature, and
|
|
392
|
+
* it must mean "leave the template's severity alone" rather than throw or
|
|
393
|
+
* return a blank id — a criteria instance with a populated incident and
|
|
394
|
+
* no severity fails MonitorCriteriaInstance.getValidationError, so the
|
|
395
|
+
* whole create would fail at submit with a message about a field the user
|
|
396
|
+
* never saw.
|
|
397
|
+
*/
|
|
398
|
+
expect(
|
|
399
|
+
MonitorRecommendationSeverityMapper.resolveSeverityId({
|
|
400
|
+
severity: "Critical",
|
|
401
|
+
severityMap: undefined,
|
|
402
|
+
}),
|
|
403
|
+
).toBeUndefined();
|
|
404
|
+
|
|
405
|
+
expect(
|
|
406
|
+
MonitorRecommendationSeverityMapper.resolveSeverityId({
|
|
407
|
+
severity: "Warning",
|
|
408
|
+
}),
|
|
409
|
+
).toBeUndefined();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it("returns undefined for a severity the map has no entry for", () => {
|
|
413
|
+
// Same "leave it alone" contract, reached through a partial map.
|
|
414
|
+
expect(
|
|
415
|
+
MonitorRecommendationSeverityMapper.resolveSeverityId({
|
|
416
|
+
severity: "Warning",
|
|
417
|
+
severityMap: { Critical: CRITICAL_INCIDENT_ID },
|
|
418
|
+
}),
|
|
419
|
+
).toBeUndefined();
|
|
420
|
+
|
|
421
|
+
expect(
|
|
422
|
+
MonitorRecommendationSeverityMapper.resolveSeverityId({
|
|
423
|
+
severity: "Critical",
|
|
424
|
+
severityMap: {},
|
|
425
|
+
}),
|
|
426
|
+
).toBeUndefined();
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
describe("describeMapping", () => {
|
|
431
|
+
it("describes both severities by their project-facing names, Critical first", () => {
|
|
432
|
+
/*
|
|
433
|
+
* This string is the only thing that makes an automatic severity choice
|
|
434
|
+
* reviewable instead of surprising: it is what the create form renders so
|
|
435
|
+
* the user can see "Critical -> Critical Incident" before submitting.
|
|
436
|
+
*/
|
|
437
|
+
expect(
|
|
438
|
+
MonitorRecommendationSeverityMapper.describeMapping({
|
|
439
|
+
options: DEFAULT_INCIDENT_SEVERITIES,
|
|
440
|
+
severityMap:
|
|
441
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(
|
|
442
|
+
DEFAULT_INCIDENT_SEVERITIES,
|
|
443
|
+
),
|
|
444
|
+
}),
|
|
445
|
+
).toEqual([
|
|
446
|
+
{ severity: "Critical", name: "Critical Incident" },
|
|
447
|
+
{ severity: "Warning", name: "Major Incident" },
|
|
448
|
+
]);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it("skips a severity the map does not cover", () => {
|
|
452
|
+
expect(
|
|
453
|
+
MonitorRecommendationSeverityMapper.describeMapping({
|
|
454
|
+
options: DEFAULT_INCIDENT_SEVERITIES,
|
|
455
|
+
severityMap: { Critical: CRITICAL_INCIDENT_ID },
|
|
456
|
+
}),
|
|
457
|
+
).toEqual([{ severity: "Critical", name: "Critical Incident" }]);
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it("skips an id that matches none of the options", () => {
|
|
461
|
+
/*
|
|
462
|
+
* A stale id is reachable in normal use: the form holds a mapping while
|
|
463
|
+
* the user deletes that severity in another tab, or the map is restored
|
|
464
|
+
* from a previous session. Rendering "Critical -> undefined" (or throwing
|
|
465
|
+
* on the missing option) is worse than saying nothing about Critical.
|
|
466
|
+
*/
|
|
467
|
+
expect(
|
|
468
|
+
MonitorRecommendationSeverityMapper.describeMapping({
|
|
469
|
+
options: DEFAULT_INCIDENT_SEVERITIES,
|
|
470
|
+
severityMap: {
|
|
471
|
+
Critical: ObjectID.generate(),
|
|
472
|
+
Warning: MAJOR_INCIDENT_ID,
|
|
473
|
+
},
|
|
474
|
+
}),
|
|
475
|
+
).toEqual([{ severity: "Warning", name: "Major Incident" }]);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it("matches options by id value rather than by object identity", () => {
|
|
479
|
+
/*
|
|
480
|
+
* The map's ObjectIDs and the options' ObjectIDs come from different
|
|
481
|
+
* fetches in the real page, so they are never the same instance even when
|
|
482
|
+
* they hold the same uuid. A `===` comparison would describe nothing.
|
|
483
|
+
*/
|
|
484
|
+
expect(
|
|
485
|
+
MonitorRecommendationSeverityMapper.describeMapping({
|
|
486
|
+
options: DEFAULT_INCIDENT_SEVERITIES,
|
|
487
|
+
severityMap: {
|
|
488
|
+
Critical: new ObjectID(CRITICAL_INCIDENT_ID.toString()),
|
|
489
|
+
},
|
|
490
|
+
}),
|
|
491
|
+
).toEqual([{ severity: "Critical", name: "Critical Incident" }]);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it("returns an empty list when there is no map", () => {
|
|
495
|
+
expect(
|
|
496
|
+
MonitorRecommendationSeverityMapper.describeMapping({
|
|
497
|
+
options: DEFAULT_INCIDENT_SEVERITIES,
|
|
498
|
+
severityMap: undefined,
|
|
499
|
+
}),
|
|
500
|
+
).toEqual([]);
|
|
501
|
+
|
|
502
|
+
expect(
|
|
503
|
+
MonitorRecommendationSeverityMapper.describeMapping({
|
|
504
|
+
options: DEFAULT_INCIDENT_SEVERITIES,
|
|
505
|
+
}),
|
|
506
|
+
).toEqual([]);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
it("returns an empty list when the project has no severities to name", () => {
|
|
510
|
+
expect(
|
|
511
|
+
MonitorRecommendationSeverityMapper.describeMapping({
|
|
512
|
+
options: [],
|
|
513
|
+
severityMap: { Critical: CRITICAL_INCIDENT_ID },
|
|
514
|
+
}),
|
|
515
|
+
).toEqual([]);
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
describe("end to end with real catalog recommendations", () => {
|
|
520
|
+
/*
|
|
521
|
+
* The mapper is only useful if its output survives the trip into
|
|
522
|
+
* `applyNotificationSettingsToMonitorStep` and lands on the criteria
|
|
523
|
+
* incidents the monitor evaluator actually reads. The unit tests above pin
|
|
524
|
+
* the mapping; this pins that nothing between here and the created monitor
|
|
525
|
+
* flattens it back to one severity — which is exactly what the code did
|
|
526
|
+
* before this feature, because every template took the single
|
|
527
|
+
* `args.defaultIncidentSeverityId`.
|
|
528
|
+
*/
|
|
529
|
+
|
|
530
|
+
const ALL_RECOMMENDATIONS: Array<MonitorRecommendation> =
|
|
531
|
+
MonitorRecommendationCatalog.getAllRecommendations();
|
|
532
|
+
|
|
533
|
+
const CRITICAL_RECOMMENDATION: MonitorRecommendation | undefined =
|
|
534
|
+
ALL_RECOMMENDATIONS.find((recommendation: MonitorRecommendation) => {
|
|
535
|
+
return recommendation.severity === "Critical";
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
const WARNING_RECOMMENDATION: MonitorRecommendation | undefined =
|
|
539
|
+
ALL_RECOMMENDATIONS.find((recommendation: MonitorRecommendation) => {
|
|
540
|
+
return recommendation.severity === "Warning";
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
const TEMPLATE_INCIDENT_SEVERITY_ID: ObjectID = ObjectID.generate();
|
|
544
|
+
const TEMPLATE_ALERT_SEVERITY_ID: ObjectID = ObjectID.generate();
|
|
545
|
+
|
|
546
|
+
function buildArgs(): MonitorRecommendationArgs {
|
|
547
|
+
return {
|
|
548
|
+
resourceIdentifier: "prod-cluster-01",
|
|
549
|
+
onlineMonitorStatusId: ObjectID.generate(),
|
|
550
|
+
offlineMonitorStatusId: ObjectID.generate(),
|
|
551
|
+
defaultIncidentSeverityId: TEMPLATE_INCIDENT_SEVERITY_ID,
|
|
552
|
+
defaultAlertSeverityId: TEMPLATE_ALERT_SEVERITY_ID,
|
|
553
|
+
monitorName: "Test Monitor",
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function buildStepWithDefaultMapping(
|
|
558
|
+
recommendation: MonitorRecommendation,
|
|
559
|
+
): MonitorStep {
|
|
560
|
+
return MonitorRecommendationUtil.applyNotificationSettingsToMonitorStep({
|
|
561
|
+
monitorStep: recommendation.getMonitorStep(buildArgs()),
|
|
562
|
+
notificationSettings: {
|
|
563
|
+
incidentSeverityIdBySeverity:
|
|
564
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(
|
|
565
|
+
DEFAULT_INCIDENT_SEVERITIES,
|
|
566
|
+
),
|
|
567
|
+
alertSeverityIdBySeverity:
|
|
568
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(
|
|
569
|
+
DEFAULT_ALERT_SEVERITIES,
|
|
570
|
+
),
|
|
571
|
+
},
|
|
572
|
+
severity: recommendation.severity,
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function getIncidents(monitorStep: MonitorStep): Array<CriteriaIncident> {
|
|
577
|
+
return (
|
|
578
|
+
monitorStep.data?.monitorCriteria?.data?.monitorCriteriaInstanceArray ||
|
|
579
|
+
[]
|
|
580
|
+
).flatMap((instance: MonitorCriteriaInstance) => {
|
|
581
|
+
return instance.data?.incidents || [];
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function getAlerts(monitorStep: MonitorStep): Array<CriteriaAlert> {
|
|
586
|
+
return (
|
|
587
|
+
monitorStep.data?.monitorCriteria?.data?.monitorCriteriaInstanceArray ||
|
|
588
|
+
[]
|
|
589
|
+
).flatMap((instance: MonitorCriteriaInstance) => {
|
|
590
|
+
return instance.data?.alerts || [];
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
it("ships both a Critical and a Warning recommendation to compare", () => {
|
|
595
|
+
/*
|
|
596
|
+
* Guards the two tests below against passing vacuously if the catalog
|
|
597
|
+
* ever stops shipping one of the two severities.
|
|
598
|
+
*/
|
|
599
|
+
expect(CRITICAL_RECOMMENDATION).toBeDefined();
|
|
600
|
+
expect(WARNING_RECOMMENDATION).toBeDefined();
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
it("gives a Critical and a Warning recommendation DIFFERENT incident severities", () => {
|
|
604
|
+
const criticalIncidents: Array<CriteriaIncident> = getIncidents(
|
|
605
|
+
buildStepWithDefaultMapping(CRITICAL_RECOMMENDATION!),
|
|
606
|
+
);
|
|
607
|
+
const warningIncidents: Array<CriteriaIncident> = getIncidents(
|
|
608
|
+
buildStepWithDefaultMapping(WARNING_RECOMMENDATION!),
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
expect(criticalIncidents.length).toBeGreaterThan(0);
|
|
612
|
+
expect(warningIncidents.length).toBeGreaterThan(0);
|
|
613
|
+
|
|
614
|
+
for (const incident of criticalIncidents) {
|
|
615
|
+
expect(idString(incident.incidentSeverityId)).toBe(
|
|
616
|
+
CRITICAL_INCIDENT_ID.toString(),
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
for (const incident of warningIncidents) {
|
|
621
|
+
expect(idString(incident.incidentSeverityId)).toBe(
|
|
622
|
+
MAJOR_INCIDENT_ID.toString(),
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/*
|
|
627
|
+
* The regression this whole feature fixes, stated directly: both used to
|
|
628
|
+
* come out as `args.defaultIncidentSeverityId`, so the two arrays were
|
|
629
|
+
* identical and neither told the truth about the card's badge.
|
|
630
|
+
*/
|
|
631
|
+
expect(idString(criticalIncidents[0]!.incidentSeverityId)).not.toBe(
|
|
632
|
+
idString(warningIncidents[0]!.incidentSeverityId),
|
|
633
|
+
);
|
|
634
|
+
expect(idString(warningIncidents[0]!.incidentSeverityId)).not.toBe(
|
|
635
|
+
TEMPLATE_INCIDENT_SEVERITY_ID.toString(),
|
|
636
|
+
);
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
it("gives a Critical and a Warning recommendation DIFFERENT alert severities", () => {
|
|
640
|
+
const criticalAlerts: Array<CriteriaAlert> = getAlerts(
|
|
641
|
+
buildStepWithDefaultMapping(CRITICAL_RECOMMENDATION!),
|
|
642
|
+
);
|
|
643
|
+
const warningAlerts: Array<CriteriaAlert> = getAlerts(
|
|
644
|
+
buildStepWithDefaultMapping(WARNING_RECOMMENDATION!),
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
expect(criticalAlerts.length).toBeGreaterThan(0);
|
|
648
|
+
expect(warningAlerts.length).toBeGreaterThan(0);
|
|
649
|
+
|
|
650
|
+
for (const alert of criticalAlerts) {
|
|
651
|
+
expect(idString(alert.alertSeverityId)).toBe(HIGH_ALERT_ID.toString());
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
for (const alert of warningAlerts) {
|
|
655
|
+
expect(idString(alert.alertSeverityId)).toBe(LOW_ALERT_ID.toString());
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
it("routes every catalog recommendation to the severity its own badge claims", () => {
|
|
660
|
+
/*
|
|
661
|
+
* The per-recommendation version of the above, across all eight resource
|
|
662
|
+
* types. A single template whose declared severity disagrees with what it
|
|
663
|
+
* writes onto its criteria would be invisible on the page and would only
|
|
664
|
+
* surface as a mis-severity incident in production.
|
|
665
|
+
*/
|
|
666
|
+
expect(ALL_RECOMMENDATIONS.length).toBeGreaterThan(0);
|
|
667
|
+
|
|
668
|
+
for (const recommendation of ALL_RECOMMENDATIONS) {
|
|
669
|
+
const expectedIncidentSeverityId: ObjectID =
|
|
670
|
+
recommendation.severity === "Critical"
|
|
671
|
+
? CRITICAL_INCIDENT_ID
|
|
672
|
+
: MAJOR_INCIDENT_ID;
|
|
673
|
+
|
|
674
|
+
for (const incident of getIncidents(
|
|
675
|
+
buildStepWithDefaultMapping(recommendation),
|
|
676
|
+
)) {
|
|
677
|
+
expect(idString(incident.incidentSeverityId)).toBe(
|
|
678
|
+
expectedIncidentSeverityId.toString(),
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
it("falls back to the template's own severity when the project has none", () => {
|
|
685
|
+
/*
|
|
686
|
+
* A project with no severities produces an empty map, and an empty map
|
|
687
|
+
* must leave the templates untouched rather than blank the severity out —
|
|
688
|
+
* a criteria incident with no severity id fails validation and the create
|
|
689
|
+
* fails at submit.
|
|
690
|
+
*/
|
|
691
|
+
const severities: Array<MonitorRecommendationSeverity> = [
|
|
692
|
+
"Critical",
|
|
693
|
+
"Warning",
|
|
694
|
+
];
|
|
695
|
+
|
|
696
|
+
for (const severity of severities) {
|
|
697
|
+
const monitorStep: MonitorStep =
|
|
698
|
+
MonitorRecommendationUtil.applyNotificationSettingsToMonitorStep({
|
|
699
|
+
monitorStep: CRITICAL_RECOMMENDATION!.getMonitorStep(buildArgs()),
|
|
700
|
+
notificationSettings: {
|
|
701
|
+
incidentSeverityIdBySeverity:
|
|
702
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping(
|
|
703
|
+
[],
|
|
704
|
+
),
|
|
705
|
+
},
|
|
706
|
+
severity: severity,
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
for (const incident of getIncidents(monitorStep)) {
|
|
710
|
+
expect(idString(incident.incidentSeverityId)).toBe(
|
|
711
|
+
TEMPLATE_INCIDENT_SEVERITY_ID.toString(),
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
it("maps Critical and Warning to the same severity on a one-severity project", () => {
|
|
718
|
+
/*
|
|
719
|
+
* The documented single-severity fallback, checked where it actually
|
|
720
|
+
* matters: the monitor still gets a valid severity (so the create
|
|
721
|
+
* succeeds), it just cannot express the distinction.
|
|
722
|
+
*/
|
|
723
|
+
const onlyId: ObjectID = ObjectID.generate();
|
|
724
|
+
const oneSeverityMap: MonitorRecommendationSeverityMap =
|
|
725
|
+
MonitorRecommendationSeverityMapper.getDefaultSeverityMapping([
|
|
726
|
+
{ id: onlyId, name: "Sev1", order: 1 },
|
|
727
|
+
]);
|
|
728
|
+
|
|
729
|
+
const recommendations: Array<MonitorRecommendation> = [
|
|
730
|
+
CRITICAL_RECOMMENDATION!,
|
|
731
|
+
WARNING_RECOMMENDATION!,
|
|
732
|
+
];
|
|
733
|
+
|
|
734
|
+
for (const recommendation of recommendations) {
|
|
735
|
+
const monitorStep: MonitorStep =
|
|
736
|
+
MonitorRecommendationUtil.applyNotificationSettingsToMonitorStep({
|
|
737
|
+
monitorStep: recommendation.getMonitorStep(buildArgs()),
|
|
738
|
+
notificationSettings: {
|
|
739
|
+
incidentSeverityIdBySeverity: oneSeverityMap,
|
|
740
|
+
},
|
|
741
|
+
severity: recommendation.severity,
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
const incidents: Array<CriteriaIncident> = getIncidents(monitorStep);
|
|
745
|
+
|
|
746
|
+
expect(incidents.length).toBeGreaterThan(0);
|
|
747
|
+
|
|
748
|
+
for (const incident of incidents) {
|
|
749
|
+
expect(idString(incident.incidentSeverityId)).toBe(onlyId.toString());
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
});
|