@oneuptime/common 12.0.4 → 12.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/AIRun.ts +38 -1
- package/Models/DatabaseModels/AlertFeed.ts +30 -0
- package/Models/DatabaseModels/Dashboard.ts +28 -0
- package/Models/DatabaseModels/Incident.ts +2 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentFeed.ts +30 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/LogSavedView.ts +33 -0
- package/Models/DatabaseModels/Project.ts +231 -9
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +4 -4
- package/Models/DatabaseModels/StatusPage.ts +28 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
- package/Server/API/AIAgentDataAPI.ts +44 -55
- package/Server/API/AIInvestigationAPI.ts +175 -17
- package/Server/API/DashboardAPI.ts +10 -10
- package/Server/API/StatusPageAPI.ts +38 -19
- package/Server/EnvironmentConfig.ts +16 -0
- package/Server/Infrastructure/ClickhouseConfig.ts +15 -1
- package/Server/Infrastructure/ClickhouseDatabase.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.ts +89 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AIRunService.ts +78 -10
- package/Server/Services/AIService.ts +94 -22
- package/Server/Services/AlertFeedService.ts +5 -0
- package/Server/Services/AnalyticsDatabaseService.ts +29 -0
- package/Server/Services/DatabaseService.ts +43 -2
- package/Server/Services/IncidentFeedService.ts +5 -0
- package/Server/Services/LlmLogService.ts +46 -2
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +6 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +4 -0
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +8 -5
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +90 -16
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +2 -0
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +2 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +223 -22
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/ConfidenceSignal.ts +182 -71
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +252 -43
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +47 -13
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +9 -5
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +141 -24
- package/Server/Utils/AI/SRE/InvestigationSubjectLock.ts +66 -0
- package/Server/Utils/AI/SRE/PostedRootCause.ts +94 -3
- package/Server/Utils/AI/SRE/README.md +1 -1
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +132 -10
- package/Server/Utils/AnalyticsDatabase/ClusterConfig.ts +24 -0
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +29 -0
- package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +56 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +46 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
- package/Server/Utils/PasswordHash.ts +28 -4
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +251 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +747 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +480 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1184 -0
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +500 -0
- package/Tests/App/Dashboard/PortMonitorCriteriaFilter.test.ts +93 -0
- package/Tests/App/StatusPage/PublicStatusPageAPIErrorHandling.test.ts +117 -0
- package/Tests/App/StatusPage/StatusPageModelAPIPolymorphism.test.ts +223 -0
- package/Tests/Models/DatabaseModels/PermissionCatalogueCoverage.test.ts +243 -0
- package/Tests/Server/API/AIAgentDataFixFromIncidentContext.test.ts +266 -0
- package/Tests/Server/API/AIInvestigationAPI.test.ts +594 -0
- package/Tests/Server/API/AIInvestigationCreateFixTask.test.ts +80 -0
- package/Tests/Server/API/DashboardMasterPasswordAPI.test.ts +172 -1
- package/Tests/Server/API/StatusPageMasterPasswordAPI.test.ts +335 -0
- package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +59 -5
- package/Tests/Server/Services/AIRunHumanVerdict.test.ts +127 -58
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +396 -20
- package/Tests/Server/Services/AddMasterPasswordSaltMigration.test.ts +283 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +25 -1
- package/Tests/Server/Services/DatabaseServicePerUserPasswordSalt.test.ts +45 -35
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +54 -0
- package/Tests/Server/Services/FeedAIRunAssociation.test.ts +125 -0
- package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +418 -57
- package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +173 -14
- package/Tests/Server/Services/MasterPasswordScrypt.test.ts +567 -0
- package/Tests/Server/Services/SeparateIncidentAlertAiSettingsMigration.test.ts +194 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +37 -4
- package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +330 -29
- package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +25 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +293 -5
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +59 -1
- package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +342 -19
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +214 -30
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +65 -17
- package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +3 -0
- package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +313 -20
- package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +4 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +2 -0
- package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +44 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +30 -0
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +212 -0
- package/Tests/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.test.ts +401 -0
- package/Tests/Server/Utils/Monitor/MonitorMetricUtilPortTimings.test.ts +243 -0
- package/Tests/Server/Utils/PasswordHash.test.ts +30 -0
- package/Tests/Types/Dashboard/DashboardTemplates.test.ts +111 -0
- package/Tests/Types/Monitor/CephMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/CriteriaFilter.test.ts +4 -0
- package/Tests/Types/Monitor/DockerMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/DockerSwarmMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/HostMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/IotMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +42 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +38 -0
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +75 -0
- package/Tests/Types/Monitor/PodmanMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/ProxmoxMetricCatalog.test.ts +107 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.test.ts +151 -0
- package/Tests/Types/Permission.test.ts +137 -0
- package/Tests/Types/Rum/SessionReplayMaskingMode.test.ts +101 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +5 -5
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +3 -5
- package/Tests/UI/Components/ErrorBoundary.test.tsx +158 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +74 -0
- package/Tests/UI/Components/MoreMenu.test.tsx +756 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +62 -0
- package/Tests/UI/Monitor/PortMonitorView.test.tsx +237 -0
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +91 -0
- package/Tests/UI/Utils/DownloadFile.test.ts +103 -0
- package/Tests/UI/Utils/ErrorSupportBundle.test.ts +582 -0
- package/Tests/UI/Utils/Project.test.ts +31 -0
- package/Tests/UI/Utils/StatusPageModelAPIInjection.test.ts +245 -0
- package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +820 -0
- package/Tests/Utils/Dashboard/DashboardViewConfig.test.ts +329 -0
- package/Tests/Utils/Dashboard/GridLayout.test.ts +951 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +117 -0
- package/Tests/Utils/RecordingRuleExpression.test.ts +327 -0
- package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +186 -0
- package/Tests/Utils/StatusPage/GroupTree.test.ts +456 -0
- package/Tests/Utils/StatusPage/OverviewGroupHierarchyVisibility.test.ts +588 -0
- package/Tests/Utils/Telemetry/SavedViewTimeRange.test.ts +244 -0
- package/Tests/Utils/Telemetry/TelemetryQueryTimeRange.test.ts +825 -0
- package/Types/AI/AIRunCodeFixRecommendation.ts +17 -0
- package/Types/AI/CodeFixTaskContext.ts +63 -3
- package/Types/AI/CodeFixTaskType.ts +3 -3
- package/Types/HashedString.ts +4 -3
- package/Types/Monitor/CriteriaFilter.ts +4 -0
- package/Types/Monitor/DomainMonitor/DomainLookupMethod.ts +23 -0
- package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +7 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +24 -7
- package/Types/Monitor/MonitorMetricType.ts +8 -0
- package/Types/Monitor/MonitorStep.ts +10 -1
- package/Types/Monitor/MonitorStepDomainMonitor.ts +21 -0
- package/Types/Monitor/PortMonitor/PortMonitorTimings.ts +10 -0
- package/Types/Permission.ts +23 -175
- package/Types/Probe/ProbeMonitorResponse.ts +6 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +2 -3
- package/UI/Components/ErrorBoundary.tsx +138 -11
- package/UI/Components/Feed/FeedItem.tsx +9 -2
- package/UI/Components/ModelDetail/CardModelDetail.tsx +0 -12
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +12 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +285 -97
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +8 -5
- package/UI/Utils/DownloadFile.ts +16 -8
- package/UI/Utils/ErrorSupportBundle.ts +805 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +19 -8
- package/UI/Utils/Project.ts +4 -0
- package/UI/Utils/StatusPage.ts +8 -2
- package/UI/Utils/UseDashboardGridDnd.ts +917 -0
- package/Utils/Dashboard/DashboardViewConfig.ts +80 -36
- package/Utils/Dashboard/GridLayout.ts +523 -0
- package/Utils/Metrics/RecordingRuleExpression.ts +19 -17
- package/Utils/Monitor/MonitorMetricType.ts +44 -2
- package/Utils/StatusPage/GroupNestingLayout.ts +69 -0
- package/Utils/StatusPage/GroupTree.ts +157 -66
- package/Utils/StatusPage/ResourceUptime.ts +37 -2
- package/Utils/Telemetry/SavedViewTimeRange.ts +114 -0
- package/Utils/Telemetry/TelemetryQueryTimeRange.ts +334 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +39 -1
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Dashboard.js +29 -0
- package/build/dist/Models/DatabaseModels/Dashboard.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +2 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.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/IncidentFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.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/LogSavedView.js +33 -0
- package/build/dist/Models/DatabaseModels/LogSavedView.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +241 -11
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +4 -4
- package/build/dist/Models/DatabaseModels/StatusPage.js +29 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +28 -46
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +111 -11
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +8 -5
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +29 -11
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +14 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js +12 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.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/AIRunService.js +58 -12
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +74 -21
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertFeedService.js +3 -0
- package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +29 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +21 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFeedService.js +3 -0
- package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
- package/build/dist/Server/Services/LlmLogService.js +22 -1
- package/build/dist/Server/Services/LlmLogService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +4 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +8 -5
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +63 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +156 -28
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +128 -49
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +170 -31
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +33 -9
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +9 -5
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +121 -41
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js +46 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +61 -14
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +79 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js +21 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +20 -3
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +43 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/PasswordHash.js +25 -4
- package/build/dist/Server/Utils/PasswordHash.js.map +1 -1
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js +18 -0
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js +23 -3
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskType.js +3 -3
- package/build/dist/Types/HashedString.js +4 -3
- package/build/dist/Types/HashedString.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js +24 -0
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +24 -7
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +7 -0
- package/build/dist/Types/Monitor/MonitorMetricType.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/MonitorStepDomainMonitor.js +15 -0
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js +2 -0
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js.map +1 -0
- package/build/dist/Types/Permission.js +23 -155
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +2 -5
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +67 -8
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +2 -2
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +0 -12
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +12 -2
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +193 -65
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Utils/DownloadFile.js +15 -8
- package/build/dist/UI/Utils/DownloadFile.js.map +1 -1
- package/build/dist/UI/Utils/ErrorSupportBundle.js +476 -0
- package/build/dist/UI/Utils/ErrorSupportBundle.js.map +1 -0
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -8
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Project.js +3 -0
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/UI/Utils/StatusPage.js +4 -4
- package/build/dist/UI/Utils/StatusPage.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js +551 -0
- package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js +42 -26
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js.map +1 -1
- package/build/dist/Utils/Dashboard/GridLayout.js +338 -0
- package/build/dist/Utils/Dashboard/GridLayout.js.map +1 -0
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js +19 -17
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +38 -6
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js +46 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupTree.js +79 -34
- package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js +22 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js +79 -0
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js.map +1 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js +236 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js.map +1 -0
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ import IncidentFeed, {
|
|
|
10
10
|
import SortOrder from "../../../../Types/BaseDatabase/SortOrder";
|
|
11
11
|
import ObjectID from "../../../../Types/ObjectID";
|
|
12
12
|
import { afterEach, describe, expect, it } from "@jest/globals";
|
|
13
|
+
import { FindOperator } from "typeorm";
|
|
13
14
|
|
|
14
15
|
/*
|
|
15
16
|
* The one reader of the analysis an AI investigation posted.
|
|
@@ -31,6 +32,9 @@ const INCIDENT_ID: ObjectID = new ObjectID(
|
|
|
31
32
|
"cccccccc-cccc-4ccc-8ccc-cccccccccccc",
|
|
32
33
|
);
|
|
33
34
|
const ALERT_ID: ObjectID = new ObjectID("dddddddd-dddd-4ddd-8ddd-dddddddddddd");
|
|
35
|
+
const AI_RUN_ID: ObjectID = new ObjectID(
|
|
36
|
+
"eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee",
|
|
37
|
+
);
|
|
34
38
|
|
|
35
39
|
function incidentFeedItem(markdown: string | null): IncidentFeed {
|
|
36
40
|
return {
|
|
@@ -44,6 +48,23 @@ function alertFeedItem(markdown: string | null): AlertFeed {
|
|
|
44
48
|
} as unknown as AlertFeed;
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
interface RawFindOperatorInternals {
|
|
52
|
+
_getSql: (columnName: string) => string;
|
|
53
|
+
_objectLiteralParameters: Record<string, unknown>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function expectCreatedAtCutoff(
|
|
57
|
+
createdAtFilter: unknown,
|
|
58
|
+
expectedCutoff: Date,
|
|
59
|
+
): void {
|
|
60
|
+
expect(createdAtFilter).toBeInstanceOf(FindOperator);
|
|
61
|
+
|
|
62
|
+
const raw: RawFindOperatorInternals =
|
|
63
|
+
createdAtFilter as RawFindOperatorInternals;
|
|
64
|
+
expect(raw._getSql("COLUMN")).toContain("COLUMN >=");
|
|
65
|
+
expect(Object.values(raw._objectLiteralParameters)).toEqual([expectedCutoff]);
|
|
66
|
+
}
|
|
67
|
+
|
|
47
68
|
describe("PostedRootCause.getForIncident", () => {
|
|
48
69
|
afterEach(() => {
|
|
49
70
|
jest.restoreAllMocks();
|
|
@@ -85,6 +106,73 @@ describe("PostedRootCause.getForIncident", () => {
|
|
|
85
106
|
}),
|
|
86
107
|
}),
|
|
87
108
|
);
|
|
109
|
+
const query: Record<string, unknown> = find.mock.calls[0]![0]
|
|
110
|
+
.query as Record<string, unknown>;
|
|
111
|
+
expect(Object.prototype.hasOwnProperty.call(query, "createdAt")).toBe(
|
|
112
|
+
false,
|
|
113
|
+
);
|
|
114
|
+
expect(Object.prototype.hasOwnProperty.call(query, "aiRunId")).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("can select the RootCause explicitly owned by one investigation run", async () => {
|
|
118
|
+
const find: jest.SpyInstance = jest
|
|
119
|
+
.spyOn(IncidentFeedService, "findOneBy")
|
|
120
|
+
.mockResolvedValue(null);
|
|
121
|
+
|
|
122
|
+
await PostedRootCause.getForIncident(INCIDENT_ID, {
|
|
123
|
+
aiRunId: AI_RUN_ID,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(find).toHaveBeenCalledWith(
|
|
127
|
+
expect.objectContaining({
|
|
128
|
+
query: expect.objectContaining({
|
|
129
|
+
incidentId: INCIDENT_ID,
|
|
130
|
+
incidentFeedEventType: IncidentFeedEventType.RootCause,
|
|
131
|
+
aiRunId: AI_RUN_ID,
|
|
132
|
+
}),
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("can restrict an upgrade lookup to rows without an AI run association", async () => {
|
|
138
|
+
const find: jest.SpyInstance = jest
|
|
139
|
+
.spyOn(IncidentFeedService, "findOneBy")
|
|
140
|
+
.mockResolvedValue(null);
|
|
141
|
+
|
|
142
|
+
await PostedRootCause.getForIncident(INCIDENT_ID, {
|
|
143
|
+
withoutAIRunId: true,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const aiRunIdFilter: unknown = find.mock.calls[0]![0].query.aiRunId;
|
|
147
|
+
expect(aiRunIdFilter).toBeInstanceOf(FindOperator);
|
|
148
|
+
expect(
|
|
149
|
+
(aiRunIdFilter as RawFindOperatorInternals)._getSql("COLUMN"),
|
|
150
|
+
).toContain("COLUMN IS NULL");
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("can scope the RootCause item to feed rows created by this run", async () => {
|
|
154
|
+
const runCompletedAt: Date = new Date("2026-08-07T10:00:00.000Z");
|
|
155
|
+
const find: jest.SpyInstance = jest
|
|
156
|
+
.spyOn(IncidentFeedService, "findOneBy")
|
|
157
|
+
.mockResolvedValue(null);
|
|
158
|
+
|
|
159
|
+
await PostedRootCause.getForIncident(INCIDENT_ID, {
|
|
160
|
+
createdAtOrAfter: runCompletedAt,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(find).toHaveBeenCalledWith(
|
|
164
|
+
expect.objectContaining({
|
|
165
|
+
query: expect.objectContaining({
|
|
166
|
+
incidentId: INCIDENT_ID,
|
|
167
|
+
incidentFeedEventType: IncidentFeedEventType.RootCause,
|
|
168
|
+
createdAt: expect.any(FindOperator),
|
|
169
|
+
}),
|
|
170
|
+
}),
|
|
171
|
+
);
|
|
172
|
+
expectCreatedAtCutoff(
|
|
173
|
+
find.mock.calls[0]![0].query.createdAt,
|
|
174
|
+
runCompletedAt,
|
|
175
|
+
);
|
|
88
176
|
});
|
|
89
177
|
|
|
90
178
|
it("returns null when no analysis has been posted", async () => {
|
|
@@ -166,6 +254,57 @@ describe("PostedRootCause.getForAlert", () => {
|
|
|
166
254
|
}),
|
|
167
255
|
}),
|
|
168
256
|
);
|
|
257
|
+
const query: Record<string, unknown> = find.mock.calls[0]![0]
|
|
258
|
+
.query as Record<string, unknown>;
|
|
259
|
+
expect(Object.prototype.hasOwnProperty.call(query, "createdAt")).toBe(
|
|
260
|
+
false,
|
|
261
|
+
);
|
|
262
|
+
expect(Object.prototype.hasOwnProperty.call(query, "aiRunId")).toBe(false);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it("can select the RootCause explicitly owned by one alert investigation", async () => {
|
|
266
|
+
const find: jest.SpyInstance = jest
|
|
267
|
+
.spyOn(AlertFeedService, "findOneBy")
|
|
268
|
+
.mockResolvedValue(null);
|
|
269
|
+
|
|
270
|
+
await PostedRootCause.getForAlert(ALERT_ID, {
|
|
271
|
+
aiRunId: AI_RUN_ID,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
expect(find).toHaveBeenCalledWith(
|
|
275
|
+
expect.objectContaining({
|
|
276
|
+
query: expect.objectContaining({
|
|
277
|
+
alertId: ALERT_ID,
|
|
278
|
+
alertFeedEventType: AlertFeedEventType.RootCause,
|
|
279
|
+
aiRunId: AI_RUN_ID,
|
|
280
|
+
}),
|
|
281
|
+
}),
|
|
282
|
+
);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("can scope the RootCause item to alert feed rows created by this run", async () => {
|
|
286
|
+
const runCompletedAt: Date = new Date("2026-08-07T11:00:00.000Z");
|
|
287
|
+
const find: jest.SpyInstance = jest
|
|
288
|
+
.spyOn(AlertFeedService, "findOneBy")
|
|
289
|
+
.mockResolvedValue(null);
|
|
290
|
+
|
|
291
|
+
await PostedRootCause.getForAlert(ALERT_ID, {
|
|
292
|
+
createdAtOrAfter: runCompletedAt,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
expect(find).toHaveBeenCalledWith(
|
|
296
|
+
expect.objectContaining({
|
|
297
|
+
query: expect.objectContaining({
|
|
298
|
+
alertId: ALERT_ID,
|
|
299
|
+
alertFeedEventType: AlertFeedEventType.RootCause,
|
|
300
|
+
createdAt: expect.any(FindOperator),
|
|
301
|
+
}),
|
|
302
|
+
}),
|
|
303
|
+
);
|
|
304
|
+
expectCreatedAtCutoff(
|
|
305
|
+
find.mock.calls[0]![0].query.createdAt,
|
|
306
|
+
runCompletedAt,
|
|
307
|
+
);
|
|
169
308
|
});
|
|
170
309
|
|
|
171
310
|
it("returns null when no analysis has been posted", async () => {
|
|
@@ -196,6 +335,43 @@ describe("PostedRootCause.getForSubject", () => {
|
|
|
196
335
|
expect(alertFind).not.toHaveBeenCalled();
|
|
197
336
|
});
|
|
198
337
|
|
|
338
|
+
it("forwards the run boundary to the subject-specific reader", async () => {
|
|
339
|
+
const runCompletedAt: Date = new Date("2026-08-07T12:00:00.000Z");
|
|
340
|
+
const getForIncident: jest.SpyInstance = jest
|
|
341
|
+
.spyOn(PostedRootCause, "getForIncident")
|
|
342
|
+
.mockResolvedValue("current analysis");
|
|
343
|
+
|
|
344
|
+
expect(
|
|
345
|
+
await PostedRootCause.getForSubject({
|
|
346
|
+
incidentId: INCIDENT_ID,
|
|
347
|
+
createdAtOrAfter: runCompletedAt,
|
|
348
|
+
}),
|
|
349
|
+
).toBe("current analysis");
|
|
350
|
+
expect(getForIncident).toHaveBeenCalledWith(INCIDENT_ID, {
|
|
351
|
+
aiRunId: undefined,
|
|
352
|
+
withoutAIRunId: undefined,
|
|
353
|
+
createdAtOrAfter: runCompletedAt,
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it("forwards the exact run id to the subject-specific reader", async () => {
|
|
358
|
+
const getForAlert: jest.SpyInstance = jest
|
|
359
|
+
.spyOn(PostedRootCause, "getForAlert")
|
|
360
|
+
.mockResolvedValue("current alert analysis");
|
|
361
|
+
|
|
362
|
+
expect(
|
|
363
|
+
await PostedRootCause.getForSubject({
|
|
364
|
+
alertId: ALERT_ID,
|
|
365
|
+
aiRunId: AI_RUN_ID,
|
|
366
|
+
}),
|
|
367
|
+
).toBe("current alert analysis");
|
|
368
|
+
expect(getForAlert).toHaveBeenCalledWith(ALERT_ID, {
|
|
369
|
+
aiRunId: AI_RUN_ID,
|
|
370
|
+
withoutAIRunId: undefined,
|
|
371
|
+
createdAtOrAfter: undefined,
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
199
375
|
it("reads the alert feed for an alert subject", async () => {
|
|
200
376
|
const alertFind: jest.SpyInstance = jest
|
|
201
377
|
.spyOn(AlertFeedService, "findOneBy")
|
|
@@ -252,3 +428,81 @@ describe("PostedRootCause.getForSubject", () => {
|
|
|
252
428
|
expect(alertFind).not.toHaveBeenCalled();
|
|
253
429
|
});
|
|
254
430
|
});
|
|
431
|
+
|
|
432
|
+
describe("PostedRootCause.getForInvestigation", () => {
|
|
433
|
+
afterEach(() => {
|
|
434
|
+
jest.restoreAllMocks();
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it("returns the exact run-associated report without a legacy lookup", async () => {
|
|
438
|
+
const getForSubject: jest.SpyInstance = jest
|
|
439
|
+
.spyOn(PostedRootCause, "getForSubject")
|
|
440
|
+
.mockResolvedValue("exact report");
|
|
441
|
+
|
|
442
|
+
expect(
|
|
443
|
+
await PostedRootCause.getForInvestigation({
|
|
444
|
+
incidentId: INCIDENT_ID,
|
|
445
|
+
aiRunId: AI_RUN_ID,
|
|
446
|
+
}),
|
|
447
|
+
).toBe("exact report");
|
|
448
|
+
expect(getForSubject).toHaveBeenCalledTimes(1);
|
|
449
|
+
expect(getForSubject).toHaveBeenCalledWith({
|
|
450
|
+
incidentId: INCIDENT_ID,
|
|
451
|
+
alertId: undefined,
|
|
452
|
+
aiRunId: AI_RUN_ID,
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it("recovers a branded null-associated report across a deployment-safe upgrade window", async () => {
|
|
457
|
+
const runCompletedAt: Date = new Date("2026-08-08T10:00:00.000Z");
|
|
458
|
+
const legacyReport: string =
|
|
459
|
+
"## AI — Automated Root Cause Analysis\n\nHistorical evidence.";
|
|
460
|
+
const getForSubject: jest.SpyInstance = jest
|
|
461
|
+
.spyOn(PostedRootCause, "getForSubject")
|
|
462
|
+
.mockResolvedValueOnce(null)
|
|
463
|
+
.mockResolvedValueOnce(legacyReport);
|
|
464
|
+
|
|
465
|
+
expect(
|
|
466
|
+
await PostedRootCause.getForInvestigation({
|
|
467
|
+
alertId: ALERT_ID,
|
|
468
|
+
aiRunId: AI_RUN_ID,
|
|
469
|
+
runCompletedAt,
|
|
470
|
+
}),
|
|
471
|
+
).toBe(legacyReport);
|
|
472
|
+
expect(getForSubject).toHaveBeenNthCalledWith(2, {
|
|
473
|
+
incidentId: undefined,
|
|
474
|
+
alertId: ALERT_ID,
|
|
475
|
+
withoutAIRunId: true,
|
|
476
|
+
createdAtOrAfter: runCompletedAt,
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
it("rejects ordinary RootCause markdown from the legacy path", async () => {
|
|
481
|
+
jest
|
|
482
|
+
.spyOn(PostedRootCause, "getForSubject")
|
|
483
|
+
.mockResolvedValueOnce(null)
|
|
484
|
+
.mockResolvedValueOnce("## Root cause\n\nWritten by an engineer.");
|
|
485
|
+
|
|
486
|
+
expect(
|
|
487
|
+
await PostedRootCause.getForInvestigation({
|
|
488
|
+
incidentId: INCIDENT_ID,
|
|
489
|
+
aiRunId: AI_RUN_ID,
|
|
490
|
+
runCompletedAt: new Date("2026-08-08T10:00:00.000Z"),
|
|
491
|
+
}),
|
|
492
|
+
).toBeNull();
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it("never falls back to an unassociated row without a reliable completion boundary", async () => {
|
|
496
|
+
const getForSubject: jest.SpyInstance = jest
|
|
497
|
+
.spyOn(PostedRootCause, "getForSubject")
|
|
498
|
+
.mockResolvedValue(null);
|
|
499
|
+
|
|
500
|
+
expect(
|
|
501
|
+
await PostedRootCause.getForInvestigation({
|
|
502
|
+
incidentId: INCIDENT_ID,
|
|
503
|
+
aiRunId: AI_RUN_ID,
|
|
504
|
+
}),
|
|
505
|
+
).toBeNull();
|
|
506
|
+
expect(getForSubject).toHaveBeenCalledTimes(1);
|
|
507
|
+
});
|
|
508
|
+
});
|
|
@@ -547,6 +547,8 @@ describe("RemediationExecutionRunner.executeRemediation", () => {
|
|
|
547
547
|
);
|
|
548
548
|
// Persisted budget-ledger string — pinned as a literal on purpose.
|
|
549
549
|
expect(request.get().feature).toBe("AI Remediation Execution");
|
|
550
|
+
expect(request.get().incidentId).toBe(INCIDENT_ID);
|
|
551
|
+
expect(request.get().alertId).toBeUndefined();
|
|
550
552
|
});
|
|
551
553
|
|
|
552
554
|
it("runs FullAuto with the execute tool and the allowlist in context when every condition holds", async () => {
|
|
@@ -859,6 +861,8 @@ describe("RemediationExecutionRunner.executeRemediation", () => {
|
|
|
859
861
|
'<untrusted_context source="alert_text">',
|
|
860
862
|
);
|
|
861
863
|
expect(captured!.contextSummary).toContain("Disk almost full on db-1");
|
|
864
|
+
expect(captured!.incidentId).toBeUndefined();
|
|
865
|
+
expect(captured!.alertId).toBe(ALERT_ID);
|
|
862
866
|
expect(incidentFeed).not.toHaveBeenCalled();
|
|
863
867
|
expect(alertFeed).toHaveBeenCalledWith(
|
|
864
868
|
expect.objectContaining({
|
|
@@ -260,6 +260,8 @@ describe("RemediationPlanRunner.executePlan", () => {
|
|
|
260
260
|
request: expect.objectContaining({
|
|
261
261
|
// Persisted budget-ledger string — pinned as a literal on purpose.
|
|
262
262
|
feature: "AI Remediation Planning",
|
|
263
|
+
incidentId: INCIDENT_ID,
|
|
264
|
+
alertId: undefined,
|
|
263
265
|
}),
|
|
264
266
|
}),
|
|
265
267
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import SubjectCodeFixRun from "../../../../Server/Utils/AI/SRE/SubjectCodeFixRun";
|
|
2
|
+
import FixRunBudget from "../../../../Server/Utils/AI/CodeFix/FixRunBudget";
|
|
2
3
|
import AIRunService from "../../../../Server/Services/AIRunService";
|
|
3
4
|
import QueryHelper from "../../../../Server/Types/Database/QueryHelper";
|
|
4
5
|
import AIRun from "../../../../Models/DatabaseModels/AIRun";
|
|
@@ -119,6 +120,27 @@ describe("SubjectCodeFixRun dedupe guards", () => {
|
|
|
119
120
|
});
|
|
120
121
|
|
|
121
122
|
describe("findNonTerminalRunForSubject", () => {
|
|
123
|
+
test.each([
|
|
124
|
+
{ label: "neither", input: {} },
|
|
125
|
+
{ label: "both", input: { incidentId, alertId } },
|
|
126
|
+
])(
|
|
127
|
+
"rejects $label subject type before querying",
|
|
128
|
+
async ({
|
|
129
|
+
input,
|
|
130
|
+
}: {
|
|
131
|
+
input: { incidentId?: ObjectID; alertId?: ObjectID };
|
|
132
|
+
}) => {
|
|
133
|
+
await expect(
|
|
134
|
+
SubjectCodeFixRun.findNonTerminalRunForSubject({
|
|
135
|
+
taskType: CodeFixTaskType.FixFromIncident,
|
|
136
|
+
...input,
|
|
137
|
+
}),
|
|
138
|
+
).rejects.toThrow(/Exactly one/);
|
|
139
|
+
|
|
140
|
+
expect(AIRunService.findOneBy).not.toHaveBeenCalled();
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
|
|
122
144
|
test("a NoFixFound run does NOT block a new run for the same subject", async () => {
|
|
123
145
|
storeRun(AIRunStatus.NoFixFound);
|
|
124
146
|
|
|
@@ -176,6 +198,28 @@ describe("SubjectCodeFixRun dedupe guards", () => {
|
|
|
176
198
|
});
|
|
177
199
|
});
|
|
178
200
|
|
|
201
|
+
describe("enqueueSubjectCodeFixRun", () => {
|
|
202
|
+
test("rejects a dual-subject run before the budget check or write", async () => {
|
|
203
|
+
const assertWithinBudget: jest.SpyInstance = jest.spyOn(
|
|
204
|
+
FixRunBudget,
|
|
205
|
+
"assertWithinBudget",
|
|
206
|
+
);
|
|
207
|
+
const create: jest.SpyInstance = jest.spyOn(AIRunService, "create");
|
|
208
|
+
|
|
209
|
+
await expect(
|
|
210
|
+
SubjectCodeFixRun.enqueueSubjectCodeFixRun({
|
|
211
|
+
projectId,
|
|
212
|
+
taskType: CodeFixTaskType.FixFromIncident,
|
|
213
|
+
incidentId,
|
|
214
|
+
alertId,
|
|
215
|
+
}),
|
|
216
|
+
).rejects.toThrow(/both an incident and an alert/);
|
|
217
|
+
|
|
218
|
+
expect(assertWithinBudget).not.toHaveBeenCalled();
|
|
219
|
+
expect(create).not.toHaveBeenCalled();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
179
223
|
describe("findNonTerminalPerformanceFixRunForTrace", () => {
|
|
180
224
|
test("a NoFixFound run does NOT block a new run for the same trace", async () => {
|
|
181
225
|
storeRun(AIRunStatus.NoFixFound);
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
adaptTableSettingsForStorage,
|
|
9
9
|
applyClusterToMaterializedViewQuery,
|
|
10
10
|
getClickhouseClusterName,
|
|
11
|
+
getDistributedDdlTaskTimeoutSeconds,
|
|
11
12
|
getDistributedEngine,
|
|
12
13
|
getStorageEngine,
|
|
13
14
|
getStorageTableName,
|
|
@@ -33,6 +34,8 @@ import MetricBaselineHourly from "../../../../Models/AnalyticsModels/MetricBasel
|
|
|
33
34
|
|
|
34
35
|
const CLUSTER_ENV_KEY: string = "CLICKHOUSE_CLUSTER_NAME";
|
|
35
36
|
const SHARDING_ENV_KEY: string = "CLICKHOUSE_SHARDING_KEY";
|
|
37
|
+
const DDL_TIMEOUT_ENV_KEY: string =
|
|
38
|
+
"CLICKHOUSE_DISTRIBUTED_DDL_TASK_TIMEOUT_SECONDS";
|
|
36
39
|
|
|
37
40
|
/*
|
|
38
41
|
* Flatten a Statement into a single string (raw SQL + serialized identifier
|
|
@@ -49,6 +52,8 @@ function fullText(statement: Statement | string): string {
|
|
|
49
52
|
describe("ClickHouse cluster-aware schema (always-on)", () => {
|
|
50
53
|
const originalCluster: string | undefined = process.env[CLUSTER_ENV_KEY];
|
|
51
54
|
const originalSharding: string | undefined = process.env[SHARDING_ENV_KEY];
|
|
55
|
+
const originalDdlTimeout: string | undefined =
|
|
56
|
+
process.env[DDL_TIMEOUT_ENV_KEY];
|
|
52
57
|
|
|
53
58
|
afterEach(() => {
|
|
54
59
|
if (originalCluster === undefined) {
|
|
@@ -61,6 +66,11 @@ describe("ClickHouse cluster-aware schema (always-on)", () => {
|
|
|
61
66
|
} else {
|
|
62
67
|
process.env[SHARDING_ENV_KEY] = originalSharding;
|
|
63
68
|
}
|
|
69
|
+
if (originalDdlTimeout === undefined) {
|
|
70
|
+
delete process.env[DDL_TIMEOUT_ENV_KEY];
|
|
71
|
+
} else {
|
|
72
|
+
process.env[DDL_TIMEOUT_ENV_KEY] = originalDdlTimeout;
|
|
73
|
+
}
|
|
64
74
|
});
|
|
65
75
|
|
|
66
76
|
describe("ClusterConfig helpers", () => {
|
|
@@ -101,6 +111,26 @@ describe("ClickHouse cluster-aware schema (always-on)", () => {
|
|
|
101
111
|
);
|
|
102
112
|
});
|
|
103
113
|
|
|
114
|
+
test("distributed DDL task timeout: default 180, overridable, garbage-safe", () => {
|
|
115
|
+
delete process.env[DDL_TIMEOUT_ENV_KEY];
|
|
116
|
+
expect(getDistributedDdlTaskTimeoutSeconds()).toBe(180);
|
|
117
|
+
|
|
118
|
+
process.env[DDL_TIMEOUT_ENV_KEY] = "1800";
|
|
119
|
+
expect(getDistributedDdlTaskTimeoutSeconds()).toBe(1800);
|
|
120
|
+
|
|
121
|
+
// ClickHouse semantics pass through: 0 = async, negative = no server cap.
|
|
122
|
+
process.env[DDL_TIMEOUT_ENV_KEY] = "0";
|
|
123
|
+
expect(getDistributedDdlTaskTimeoutSeconds()).toBe(0);
|
|
124
|
+
process.env[DDL_TIMEOUT_ENV_KEY] = "-1";
|
|
125
|
+
expect(getDistributedDdlTaskTimeoutSeconds()).toBe(-1);
|
|
126
|
+
|
|
127
|
+
// Garbage and whitespace fall back to the default.
|
|
128
|
+
process.env[DDL_TIMEOUT_ENV_KEY] = "not-a-number";
|
|
129
|
+
expect(getDistributedDdlTaskTimeoutSeconds()).toBe(180);
|
|
130
|
+
process.env[DDL_TIMEOUT_ENV_KEY] = " ";
|
|
131
|
+
expect(getDistributedDdlTaskTimeoutSeconds()).toBe(180);
|
|
132
|
+
});
|
|
133
|
+
|
|
104
134
|
test("distributed engine: model key, with global override winning", () => {
|
|
105
135
|
delete process.env[SHARDING_ENV_KEY];
|
|
106
136
|
// model sharding key is used
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import APIRequestCriteria from "../../../../../Server/Utils/Monitor/Criteria/APIRequestCriteria";
|
|
2
|
+
import EvaluateOverTime from "../../../../../Server/Utils/Monitor/Criteria/EvaluateOverTime";
|
|
3
|
+
import {
|
|
4
|
+
CheckOn,
|
|
5
|
+
CriteriaFilter,
|
|
6
|
+
EvaluateOverTimeType,
|
|
7
|
+
FilterType,
|
|
8
|
+
} from "../../../../../Types/Monitor/CriteriaFilter";
|
|
9
|
+
import PortMonitorTimings from "../../../../../Types/Monitor/PortMonitor/PortMonitorTimings";
|
|
10
|
+
import ProbeMonitorResponse from "../../../../../Types/Probe/ProbeMonitorResponse";
|
|
11
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
12
|
+
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
13
|
+
|
|
14
|
+
function buildResponse(portTimings?: PortMonitorTimings): ProbeMonitorResponse {
|
|
15
|
+
return {
|
|
16
|
+
projectId: ObjectID.generate(),
|
|
17
|
+
monitorId: ObjectID.generate(),
|
|
18
|
+
monitorStepId: ObjectID.generate(),
|
|
19
|
+
probeId: ObjectID.generate(),
|
|
20
|
+
failureCause: "",
|
|
21
|
+
monitoredAt: new Date(),
|
|
22
|
+
portTimings: portTimings,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function criteria(input: {
|
|
27
|
+
checkOn: CheckOn.PortDnsLookupTime | CheckOn.PortTcpConnectTime;
|
|
28
|
+
filterType?: FilterType;
|
|
29
|
+
value: number | string;
|
|
30
|
+
evaluateOverTime?: boolean;
|
|
31
|
+
}): CriteriaFilter {
|
|
32
|
+
return {
|
|
33
|
+
checkOn: input.checkOn,
|
|
34
|
+
filterType: input.filterType || FilterType.GreaterThan,
|
|
35
|
+
value: input.value,
|
|
36
|
+
evaluateOverTime: input.evaluateOverTime,
|
|
37
|
+
evaluateOverTimeOptions: input.evaluateOverTime
|
|
38
|
+
? {
|
|
39
|
+
timeValueInMinutes: 5,
|
|
40
|
+
evaluateOverTimeType: EvaluateOverTimeType.Average,
|
|
41
|
+
}
|
|
42
|
+
: undefined,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function evaluate(
|
|
47
|
+
response: ProbeMonitorResponse,
|
|
48
|
+
criteriaFilter: CriteriaFilter,
|
|
49
|
+
): Promise<string | null> {
|
|
50
|
+
return APIRequestCriteria.isMonitorInstanceCriteriaFilterMet({
|
|
51
|
+
dataToProcess: response,
|
|
52
|
+
criteriaFilter: criteriaFilter,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe("APIRequestCriteria Port connection phase timings", () => {
|
|
57
|
+
afterEach(() => {
|
|
58
|
+
jest.restoreAllMocks();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("evaluates the current DNS lookup duration", async () => {
|
|
62
|
+
const result: string | null = await evaluate(
|
|
63
|
+
buildResponse({
|
|
64
|
+
dnsLookupInMs: 151,
|
|
65
|
+
tcpConnectInMs: 25,
|
|
66
|
+
totalConnectionInMs: 176,
|
|
67
|
+
}),
|
|
68
|
+
criteria({ checkOn: CheckOn.PortDnsLookupTime, value: "150" }),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
expect(result).toContain(CheckOn.PortDnsLookupTime);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("returns null when the current DNS lookup duration is below the threshold", async () => {
|
|
75
|
+
const result: string | null = await evaluate(
|
|
76
|
+
buildResponse({
|
|
77
|
+
dnsLookupInMs: 149,
|
|
78
|
+
tcpConnectInMs: 25,
|
|
79
|
+
totalConnectionInMs: 174,
|
|
80
|
+
}),
|
|
81
|
+
criteria({ checkOn: CheckOn.PortDnsLookupTime, value: 150 }),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(result).toBeNull();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("evaluates the current TCP connect duration independently of DNS", async () => {
|
|
88
|
+
const result: string | null = await evaluate(
|
|
89
|
+
buildResponse({
|
|
90
|
+
dnsLookupInMs: 300,
|
|
91
|
+
tcpConnectInMs: 75,
|
|
92
|
+
totalConnectionInMs: 375,
|
|
93
|
+
}),
|
|
94
|
+
criteria({
|
|
95
|
+
checkOn: CheckOn.PortTcpConnectTime,
|
|
96
|
+
filterType: FilterType.GreaterThanOrEqualTo,
|
|
97
|
+
value: 75,
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(result).toContain(CheckOn.PortTcpConnectTime);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("treats an absent DNS phase on an IP-literal destination as no data", async () => {
|
|
105
|
+
const result: string | null = await evaluate(
|
|
106
|
+
buildResponse({ tcpConnectInMs: 20, totalConnectionInMs: 20 }),
|
|
107
|
+
criteria({
|
|
108
|
+
checkOn: CheckOn.PortDnsLookupTime,
|
|
109
|
+
filterType: FilterType.LessThan,
|
|
110
|
+
value: 100,
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
expect(result).toBeNull();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("treats an absent TCP phase on a failed pre-connect check as no data", async () => {
|
|
118
|
+
const result: string | null = await evaluate(
|
|
119
|
+
buildResponse({ dnsLookupInMs: 100, totalConnectionInMs: 100 }),
|
|
120
|
+
criteria({ checkOn: CheckOn.PortTcpConnectTime, value: 10 }),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
expect(result).toBeNull();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("preserves a legitimate zero-millisecond phase", async () => {
|
|
127
|
+
const result: string | null = await evaluate(
|
|
128
|
+
buildResponse({
|
|
129
|
+
dnsLookupInMs: 0,
|
|
130
|
+
tcpConnectInMs: 0,
|
|
131
|
+
totalConnectionInMs: 0,
|
|
132
|
+
}),
|
|
133
|
+
criteria({
|
|
134
|
+
checkOn: CheckOn.PortDnsLookupTime,
|
|
135
|
+
filterType: FilterType.LessThan,
|
|
136
|
+
value: 1,
|
|
137
|
+
}),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
expect(result).not.toBeNull();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("uses an evaluate-over-time aggregate instead of the current phase", async () => {
|
|
144
|
+
const overTimeSpy: ReturnType<typeof jest.spyOn> = jest
|
|
145
|
+
.spyOn(EvaluateOverTime, "getValueOverTime")
|
|
146
|
+
.mockResolvedValue(250);
|
|
147
|
+
|
|
148
|
+
const response: ProbeMonitorResponse = buildResponse({
|
|
149
|
+
dnsLookupInMs: 5,
|
|
150
|
+
tcpConnectInMs: 10,
|
|
151
|
+
totalConnectionInMs: 15,
|
|
152
|
+
});
|
|
153
|
+
const result: string | null = await evaluate(
|
|
154
|
+
response,
|
|
155
|
+
criteria({
|
|
156
|
+
checkOn: CheckOn.PortDnsLookupTime,
|
|
157
|
+
value: 200,
|
|
158
|
+
evaluateOverTime: true,
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
expect(result).not.toBeNull();
|
|
163
|
+
expect(overTimeSpy).toHaveBeenCalledWith(
|
|
164
|
+
expect.objectContaining({
|
|
165
|
+
projectId: response.projectId,
|
|
166
|
+
monitorId: response.monitorId,
|
|
167
|
+
metricType: CheckOn.PortDnsLookupTime,
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test("does not replace a zero evaluate-over-time aggregate with the current value", async () => {
|
|
173
|
+
jest.spyOn(EvaluateOverTime, "getValueOverTime").mockResolvedValue(0);
|
|
174
|
+
|
|
175
|
+
const result: string | null = await evaluate(
|
|
176
|
+
buildResponse({
|
|
177
|
+
dnsLookupInMs: 500,
|
|
178
|
+
tcpConnectInMs: 10,
|
|
179
|
+
totalConnectionInMs: 510,
|
|
180
|
+
}),
|
|
181
|
+
criteria({
|
|
182
|
+
checkOn: CheckOn.PortDnsLookupTime,
|
|
183
|
+
filterType: FilterType.LessThan,
|
|
184
|
+
value: 1,
|
|
185
|
+
evaluateOverTime: true,
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
expect(result).not.toBeNull();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("falls back to the current phase if the history query fails", async () => {
|
|
193
|
+
jest
|
|
194
|
+
.spyOn(EvaluateOverTime, "getValueOverTime")
|
|
195
|
+
.mockRejectedValue(new Error("history unavailable"));
|
|
196
|
+
|
|
197
|
+
const result: string | null = await evaluate(
|
|
198
|
+
buildResponse({
|
|
199
|
+
dnsLookupInMs: 1,
|
|
200
|
+
tcpConnectInMs: 250,
|
|
201
|
+
totalConnectionInMs: 251,
|
|
202
|
+
}),
|
|
203
|
+
criteria({
|
|
204
|
+
checkOn: CheckOn.PortTcpConnectTime,
|
|
205
|
+
value: 200,
|
|
206
|
+
evaluateOverTime: true,
|
|
207
|
+
}),
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
expect(result).not.toBeNull();
|
|
211
|
+
});
|
|
212
|
+
});
|