@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,241 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isSamplePercentageConfigured,
|
|
3
|
+
KEEP_ALL_PERCENTAGE,
|
|
4
|
+
MAX_SAMPLE_PERCENTAGE,
|
|
5
|
+
MIN_SAMPLE_PERCENTAGE,
|
|
6
|
+
resolveSamplePercentage,
|
|
7
|
+
shouldDropBySampling,
|
|
8
|
+
} from "../../../Types/Telemetry/DropFilterSampling";
|
|
9
|
+
import { describe, expect, it } from "@jest/globals";
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* Contract under test — how a drop filter's `samplePercentage` turns into a
|
|
13
|
+
* keep/discard decision.
|
|
14
|
+
*
|
|
15
|
+
* This replaced `filter.samplePercentage || 50`, duplicated in the log and
|
|
16
|
+
* trace drop-filter engines. That expression silently destroyed data three
|
|
17
|
+
* ways, and each one has a test below:
|
|
18
|
+
*
|
|
19
|
+
* 1. `samplePercentage` is nullable with no default and its form field was
|
|
20
|
+
* optional, so an UNSET percentage meant "discard half of every
|
|
21
|
+
* matching record" — a number nobody chose.
|
|
22
|
+
* 2. A stored `0` is falsy, so it was indistinguishable from unset and
|
|
23
|
+
* also kept 50%, contradicting both the literal reading ("keep 0%") and
|
|
24
|
+
* the view page's display of "0% kept".
|
|
25
|
+
* 3. Two copies of the expression could drift apart.
|
|
26
|
+
*
|
|
27
|
+
* The rule now is to fail SAFE: any percentage we cannot honour makes the
|
|
28
|
+
* filter a no-op rather than a shredder. `drop` exists for "discard
|
|
29
|
+
* everything matching", so nothing of value is lost by refusing to guess.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
describe("resolveSamplePercentage", () => {
|
|
33
|
+
it("honours a percentage inside the usable range", () => {
|
|
34
|
+
expect(resolveSamplePercentage(1)).toBe(1);
|
|
35
|
+
expect(resolveSamplePercentage(10)).toBe(10);
|
|
36
|
+
expect(resolveSamplePercentage(50)).toBe(50);
|
|
37
|
+
expect(resolveSamplePercentage(99)).toBe(99);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("honours a fractional percentage inside the range", () => {
|
|
41
|
+
expect(resolveSamplePercentage(0.5)).toBe(0.5);
|
|
42
|
+
expect(resolveSamplePercentage(99.9)).toBe(99.9);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* The headline regression. `undefined || 50` was 50, so a sample filter
|
|
47
|
+
* saved with no percentage threw away roughly half of everything it
|
|
48
|
+
* matched, and nothing recorded that it had happened.
|
|
49
|
+
*/
|
|
50
|
+
it("resolves an UNSET percentage to keep-everything, not the old 50", () => {
|
|
51
|
+
expect(resolveSamplePercentage(undefined)).toBe(KEEP_ALL_PERCENTAGE);
|
|
52
|
+
expect(resolveSamplePercentage(null)).toBe(KEEP_ALL_PERCENTAGE);
|
|
53
|
+
expect(resolveSamplePercentage(undefined)).not.toBe(50);
|
|
54
|
+
expect(resolveSamplePercentage(null)).not.toBe(50);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* 0 never meant "keep nothing" in any shipped version — it was falsy, so
|
|
59
|
+
* it kept half. Honouring it literally now would start deleting data that
|
|
60
|
+
* used to survive, so it is treated as misconfigured instead.
|
|
61
|
+
*/
|
|
62
|
+
it("treats 0 as misconfigured rather than 'discard everything'", () => {
|
|
63
|
+
expect(resolveSamplePercentage(0)).toBe(KEEP_ALL_PERCENTAGE);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("treats a negative percentage as misconfigured", () => {
|
|
67
|
+
expect(resolveSamplePercentage(-1)).toBe(KEEP_ALL_PERCENTAGE);
|
|
68
|
+
expect(resolveSamplePercentage(-100)).toBe(KEEP_ALL_PERCENTAGE);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("clamps 100 and above to keep-everything", () => {
|
|
72
|
+
expect(resolveSamplePercentage(100)).toBe(KEEP_ALL_PERCENTAGE);
|
|
73
|
+
expect(resolveSamplePercentage(1000)).toBe(KEEP_ALL_PERCENTAGE);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("rejects non-finite numbers", () => {
|
|
77
|
+
expect(resolveSamplePercentage(NaN)).toBe(KEEP_ALL_PERCENTAGE);
|
|
78
|
+
expect(resolveSamplePercentage(Infinity)).toBe(KEEP_ALL_PERCENTAGE);
|
|
79
|
+
expect(resolveSamplePercentage(-Infinity)).toBe(KEEP_ALL_PERCENTAGE);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
* The column is nullable and typed `number`, but the value arrives through
|
|
84
|
+
* a bigint-free JSON boundary and a form. A string that happens to look
|
|
85
|
+
* like a number must not be treated as one — `"50" || 50` would have been
|
|
86
|
+
* "50", and `Math.random() * 100 >= "50"` coerces, so the old code would
|
|
87
|
+
* have sampled on a string. Now it fails safe.
|
|
88
|
+
*/
|
|
89
|
+
it("rejects a value that is not a number at all", () => {
|
|
90
|
+
expect(resolveSamplePercentage("10" as unknown as number)).toBe(
|
|
91
|
+
KEEP_ALL_PERCENTAGE,
|
|
92
|
+
);
|
|
93
|
+
expect(resolveSamplePercentage({} as unknown as number)).toBe(
|
|
94
|
+
KEEP_ALL_PERCENTAGE,
|
|
95
|
+
);
|
|
96
|
+
expect(resolveSamplePercentage([] as unknown as number)).toBe(
|
|
97
|
+
KEEP_ALL_PERCENTAGE,
|
|
98
|
+
);
|
|
99
|
+
expect(resolveSamplePercentage(true as unknown as number)).toBe(
|
|
100
|
+
KEEP_ALL_PERCENTAGE,
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("accepts both ends of the range the validator enforces", () => {
|
|
105
|
+
expect(resolveSamplePercentage(MIN_SAMPLE_PERCENTAGE)).toBe(
|
|
106
|
+
MIN_SAMPLE_PERCENTAGE,
|
|
107
|
+
);
|
|
108
|
+
expect(resolveSamplePercentage(MAX_SAMPLE_PERCENTAGE)).toBe(
|
|
109
|
+
MAX_SAMPLE_PERCENTAGE,
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("isSamplePercentageConfigured", () => {
|
|
115
|
+
it("is true only for a percentage the engine will actually sample on", () => {
|
|
116
|
+
expect(isSamplePercentageConfigured(1)).toBe(true);
|
|
117
|
+
expect(isSamplePercentageConfigured(50)).toBe(true);
|
|
118
|
+
expect(isSamplePercentageConfigured(99)).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
* This is what the view page keys off. It used to render `|| 0` as
|
|
123
|
+
* "0% kept / 100% discarded" for an unset percentage while the engine kept
|
|
124
|
+
* half — the display and the behaviour disagreed, and both were wrong.
|
|
125
|
+
*/
|
|
126
|
+
it("is false for the values that used to render as '0% kept'", () => {
|
|
127
|
+
expect(isSamplePercentageConfigured(undefined)).toBe(false);
|
|
128
|
+
expect(isSamplePercentageConfigured(null)).toBe(false);
|
|
129
|
+
expect(isSamplePercentageConfigured(0)).toBe(false);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("is false at and above 100, where sampling is a no-op", () => {
|
|
133
|
+
expect(isSamplePercentageConfigured(100)).toBe(false);
|
|
134
|
+
expect(isSamplePercentageConfigured(150)).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe("shouldDropBySampling", () => {
|
|
139
|
+
/*
|
|
140
|
+
* `random` is injected so these are exact assertions rather than
|
|
141
|
+
* statistical ones. The engine keeps a record when
|
|
142
|
+
* `random() * 100 < keepPercentage`.
|
|
143
|
+
*/
|
|
144
|
+
const fixedRandom: (value: number) => () => number = (
|
|
145
|
+
value: number,
|
|
146
|
+
): (() => number) => {
|
|
147
|
+
return (): number => {
|
|
148
|
+
return value;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
it("keeps a record when the draw lands inside the keep window", () => {
|
|
153
|
+
// 0.05 * 100 = 5, which is < 10, so this record is kept.
|
|
154
|
+
expect(shouldDropBySampling(10, fixedRandom(0.05))).toBe(false);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("drops a record when the draw lands outside the keep window", () => {
|
|
158
|
+
// 0.5 * 100 = 50, which is >= 10, so this record is dropped.
|
|
159
|
+
expect(shouldDropBySampling(10, fixedRandom(0.5))).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("drops exactly at the boundary, so keep-10% never keeps 11%", () => {
|
|
163
|
+
// >= is the comparison, so a draw of exactly the keep percentage drops.
|
|
164
|
+
expect(shouldDropBySampling(10, fixedRandom(0.1))).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("keeps everything when the percentage is unset", () => {
|
|
168
|
+
for (const draw of [0, 0.25, 0.5, 0.75, 0.999]) {
|
|
169
|
+
expect(shouldDropBySampling(undefined, fixedRandom(draw))).toBe(false);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("keeps everything when the percentage is 0", () => {
|
|
174
|
+
for (const draw of [0, 0.5, 0.999]) {
|
|
175
|
+
expect(shouldDropBySampling(0, fixedRandom(draw))).toBe(false);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
/*
|
|
180
|
+
* A keep-everything filter should not even consume entropy: the cheap
|
|
181
|
+
* check has to come before the draw, because this runs once per ingested
|
|
182
|
+
* record on the hot path.
|
|
183
|
+
*/
|
|
184
|
+
it("does not consult random at all when it is keeping everything", () => {
|
|
185
|
+
let calls: number = 0;
|
|
186
|
+
const countingRandom: () => number = (): number => {
|
|
187
|
+
calls++;
|
|
188
|
+
return 0.5;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
expect(shouldDropBySampling(undefined, countingRandom)).toBe(false);
|
|
192
|
+
expect(shouldDropBySampling(0, countingRandom)).toBe(false);
|
|
193
|
+
expect(shouldDropBySampling(100, countingRandom)).toBe(false);
|
|
194
|
+
expect(calls).toBe(0);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("consults random exactly once when it is sampling", () => {
|
|
198
|
+
let calls: number = 0;
|
|
199
|
+
const countingRandom: () => number = (): number => {
|
|
200
|
+
calls++;
|
|
201
|
+
return 0.5;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
shouldDropBySampling(10, countingRandom);
|
|
205
|
+
expect(calls).toBe(1);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
/*
|
|
209
|
+
* End-to-end sanity on the distribution, using a deterministic sweep
|
|
210
|
+
* rather than real randomness so this can never flake.
|
|
211
|
+
*/
|
|
212
|
+
it("keeps approximately the requested share over a uniform sweep", () => {
|
|
213
|
+
const draws: Array<number> = [];
|
|
214
|
+
for (let i: number = 0; i < 1000; i++) {
|
|
215
|
+
draws.push(i / 1000);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for (const keepPercentage of [1, 10, 25, 50, 90, 99]) {
|
|
219
|
+
let kept: number = 0;
|
|
220
|
+
for (const draw of draws) {
|
|
221
|
+
if (!shouldDropBySampling(keepPercentage, fixedRandom(draw))) {
|
|
222
|
+
kept++;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Exact for a uniform sweep of 1000 draws over [0, 1).
|
|
226
|
+
expect(kept / 10).toBeCloseTo(keepPercentage, 5);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("defaults to Math.random when no generator is injected", () => {
|
|
231
|
+
// keep-99% over many real draws should keep at least one record.
|
|
232
|
+
let keptAtLeastOne: boolean = false;
|
|
233
|
+
for (let i: number = 0; i < 200; i++) {
|
|
234
|
+
if (!shouldDropBySampling(99)) {
|
|
235
|
+
keptAtLeastOne = true;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
expect(keptAtLeastOne).toBe(true);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import FilterCondition from "../../../Types/Filter/FilterCondition";
|
|
2
|
+
import NotificationRuleEventType from "../../../Types/Workspace/NotificationRules/EventType";
|
|
3
|
+
import {
|
|
4
|
+
ConditionType,
|
|
5
|
+
NotificationRuleConditionCheckOn,
|
|
6
|
+
NotificationRuleConditionUtil,
|
|
7
|
+
} from "../../../Types/Workspace/NotificationRules/NotificationRuleCondition";
|
|
8
|
+
import IncidentNotificationRule from "../../../Types/Workspace/NotificationRules/NotificationRuleTypes/IncidentNotificationRule";
|
|
9
|
+
import WorkspaceType from "../../../Types/Workspace/WorkspaceType";
|
|
10
|
+
import { describe, expect, it } from "@jest/globals";
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* NotificationRuleConditionUtil backs the workspace-notification-rule editor:
|
|
14
|
+
* getValidationError gates saving a rule, and the smaller helpers drive which
|
|
15
|
+
* inputs the form shows. A regression here either lets an unsavable rule
|
|
16
|
+
* through or hides the field the user needs, so the branches are pinned here.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
function baseRule(
|
|
20
|
+
overrides: Partial<IncidentNotificationRule> = {},
|
|
21
|
+
): IncidentNotificationRule {
|
|
22
|
+
return {
|
|
23
|
+
_type: "IncidentNotificationRule",
|
|
24
|
+
filterCondition: FilterCondition.All,
|
|
25
|
+
filters: [],
|
|
26
|
+
shouldCreateNewChannel: false,
|
|
27
|
+
shouldPostToExistingChannel: false,
|
|
28
|
+
existingChannelNames: "",
|
|
29
|
+
inviteTeamsToNewChannel: [],
|
|
30
|
+
inviteUsersToNewChannel: [],
|
|
31
|
+
shouldInviteOwnersToNewChannel: false,
|
|
32
|
+
newChannelTemplateName: "",
|
|
33
|
+
archiveChannelAutomatically: false,
|
|
34
|
+
shouldAutomaticallyInviteOnCallUsersToNewChannel: false,
|
|
35
|
+
...overrides,
|
|
36
|
+
} as IncidentNotificationRule;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("NotificationRuleConditionUtil.getValidationError", () => {
|
|
40
|
+
it("requires a conditionType when a filter has a checkOn but no condition", () => {
|
|
41
|
+
const error: string | null =
|
|
42
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
43
|
+
notificationRule: baseRule({
|
|
44
|
+
shouldCreateNewChannel: true,
|
|
45
|
+
newChannelTemplateName: "incident-{{id}}",
|
|
46
|
+
filters: [
|
|
47
|
+
{
|
|
48
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
|
|
49
|
+
conditionType: undefined,
|
|
50
|
+
value: "x",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
}),
|
|
54
|
+
eventType: NotificationRuleEventType.Incident,
|
|
55
|
+
workspaceType: WorkspaceType.Slack,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(error).toBe(
|
|
59
|
+
`Filter Condition is required for ${NotificationRuleConditionCheckOn.IncidentTitle}`,
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("requires a value when a filter has checkOn and condition but no value", () => {
|
|
64
|
+
const error: string | null =
|
|
65
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
66
|
+
notificationRule: baseRule({
|
|
67
|
+
shouldCreateNewChannel: true,
|
|
68
|
+
newChannelTemplateName: "incident-{{id}}",
|
|
69
|
+
filters: [
|
|
70
|
+
{
|
|
71
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
|
|
72
|
+
conditionType: ConditionType.EqualTo,
|
|
73
|
+
value: undefined,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
}),
|
|
77
|
+
eventType: NotificationRuleEventType.Incident,
|
|
78
|
+
workspaceType: WorkspaceType.Slack,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expect(error).toBe(
|
|
82
|
+
`Value is required for ${NotificationRuleConditionCheckOn.IncidentTitle}`,
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("treats an empty array value as a missing value", () => {
|
|
87
|
+
const error: string | null =
|
|
88
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
89
|
+
notificationRule: baseRule({
|
|
90
|
+
shouldCreateNewChannel: true,
|
|
91
|
+
newChannelTemplateName: "incident-{{id}}",
|
|
92
|
+
filters: [
|
|
93
|
+
{
|
|
94
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentLabels,
|
|
95
|
+
conditionType: ConditionType.ContainsAny,
|
|
96
|
+
value: [],
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
}),
|
|
100
|
+
eventType: NotificationRuleEventType.Incident,
|
|
101
|
+
workspaceType: WorkspaceType.Slack,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(error).toBe(
|
|
105
|
+
`Value is required for ${NotificationRuleConditionCheckOn.IncidentLabels}`,
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("requires a destination for incident rules when none is selected", () => {
|
|
110
|
+
const error: string | null =
|
|
111
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
112
|
+
notificationRule: baseRule(),
|
|
113
|
+
eventType: NotificationRuleEventType.Incident,
|
|
114
|
+
workspaceType: WorkspaceType.Slack,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(error).toBe(
|
|
118
|
+
"Please select a destination: create a Slack channel or post to an existing Slack channel",
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("mentions the chat option for Microsoft Teams destinations", () => {
|
|
123
|
+
const error: string | null =
|
|
124
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
125
|
+
notificationRule: baseRule(),
|
|
126
|
+
eventType: NotificationRuleEventType.Incident,
|
|
127
|
+
workspaceType: WorkspaceType.MicrosoftTeams,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(error).toBe(
|
|
131
|
+
"Please select a destination: create a Microsoft Teams channel, post to an existing Microsoft Teams channel, or post to an existing Microsoft Teams chat",
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("requires an existing channel name when posting to an existing channel", () => {
|
|
136
|
+
const error: string | null =
|
|
137
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
138
|
+
notificationRule: baseRule({
|
|
139
|
+
shouldPostToExistingChannel: true,
|
|
140
|
+
existingChannelNames: " ",
|
|
141
|
+
}),
|
|
142
|
+
eventType: NotificationRuleEventType.Incident,
|
|
143
|
+
workspaceType: WorkspaceType.Slack,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(error).toBe("Existing Slack channel name is required");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("requires a template name when creating a new channel", () => {
|
|
150
|
+
const error: string | null =
|
|
151
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
152
|
+
notificationRule: baseRule({
|
|
153
|
+
shouldCreateNewChannel: true,
|
|
154
|
+
newChannelTemplateName: "",
|
|
155
|
+
}),
|
|
156
|
+
eventType: NotificationRuleEventType.Incident,
|
|
157
|
+
workspaceType: WorkspaceType.Slack,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
expect(error).toBe("New Slack channel name is required");
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it("requires at least one chat when posting to an existing chat", () => {
|
|
164
|
+
const error: string | null =
|
|
165
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
166
|
+
notificationRule: baseRule({
|
|
167
|
+
shouldPostToExistingChat: true,
|
|
168
|
+
existingChatIds: [],
|
|
169
|
+
}),
|
|
170
|
+
eventType: NotificationRuleEventType.Incident,
|
|
171
|
+
workspaceType: WorkspaceType.MicrosoftTeams,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
expect(error).toContain(
|
|
175
|
+
"Please select at least one Microsoft Teams chat to post to",
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("returns null for a fully valid rule that creates a channel", () => {
|
|
180
|
+
const error: string | null =
|
|
181
|
+
NotificationRuleConditionUtil.getValidationError({
|
|
182
|
+
notificationRule: baseRule({
|
|
183
|
+
shouldCreateNewChannel: true,
|
|
184
|
+
newChannelTemplateName: "incident-{{id}}",
|
|
185
|
+
filters: [
|
|
186
|
+
{
|
|
187
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
|
|
188
|
+
conditionType: ConditionType.Contains,
|
|
189
|
+
value: "down",
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
}),
|
|
193
|
+
eventType: NotificationRuleEventType.Incident,
|
|
194
|
+
workspaceType: WorkspaceType.Slack,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
expect(error).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe("NotificationRuleConditionUtil.hasValueField", () => {
|
|
202
|
+
it.each([
|
|
203
|
+
ConditionType.IsEmpty,
|
|
204
|
+
ConditionType.IsNotEmpty,
|
|
205
|
+
ConditionType.True,
|
|
206
|
+
ConditionType.False,
|
|
207
|
+
])("hides the value field for %s", (conditionType: ConditionType) => {
|
|
208
|
+
expect(
|
|
209
|
+
NotificationRuleConditionUtil.hasValueField({
|
|
210
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
|
|
211
|
+
conditionType,
|
|
212
|
+
}),
|
|
213
|
+
).toBe(false);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it.each([
|
|
217
|
+
ConditionType.EqualTo,
|
|
218
|
+
ConditionType.Contains,
|
|
219
|
+
ConditionType.GreaterThan,
|
|
220
|
+
ConditionType.ContainsAll,
|
|
221
|
+
])("shows the value field for %s", (conditionType: ConditionType) => {
|
|
222
|
+
expect(
|
|
223
|
+
NotificationRuleConditionUtil.hasValueField({
|
|
224
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
|
|
225
|
+
conditionType,
|
|
226
|
+
}),
|
|
227
|
+
).toBe(true);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe("NotificationRuleConditionUtil.isDropdownValueField", () => {
|
|
232
|
+
it("returns false when checkOn or conditionType is missing", () => {
|
|
233
|
+
expect(
|
|
234
|
+
NotificationRuleConditionUtil.isDropdownValueField({
|
|
235
|
+
checkOn: undefined,
|
|
236
|
+
conditionType: ConditionType.ContainsAny,
|
|
237
|
+
}),
|
|
238
|
+
).toBe(false);
|
|
239
|
+
expect(
|
|
240
|
+
NotificationRuleConditionUtil.isDropdownValueField({
|
|
241
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentState,
|
|
242
|
+
conditionType: undefined,
|
|
243
|
+
}),
|
|
244
|
+
).toBe(false);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("returns true for enum/label-backed check-ons", () => {
|
|
248
|
+
expect(
|
|
249
|
+
NotificationRuleConditionUtil.isDropdownValueField({
|
|
250
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentState,
|
|
251
|
+
conditionType: ConditionType.ContainsAny,
|
|
252
|
+
}),
|
|
253
|
+
).toBe(true);
|
|
254
|
+
expect(
|
|
255
|
+
NotificationRuleConditionUtil.isDropdownValueField({
|
|
256
|
+
checkOn: NotificationRuleConditionCheckOn.MonitorLabels,
|
|
257
|
+
conditionType: ConditionType.ContainsAny,
|
|
258
|
+
}),
|
|
259
|
+
).toBe(true);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("returns false for free-text check-ons", () => {
|
|
263
|
+
expect(
|
|
264
|
+
NotificationRuleConditionUtil.isDropdownValueField({
|
|
265
|
+
checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
|
|
266
|
+
conditionType: ConditionType.Contains,
|
|
267
|
+
}),
|
|
268
|
+
).toBe(false);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe("NotificationRuleConditionUtil.getCheckOnByEventType", () => {
|
|
273
|
+
it("returns incident-scoped check-ons for the Incident event", () => {
|
|
274
|
+
const checkOns: Array<NotificationRuleConditionCheckOn> =
|
|
275
|
+
NotificationRuleConditionUtil.getCheckOnByEventType(
|
|
276
|
+
NotificationRuleEventType.Incident,
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
expect(checkOns).toContain(NotificationRuleConditionCheckOn.IncidentTitle);
|
|
280
|
+
expect(checkOns).toContain(NotificationRuleConditionCheckOn.IncidentState);
|
|
281
|
+
// Alert-only check-ons must not leak into the incident editor.
|
|
282
|
+
expect(checkOns).not.toContain(NotificationRuleConditionCheckOn.AlertTitle);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("returns monitor-scoped check-ons for the Monitor event", () => {
|
|
286
|
+
const checkOns: Array<NotificationRuleConditionCheckOn> =
|
|
287
|
+
NotificationRuleConditionUtil.getCheckOnByEventType(
|
|
288
|
+
NotificationRuleEventType.Monitor,
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
expect(checkOns).toContain(NotificationRuleConditionCheckOn.MonitorName);
|
|
292
|
+
expect(checkOns).toContain(NotificationRuleConditionCheckOn.MonitorStatus);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("returns an empty list for an event type with no check-ons", () => {
|
|
296
|
+
expect(
|
|
297
|
+
NotificationRuleConditionUtil.getCheckOnByEventType(
|
|
298
|
+
NotificationRuleEventType.OnCallDutyPolicy,
|
|
299
|
+
),
|
|
300
|
+
).toEqual([]);
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe("NotificationRuleConditionUtil.getConditionTypeByCheckOn", () => {
|
|
305
|
+
it("offers text operators for free-text fields", () => {
|
|
306
|
+
const conditions: Array<ConditionType> =
|
|
307
|
+
NotificationRuleConditionUtil.getConditionTypeByCheckOn(
|
|
308
|
+
NotificationRuleConditionCheckOn.IncidentTitle,
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
expect(conditions).toEqual([
|
|
312
|
+
ConditionType.EqualTo,
|
|
313
|
+
ConditionType.NotEqualTo,
|
|
314
|
+
ConditionType.Contains,
|
|
315
|
+
ConditionType.NotContains,
|
|
316
|
+
ConditionType.StartsWith,
|
|
317
|
+
ConditionType.EndsWith,
|
|
318
|
+
]);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("offers set operators including ContainsAll for label fields", () => {
|
|
322
|
+
const conditions: Array<ConditionType> =
|
|
323
|
+
NotificationRuleConditionUtil.getConditionTypeByCheckOn(
|
|
324
|
+
NotificationRuleConditionCheckOn.IncidentLabels,
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
expect(conditions).toEqual([
|
|
328
|
+
ConditionType.ContainsAny,
|
|
329
|
+
ConditionType.NotContains,
|
|
330
|
+
ConditionType.ContainsAll,
|
|
331
|
+
]);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it("offers only ContainsAny / NotContains for severity fields", () => {
|
|
335
|
+
const conditions: Array<ConditionType> =
|
|
336
|
+
NotificationRuleConditionUtil.getConditionTypeByCheckOn(
|
|
337
|
+
NotificationRuleConditionCheckOn.IncidentSeverity,
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
expect(conditions).toEqual([
|
|
341
|
+
ConditionType.ContainsAny,
|
|
342
|
+
ConditionType.NotContains,
|
|
343
|
+
]);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it("returns an empty list for a check-on with no configured operators", () => {
|
|
347
|
+
expect(
|
|
348
|
+
NotificationRuleConditionUtil.getConditionTypeByCheckOn(
|
|
349
|
+
NotificationRuleConditionCheckOn.OnCallDutyPolicyName,
|
|
350
|
+
),
|
|
351
|
+
).toEqual([]);
|
|
352
|
+
});
|
|
353
|
+
});
|