@oneuptime/common 11.4.0 → 11.5.0
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 +50 -0
- package/Models/DatabaseModels/AlertSeverity.ts +6 -0
- package/Models/DatabaseModels/IncidentSeverity.ts +6 -0
- package/Models/DatabaseModels/Index.ts +16 -0
- package/Models/DatabaseModels/IoTDeviceCredential.ts +471 -0
- package/Models/DatabaseModels/LlmLog.ts +56 -0
- package/Models/DatabaseModels/LlmProvider.ts +33 -0
- package/Models/DatabaseModels/NetworkDevice.ts +1385 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +717 -0
- package/Models/DatabaseModels/NetworkDeviceLabelRule.ts +514 -0
- package/Models/DatabaseModels/NetworkDeviceOwnerRule.ts +596 -0
- package/Models/DatabaseModels/NetworkDeviceOwnerTeam.ts +487 -0
- package/Models/DatabaseModels/NetworkDeviceOwnerUser.ts +486 -0
- package/Models/DatabaseModels/NetworkInterface.ts +563 -0
- package/Models/DatabaseModels/Project.ts +145 -0
- package/Models/DatabaseModels/TelemetryEntityRelationship.ts +54 -0
- package/Server/API/AIAgentTaskAPI.ts +10 -24
- package/Server/API/AIInvestigationAPI.ts +131 -63
- package/Server/API/AlertAPI.ts +5 -0
- package/Server/API/IncidentAPI.ts +10 -0
- package/Server/API/IncidentEpisodeAPI.ts +5 -0
- package/Server/API/LlmProviderAPI.ts +4 -0
- package/Server/API/ScheduledMaintenanceAPI.ts +5 -0
- package/Server/API/TelemetryAPI.ts +4 -3
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783650000000-AddAdditionalParamsToLlmProvider.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783695782697-AddCacheTokenColumnsToLlmLog.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783701585317-AddAlertInvestigationGating.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783702431535-AddAiDailyAutonomousTokenLimitToProject.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783720000000-AddNetworkDeviceTables.ts +105 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783721121260-AddAttemptCountToAIRun.ts +15 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783730000000-AddNetworkDeviceOwnersAndRules.ts +192 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783740000000-AddNetworkDeviceDiscoveryScan.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783750000000-AddLldpNeighborsToNetworkDevice.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783760576655-AddInvestigationTuningToProject.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783762505482-AddTelemetryEntityRelationshipMetrics.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783780000000-AddIoTDeviceCredentialTable.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783790000000-AddSnmpV3AuthColumnsToNetworkDevice.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +24 -0
- package/Server/Services/AIAgentTaskService.ts +62 -0
- package/Server/Services/AIRunService.ts +58 -0
- package/Server/Services/AIService.ts +101 -0
- package/Server/Services/AnalyticsDatabaseService.ts +27 -0
- package/Server/Services/IncidentService.ts +14 -41
- package/Server/Services/Index.ts +14 -0
- package/Server/Services/IoTDeviceCredentialService.ts +351 -0
- package/Server/Services/IoTDeviceService.ts +64 -21
- package/Server/Services/LlmLogService.ts +26 -0
- package/Server/Services/LlmProviderService.ts +3 -0
- package/Server/Services/LogAggregationService.ts +29 -11
- package/Server/Services/MetricService.ts +603 -13
- package/Server/Services/MonitorService.ts +4 -1
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +10 -0
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +204 -0
- package/Server/Services/NetworkDeviceLabelRuleService.ts +14 -0
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +222 -0
- package/Server/Services/NetworkDeviceOwnerRuleService.ts +14 -0
- package/Server/Services/NetworkDeviceOwnerTeamService.ts +10 -0
- package/Server/Services/NetworkDeviceOwnerUserService.ts +10 -0
- package/Server/Services/NetworkDeviceService.ts +50 -0
- package/Server/Services/NetworkInterfaceService.ts +10 -0
- package/Server/Services/TelemetryEntityRelationshipService.ts +23 -0
- package/Server/Services/TelemetryEntityService.ts +72 -2
- package/Server/Utils/AI/Sentinel/AlertInvestigationRunner.ts +244 -12
- package/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.ts +92 -19
- package/Server/Utils/AI/Sentinel/InvestigationQueue.ts +493 -0
- package/Server/Utils/AI/Sentinel/README.md +10 -0
- package/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.ts +88 -68
- package/Server/Utils/AI/Toolbox/Index.ts +2 -1
- package/Server/Utils/AI/Toolbox/MetricTools.ts +391 -0
- package/Server/Utils/LLM/LLMService.ts +21 -0
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +44 -0
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +170 -2
- package/Server/Utils/Monitor/IoTDeviceAbsenceSeries.ts +101 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +15 -3
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +1 -1
- package/Server/Utils/Monitor/MonitorIncident.ts +19 -3
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +195 -2
- package/Server/Utils/Monitor/MonitorResource.ts +77 -21
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -1
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +201 -0
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +215 -0
- package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +169 -0
- package/Tests/Server/Services/AIAgentTaskServiceClaim.test.ts +146 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +173 -0
- package/Tests/Server/Services/IncidentInternalNoteAnnouncement.test.ts +97 -0
- package/Tests/Server/Services/IoTDeviceService.test.ts +54 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +22 -0
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +194 -0
- package/Tests/Server/Utils/AI/BaselineAnomalyTool.test.ts +253 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +44 -0
- package/Tests/Server/Utils/AI/SentinelAlertGating.test.ts +360 -0
- package/Tests/Server/Utils/AI/SentinelInvestigationQueue.test.ts +295 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +59 -0
- package/Tests/Server/Utils/Monitor/IoTDeviceAbsenceSeries.test.ts +113 -0
- package/Tests/Server/Utils/Monitor/PerSeriesRecoveryResolution.test.ts +198 -0
- package/Tests/Types/AI/AIAgentTaskStatus.test.ts +86 -0
- package/Tests/Types/BaseDatabase/AggregationIntervalUtil.test.ts +127 -0
- package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.test.ts +152 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -1
- package/Tests/Types/Trace/TraceRecordingRuleDefinition.test.ts +308 -0
- package/Tests/UI/Components/Dropdown.test.tsx +17 -0
- package/Tests/UI/Components/EntityDropdown.test.tsx +130 -0
- package/Tests/UI/Components/Modal.test.tsx +144 -2
- package/Tests/UI/Components/TelemetrySearchBar.test.tsx +90 -0
- package/Tests/UI/Utils/Theme.test.ts +161 -0
- package/Tests/Utils/Monitor/LatencyMatrixUtil.test.ts +111 -0
- package/Types/AI/AIRunStatus.ts +9 -0
- package/Types/BaseDatabase/AggregateBy.ts +12 -0
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.ts +24 -0
- package/Types/Dashboard/DashboardTemplates.ts +9 -1
- package/Types/LlmLogStatus.ts +1 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/Monitor/HttpPhaseTimings.ts +16 -0
- package/Types/Monitor/IotAlertTemplates.ts +22 -3
- package/Types/Monitor/LatencyMatrix.ts +27 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +2 -2
- package/Types/Monitor/MonitorMetricType.ts +27 -0
- package/Types/Monitor/MonitorStep.ts +36 -11
- package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +55 -0
- package/Types/Monitor/MonitorStepSnmpMonitor.ts +8 -0
- package/Types/Monitor/MonitorType.ts +14 -9
- package/Types/Monitor/PingMonitor/PingMonitorResponse.ts +20 -0
- package/Types/Monitor/SnmpMonitor/LldpNeighbor.ts +12 -0
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +116 -0
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +29 -0
- package/Types/Monitor/SnmpMonitor/SnmpInterface.ts +31 -0
- package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +24 -0
- package/Types/Monitor/SnmpMonitor/SnmpTrap.ts +20 -0
- package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +173 -0
- package/Types/Permission.ts +314 -0
- package/Types/Probe/ProbeMonitorResponse.ts +22 -0
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +8 -5
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +4 -1
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +6 -3
- package/UI/Components/CodeBlock/CodeBlock.tsx +2 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
- package/UI/Components/Divider/Divider.tsx +1 -1
- package/UI/Components/Dropdown/Dropdown.tsx +13 -4
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +110 -2
- package/UI/Components/ErrorBoundary.tsx +2 -1
- package/UI/Components/EventItem/EventItem.tsx +2 -2
- package/UI/Components/GanttChart/Bar/Index.tsx +1 -1
- package/UI/Components/Graphs/UptimeBarTooltip.tsx +30 -23
- package/UI/Components/Header/Header.tsx +7 -0
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +2 -0
- package/UI/Components/Icon/Icon.tsx +8 -6
- package/UI/Components/Label/Label.tsx +2 -2
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +22 -10
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +9 -3
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +8 -8
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +44 -20
- package/UI/Components/Modal/ConfirmModal.tsx +1 -1
- package/UI/Components/Modal/Modal.tsx +213 -121
- package/UI/Components/Modal/ModalFooter.tsx +33 -22
- package/UI/Components/ModelTable/TableView.tsx +1 -1
- package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +20 -12
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +2 -2
- package/UI/Components/Pill/Pill.tsx +21 -13
- package/UI/Components/StatusBubble/StatusBubble.tsx +3 -3
- package/UI/Components/Tabs/Tabs.tsx +10 -1
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +7 -1
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +9 -3
- package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +62 -4
- package/UI/Components/Workflow/Component.tsx +53 -33
- package/UI/Components/Workflow/ComponentPortViewer.tsx +6 -6
- package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +8 -8
- package/UI/Components/Workflow/ComponentsModal.tsx +16 -9
- package/UI/Components/Workflow/Workflow.tsx +13 -11
- package/UI/Utils/Navigation.ts +10 -1
- package/UI/Utils/Theme.ts +140 -0
- package/Utils/Dashboard/Components/DashboardLogChartComponent.ts +99 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/Monitor/LatencyMatrixUtil.ts +162 -0
- package/Utils/Monitor/MonitorMetricType.ts +141 -3
- package/Utils/Monitor/NetworkTopologyUtil.ts +159 -0
- package/Utils/Telemetry/EntityRelationship.ts +11 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +52 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertSeverity.js +6 -0
- package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js +6 -0
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTDeviceCredential.js +493 -0
- package/build/dist/Models/DatabaseModels/IoTDeviceCredential.js.map +1 -0
- package/build/dist/Models/DatabaseModels/LlmLog.js +58 -0
- package/build/dist/Models/DatabaseModels/LlmLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LlmProvider.js +33 -0
- package/build/dist/Models/DatabaseModels/LlmProvider.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +1426 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +738 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerTeam.js +503 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerUser.js +502 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkInterface.js +589 -0
- package/build/dist/Models/DatabaseModels/NetworkInterface.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Project.js +147 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js +57 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskAPI.js +8 -23
- package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +95 -55
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +5 -0
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +10 -0
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +5 -0
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/LlmProviderAPI.js +5 -7
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +5 -0
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783650000000-AddAdditionalParamsToLlmProvider.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783650000000-AddAdditionalParamsToLlmProvider.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783695782697-AddCacheTokenColumnsToLlmLog.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783695782697-AddCacheTokenColumnsToLlmLog.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783701585317-AddAlertInvestigationGating.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783701585317-AddAlertInvestigationGating.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783702431535-AddAiDailyAutonomousTokenLimitToProject.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783702431535-AddAiDailyAutonomousTokenLimitToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783720000000-AddNetworkDeviceTables.js +51 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783720000000-AddNetworkDeviceTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783721121260-AddAttemptCountToAIRun.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783721121260-AddAttemptCountToAIRun.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783730000000-AddNetworkDeviceOwnersAndRules.js +101 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783730000000-AddNetworkDeviceOwnersAndRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783740000000-AddNetworkDeviceDiscoveryScan.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783740000000-AddNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783750000000-AddLldpNeighborsToNetworkDevice.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783750000000-AddLldpNeighborsToNetworkDevice.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783760576655-AddInvestigationTuningToProject.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783760576655-AddInvestigationTuningToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783762505482-AddTelemetryEntityRelationshipMetrics.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783762505482-AddTelemetryEntityRelationshipMetrics.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783780000000-AddIoTDeviceCredentialTable.js +38 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783780000000-AddIoTDeviceCredentialTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783790000000-AddSnmpV3AuthColumnsToNetworkDevice.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783790000000-AddSnmpV3AuthColumnsToNetworkDevice.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIAgentTaskService.js +59 -0
- package/build/dist/Server/Services/AIAgentTaskService.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +33 -0
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +82 -9
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +19 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +14 -25
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +14 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceCredentialService.js +321 -0
- package/build/dist/Server/Services/IoTDeviceCredentialService.js.map +1 -0
- package/build/dist/Server/Services/IoTDeviceService.js +49 -15
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/LlmLogService.js +29 -0
- package/build/dist/Server/Services/LlmLogService.js.map +1 -1
- package/build/dist/Server/Services/LlmProviderService.js +3 -0
- package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +21 -7
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +449 -7
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +2 -1
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +9 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +166 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleService.js +13 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +186 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerUserService.js +9 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceService.js +52 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -0
- package/build/dist/Server/Services/NetworkInterfaceService.js +9 -0
- package/build/dist/Server/Services/NetworkInterfaceService.js.map +1 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js +22 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +64 -2
- package/build/dist/Server/Services/TelemetryEntityService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js +189 -9
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js +84 -17
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Sentinel/InvestigationQueue.js +428 -0
- package/build/dist/Server/Utils/AI/Sentinel/InvestigationQueue.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js +63 -47
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +2 -1
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/MetricTools.js +300 -0
- package/build/dist/Server/Utils/AI/Toolbox/MetricTools.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +16 -0
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +29 -0
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +130 -2
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/IoTDeviceAbsenceSeries.js +81 -0
- package/build/dist/Server/Utils/Monitor/IoTDeviceAbsenceSeries.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +18 -7
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +25 -10
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +155 -5
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +76 -30
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +147 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +167 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +93 -0
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -0
- package/build/dist/Types/AI/AIRunStatus.js +9 -0
- package/build/dist/Types/AI/AIRunStatus.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +9 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/LlmLogStatus.js +1 -0
- package/build/dist/Types/LlmLogStatus.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +9 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/HttpPhaseTimings.js +2 -0
- package/build/dist/Types/Monitor/HttpPhaseTimings.js.map +1 -0
- package/build/dist/Types/Monitor/IotAlertTemplates.js +7 -7
- package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/LatencyMatrix.js +2 -0
- package/build/dist/Types/Monitor/LatencyMatrix.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +2 -2
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +24 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +22 -9
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +36 -0
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js +3 -0
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +14 -9
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js +2 -0
- package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/LldpNeighbor.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/LldpNeighbor.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +89 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkTopology.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkTopology.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpInterface.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpInterface.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpTrap.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpTrap.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +137 -0
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -0
- package/build/dist/Types/Permission.js +280 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +7 -4
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +4 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +6 -3
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +3 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/Divider/Divider.js +1 -1
- package/build/dist/UI/Components/Divider/Divider.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +10 -4
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +76 -3
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +2 -1
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
- package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js +1 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +1 -1
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +29 -23
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
- package/build/dist/UI/Components/Header/Header.js +1 -0
- package/build/dist/UI/Components/Header/Header.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +8 -6
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Label/Label.js +2 -2
- package/build/dist/UI/Components/Label/Label.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +20 -8
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +8 -2
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +8 -8
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +40 -20
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +109 -51
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +13 -10
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +17 -12
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +2 -2
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/Pill/Pill.js +12 -13
- package/build/dist/UI/Components/Pill/Pill.js.map +1 -1
- package/build/dist/UI/Components/StatusBubble/StatusBubble.js +3 -3
- package/build/dist/UI/Components/StatusBubble/StatusBubble.js.map +1 -1
- package/build/dist/UI/Components/Tabs/Tabs.js +3 -1
- package/build/dist/UI/Components/Tabs/Tabs.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -2
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +36 -6
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Component.js +43 -33
- package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentPortViewer.js +6 -6
- package/build/dist/UI/Components/Workflow/ComponentPortViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +8 -8
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +15 -9
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +13 -11
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +11 -1
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/Theme.js +106 -0
- package/build/dist/UI/Utils/Theme.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js +89 -0
- package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Monitor/LatencyMatrixUtil.js +89 -0
- package/build/dist/Utils/Monitor/LatencyMatrixUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js +138 -4
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +112 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,10 +5,8 @@ import {
|
|
|
5
5
|
AIChatCitation,
|
|
6
6
|
AIRunEventResultSummary,
|
|
7
7
|
} from "../../../../Types/AI/AIChatTypes";
|
|
8
|
-
import AIRunType from "../../../../Types/AI/AIRunType";
|
|
9
8
|
import AIRunStatus from "../../../../Types/AI/AIRunStatus";
|
|
10
9
|
import AIRunEventType from "../../../../Types/AI/AIRunEventType";
|
|
11
|
-
import AIRun from "../../../../Models/DatabaseModels/AIRun";
|
|
12
10
|
import AIRunEvent from "../../../../Models/DatabaseModels/AIRunEvent";
|
|
13
11
|
import Project from "../../../../Models/DatabaseModels/Project";
|
|
14
12
|
import LlmProvider from "../../../../Models/DatabaseModels/LlmProvider";
|
|
@@ -16,6 +14,7 @@ import AIRunService from "../../../Services/AIRunService";
|
|
|
16
14
|
import AIRunEventService from "../../../Services/AIRunEventService";
|
|
17
15
|
import ProjectService from "../../../Services/ProjectService";
|
|
18
16
|
import LlmProviderService from "../../../Services/LlmProviderService";
|
|
17
|
+
import SentinelInvestigationQueue from "./InvestigationQueue";
|
|
19
18
|
import ObservabilityAssistant, {
|
|
20
19
|
ObservabilityAssistantResult,
|
|
21
20
|
ObservabilityAssistantStep,
|
|
@@ -53,6 +52,14 @@ const MAX_OUTPUT_TOKENS: number = 2000;
|
|
|
53
52
|
*/
|
|
54
53
|
const INCONCLUSIVE_RE: RegExp = /inconclusive[^.\n]*insufficient signal/i;
|
|
55
54
|
|
|
55
|
+
/*
|
|
56
|
+
* Failures a retry cannot fix within the run's usefulness window: missing/
|
|
57
|
+
* broken provider configuration and budget exhaustion (both messages minted
|
|
58
|
+
* by our own gating in AIService/LLMService, so they are stable to match).
|
|
59
|
+
*/
|
|
60
|
+
const PERMANENT_FAILURE_RE: RegExp =
|
|
61
|
+
/no llm provider configured|llm provider type is not configured|token budget exhausted/i;
|
|
62
|
+
|
|
56
63
|
// Maps a live agent step to the AIRunEvent type persisted for the glass-box trail.
|
|
57
64
|
const STEP_EVENT_TYPE: Record<ObservabilityAssistantStepType, AIRunEventType> =
|
|
58
65
|
{
|
|
@@ -67,7 +74,7 @@ const INVESTIGATION_PERSONA: string = `You are "Sentinel", OneUptime's autonomou
|
|
|
67
74
|
|
|
68
75
|
Investigate like a senior on-call engineer:
|
|
69
76
|
- Start from the affected monitors/services named in the signal.
|
|
70
|
-
- Use your read tools to inspect the telemetry AROUND the signal's creation time: recent exceptions and their trends, error/latency metrics versus their normal range, failing traces, relevant logs, and recent changes / deploys.
|
|
77
|
+
- Use your read tools to inspect the telemetry AROUND the signal's creation time: recent exceptions and their trends, error/latency metrics versus their normal range (use baseline_anomaly to judge a metric against its learned hour-of-week baseline quantitatively instead of eyeballing), failing traces, relevant logs, and recent changes / deploys.
|
|
71
78
|
- Form the single most likely root-cause hypothesis. If the evidence is inconclusive, say so plainly and list what you checked — do NOT guess a cause the data does not support.
|
|
72
79
|
- If the context lists past resolved incidents, check whether this is a RECURRENCE. If the current signal matches one, say so explicitly, reference that incident number, and note how it was resolved before — but still verify against the current telemetry.
|
|
73
80
|
|
|
@@ -83,17 +90,10 @@ Keep it tight and skimmable. You are read-only: never claim to have changed anyt
|
|
|
83
90
|
export type SentinelSubjectType = "Incident" | "Alert";
|
|
84
91
|
|
|
85
92
|
export interface InvestigationRequest {
|
|
86
|
-
projectId: ObjectID;
|
|
87
93
|
// Label recorded on LlmLog, e.g. "Sentinel Incident Investigation".
|
|
88
94
|
feature: string;
|
|
89
95
|
// A compact markdown summary of the subject that seeds the investigation.
|
|
90
96
|
contextSummary: string;
|
|
91
|
-
/*
|
|
92
|
-
* The subject that triggered this run — links the AIRun so the live panel can
|
|
93
|
-
* find "the investigation for this incident/alert". Exactly one is set.
|
|
94
|
-
*/
|
|
95
|
-
subjectIncidentId?: ObjectID | undefined;
|
|
96
|
-
subjectAlertId?: ObjectID | undefined;
|
|
97
97
|
/*
|
|
98
98
|
* Called with the finished, branded, cited analysis so the caller can post it
|
|
99
99
|
* to the subject's timeline. `isConfident` is false when Sentinel reported it
|
|
@@ -160,44 +160,38 @@ export default class SentinelInvestigationEngine {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
/*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
163
|
+
* Execute an already-CLAIMED (Running) investigation run end-to-end.
|
|
164
|
+
* Called by SentinelInvestigationQueue after a successful CAS claim —
|
|
165
|
+
* cap/budget gating and run creation live in the queue now. Never throws;
|
|
166
|
+
* failures are handed to the queue's retry policy (failOrRequeue).
|
|
165
167
|
*/
|
|
166
168
|
@CaptureSpan()
|
|
167
|
-
public static async
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
run.projectId = projectId;
|
|
175
|
-
run.runType = AIRunType.Investigation;
|
|
176
|
-
run.status = AIRunStatus.Running;
|
|
177
|
-
run.startedAt = OneUptimeDate.getCurrentDate();
|
|
178
|
-
run.lastHeartbeatAt = OneUptimeDate.getCurrentDate();
|
|
179
|
-
|
|
180
|
-
if (request.subjectIncidentId) {
|
|
181
|
-
run.triggeredByIncidentId = request.subjectIncidentId;
|
|
182
|
-
}
|
|
183
|
-
if (request.subjectAlertId) {
|
|
184
|
-
run.triggeredByAlertId = request.subjectAlertId;
|
|
185
|
-
}
|
|
169
|
+
public static async executeRun(data: {
|
|
170
|
+
aiRunId: ObjectID;
|
|
171
|
+
projectId: ObjectID;
|
|
172
|
+
attemptCount: number;
|
|
173
|
+
request: InvestigationRequest;
|
|
174
|
+
}): Promise<void> {
|
|
175
|
+
const { aiRunId, projectId, request } = data;
|
|
186
176
|
|
|
187
|
-
|
|
177
|
+
/*
|
|
178
|
+
* Retried runs already have events from earlier attempts; continue the
|
|
179
|
+
* sequence so the glass-box trail stays ordered and shows every attempt.
|
|
180
|
+
*/
|
|
181
|
+
let sequence: number = 0;
|
|
188
182
|
try {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
183
|
+
sequence = (
|
|
184
|
+
await AIRunEventService.countBy({
|
|
185
|
+
query: { aiRunId },
|
|
186
|
+
props: { isRoot: true },
|
|
187
|
+
})
|
|
188
|
+
).toNumber();
|
|
193
189
|
} catch (error) {
|
|
194
|
-
logger.error(
|
|
195
|
-
|
|
190
|
+
logger.error(
|
|
191
|
+
`Sentinel: failed to read event count for run ${aiRunId.toString()}; starting sequence at 0: ${error}`,
|
|
192
|
+
);
|
|
196
193
|
}
|
|
197
194
|
|
|
198
|
-
const aiRunId: ObjectID = createdRun.id!;
|
|
199
|
-
let sequence: number = 0;
|
|
200
|
-
|
|
201
195
|
await this.emitEvent({
|
|
202
196
|
projectId,
|
|
203
197
|
aiRunId,
|
|
@@ -234,10 +228,12 @@ export default class SentinelInvestigationEngine {
|
|
|
234
228
|
citationId: step.citationId,
|
|
235
229
|
});
|
|
236
230
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
231
|
+
/*
|
|
232
|
+
* Keep the run visibly alive for the stale-run sweeper + live UI on
|
|
233
|
+
* EVERY step — a slow self-hosted LLM call can approach the sweeper's
|
|
234
|
+
* timeout, so the heartbeat must be as frequent as we can make it.
|
|
235
|
+
*/
|
|
236
|
+
await this.touchHeartbeat(aiRunId);
|
|
241
237
|
};
|
|
242
238
|
|
|
243
239
|
try {
|
|
@@ -256,18 +252,35 @@ export default class SentinelInvestigationEngine {
|
|
|
256
252
|
onStep,
|
|
257
253
|
});
|
|
258
254
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
255
|
+
/*
|
|
256
|
+
* Atomic Running -> Completed. If we did NOT win this transition,
|
|
257
|
+
* another actor moved the run while we executed — most likely the
|
|
258
|
+
* stale sweeper falsely requeued it (slow LLM call outlasting the
|
|
259
|
+
* heartbeat window) and a second attempt is or will be running. In
|
|
260
|
+
* that case DO NOT post the analysis: the winning attempt will, and
|
|
261
|
+
* posting here would duplicate the RCA in the feed and workspace.
|
|
262
|
+
*/
|
|
263
|
+
const completedCount: number = await AIRunService.attemptStatusTransition(
|
|
264
|
+
{
|
|
265
|
+
aiRunId,
|
|
266
|
+
fromStatus: AIRunStatus.Running,
|
|
267
|
+
set: {
|
|
268
|
+
status: AIRunStatus.Completed,
|
|
269
|
+
completedAt: OneUptimeDate.getCurrentDate(),
|
|
270
|
+
lastHeartbeatAt: OneUptimeDate.getCurrentDate(),
|
|
271
|
+
llmCallCount: result.llmCallCount,
|
|
272
|
+
toolCallCount: result.toolCallCount,
|
|
273
|
+
totalTokens: result.totalTokens,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
if (completedCount === 0) {
|
|
279
|
+
logger.warn(
|
|
280
|
+
`Sentinel: run ${aiRunId.toString()} finished but was no longer Running (likely requeued as stale mid-flight); skipping postAnalysis to avoid a duplicate RCA.`,
|
|
281
|
+
);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
271
284
|
|
|
272
285
|
await this.emitEvent({
|
|
273
286
|
projectId,
|
|
@@ -300,16 +313,6 @@ export default class SentinelInvestigationEngine {
|
|
|
300
313
|
const message: string =
|
|
301
314
|
error instanceof Error ? error.message : String(error);
|
|
302
315
|
|
|
303
|
-
await AIRunService.updateOneBy({
|
|
304
|
-
query: { _id: aiRunId.toString(), status: AIRunStatus.Running },
|
|
305
|
-
data: {
|
|
306
|
-
status: AIRunStatus.Error,
|
|
307
|
-
completedAt: OneUptimeDate.getCurrentDate(),
|
|
308
|
-
errorMessage: message.substring(0, 480),
|
|
309
|
-
} as never,
|
|
310
|
-
props: { isRoot: true },
|
|
311
|
-
});
|
|
312
|
-
|
|
313
316
|
await this.emitEvent({
|
|
314
317
|
projectId,
|
|
315
318
|
aiRunId,
|
|
@@ -317,8 +320,25 @@ export default class SentinelInvestigationEngine {
|
|
|
317
320
|
eventType: AIRunEventType.RunFailed,
|
|
318
321
|
});
|
|
319
322
|
|
|
323
|
+
/*
|
|
324
|
+
* Hand the failure to the queue's retry policy: transient errors
|
|
325
|
+
* requeue while attempts remain; permanent ones finalize as Error
|
|
326
|
+
* since retrying cannot help. Classification is by message, NOT by
|
|
327
|
+
* exception type: LLMService wraps transient provider failures (429s,
|
|
328
|
+
* 5xx, timeouts) in BadDataException too, so type-based classification
|
|
329
|
+
* would wrongly make the exact failures retries exist for permanent.
|
|
330
|
+
* Only configuration/budget gating — which a retry cannot change
|
|
331
|
+
* within the run's usefulness window — counts as permanent.
|
|
332
|
+
*/
|
|
333
|
+
await SentinelInvestigationQueue.failOrRequeue({
|
|
334
|
+
aiRunId,
|
|
335
|
+
attemptCount: data.attemptCount,
|
|
336
|
+
errorMessage: message,
|
|
337
|
+
isPermanent: PERMANENT_FAILURE_RE.test(message),
|
|
338
|
+
});
|
|
339
|
+
|
|
320
340
|
logger.error(
|
|
321
|
-
`Sentinel: investigation failed (run ${aiRunId.toString()}): ${message}`,
|
|
341
|
+
`Sentinel: investigation attempt ${data.attemptCount} failed (run ${aiRunId.toString()}): ${message}`,
|
|
322
342
|
);
|
|
323
343
|
}
|
|
324
344
|
}
|
|
@@ -19,7 +19,7 @@ import { QueryMonitorsTool } from "./MonitorTools";
|
|
|
19
19
|
import { TopExceptionsTool } from "./ExceptionTools";
|
|
20
20
|
import { LogHistogramTool, SearchLogsTool } from "./LogTools";
|
|
21
21
|
import { RecentChangesTool } from "./RecentChangesTools";
|
|
22
|
-
import { QueryMetricsTool } from "./MetricTools";
|
|
22
|
+
import { BaselineAnomalyTool, QueryMetricsTool } from "./MetricTools";
|
|
23
23
|
import { GetTraceTool, QueryTracesTool } from "./TraceTools";
|
|
24
24
|
import { LookupContextTool } from "./ContextTools";
|
|
25
25
|
import {
|
|
@@ -67,6 +67,7 @@ export default class AIToolbox {
|
|
|
67
67
|
SearchLogsTool,
|
|
68
68
|
LogHistogramTool,
|
|
69
69
|
QueryMetricsTool,
|
|
70
|
+
BaselineAnomalyTool,
|
|
70
71
|
QueryTracesTool,
|
|
71
72
|
GetTraceTool,
|
|
72
73
|
RecentChangesTool,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import Metric from "../../../../Models/AnalyticsModels/Metric";
|
|
2
2
|
import AggregationType from "../../../../Types/BaseDatabase/AggregationType";
|
|
3
|
+
import DatabaseRequestType from "../../../Types/BaseDatabase/DatabaseRequestType";
|
|
4
|
+
import ModelPermission from "../../../Types/AnalyticsDatabase/ModelPermission";
|
|
3
5
|
import InBetween from "../../../../Types/BaseDatabase/InBetween";
|
|
4
6
|
import { JSONObject } from "../../../../Types/JSON";
|
|
5
7
|
import ObjectID from "../../../../Types/ObjectID";
|
|
@@ -11,6 +13,11 @@ import {
|
|
|
11
13
|
} from "../../../../Types/AI/AIChatTypes";
|
|
12
14
|
import AggregateBy from "../../../Types/AnalyticsDatabase/AggregateBy";
|
|
13
15
|
import MetricService from "../../../Services/MetricService";
|
|
16
|
+
import MetricBaselineService, {
|
|
17
|
+
BandPoint,
|
|
18
|
+
BaselineSummary,
|
|
19
|
+
MetricBaselineService as MetricBaselineServiceClass,
|
|
20
|
+
} from "../../../Services/MetricBaselineService";
|
|
14
21
|
import AggregatedResult from "../../../../Types/BaseDatabase/AggregatedResult";
|
|
15
22
|
import AggregatedModel from "../../../../Types/BaseDatabase/AggregatedModel";
|
|
16
23
|
import ToolResultSerializer, { SerializedResult } from "./Serializer";
|
|
@@ -177,3 +184,387 @@ export const QueryMetricsTool: ObservabilityTool = {
|
|
|
177
184
|
};
|
|
178
185
|
},
|
|
179
186
|
};
|
|
187
|
+
|
|
188
|
+
// The recent window whose average is judged against the baseline band.
|
|
189
|
+
const BASELINE_CURRENT_WINDOW_MINUTES: number = 15;
|
|
190
|
+
|
|
191
|
+
// Lookback rendered on the expected-range band chart.
|
|
192
|
+
const BASELINE_CHART_HOURS: number = 6;
|
|
193
|
+
|
|
194
|
+
export const BaselineAnomalyTool: ObservabilityTool = {
|
|
195
|
+
name: "baseline_anomaly",
|
|
196
|
+
description:
|
|
197
|
+
"Judge whether a metric is currently anomalous versus its learned hour-of-week baseline (rolling-window mean ± sigma band, the same math the anomaly monitors use). Answers 'is this value NORMAL for this metric at this time of week?' quantitatively — use it instead of eyeballing query_metrics output. Requires the exact metric name — discover names via lookup_context.",
|
|
198
|
+
inputSchema: {
|
|
199
|
+
type: "object",
|
|
200
|
+
properties: {
|
|
201
|
+
metricName: {
|
|
202
|
+
type: "string",
|
|
203
|
+
description: "Exact metric name (required).",
|
|
204
|
+
},
|
|
205
|
+
entityId: {
|
|
206
|
+
type: "string",
|
|
207
|
+
description:
|
|
208
|
+
"Only data points from this service/host/monitor (its OneUptime ID). When omitted, the baseline spans every entity that ingests the metric.",
|
|
209
|
+
},
|
|
210
|
+
atTime: {
|
|
211
|
+
type: "string",
|
|
212
|
+
description:
|
|
213
|
+
"Evaluate at this ISO 8601 timestamp (e.g. the signal's creation time). Defaults to now.",
|
|
214
|
+
},
|
|
215
|
+
sensitivity: {
|
|
216
|
+
type: "string",
|
|
217
|
+
enum: ["Low", "Medium", "High"],
|
|
218
|
+
description:
|
|
219
|
+
"Band width: Low = 4 sigma (fewest anomalies), Medium = 3 sigma (default), High = 2 sigma.",
|
|
220
|
+
},
|
|
221
|
+
windowDays: {
|
|
222
|
+
type: "number",
|
|
223
|
+
enum: [...MetricBaselineServiceClass.WINDOW_DAYS_OPTIONS],
|
|
224
|
+
description: "Rolling baseline window in days (default 14).",
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
required: ["metricName"],
|
|
228
|
+
},
|
|
229
|
+
requiredPermissions: METRIC_READ_PERMISSIONS,
|
|
230
|
+
execute: async (
|
|
231
|
+
args: JSONObject,
|
|
232
|
+
ctx: ToolContext,
|
|
233
|
+
): Promise<ToolExecutionResult> => {
|
|
234
|
+
const metricName: string | undefined = ToolArgs.getString(
|
|
235
|
+
args,
|
|
236
|
+
"metricName",
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
if (!metricName) {
|
|
240
|
+
throw new BadDataException(
|
|
241
|
+
"metricName is required. Use lookup_context with type 'metricNames' to discover metric names.",
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const entityId: ObjectID | undefined = ToolArgs.getObjectID(
|
|
246
|
+
args,
|
|
247
|
+
"entityId",
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
let atTime: Date = OneUptimeDate.getCurrentDate();
|
|
251
|
+
const atTimeString: string | undefined = ToolArgs.getString(args, "atTime");
|
|
252
|
+
if (atTimeString) {
|
|
253
|
+
const parsed: Date = new Date(atTimeString);
|
|
254
|
+
if (isNaN(parsed.getTime())) {
|
|
255
|
+
throw new BadDataException(
|
|
256
|
+
`atTime "${atTimeString}" is not a valid ISO 8601 timestamp (e.g. 2024-01-31T14:00:00Z).`,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
atTime = parsed;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const sensitivityString: string =
|
|
263
|
+
ToolArgs.getString(args, "sensitivity") || "Medium";
|
|
264
|
+
if (!["Low", "Medium", "High"].includes(sensitivityString)) {
|
|
265
|
+
throw new BadDataException(
|
|
266
|
+
`Invalid sensitivity: ${sensitivityString}. Must be Low, Medium or High.`,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
const sensitivity: "Low" | "Medium" | "High" = sensitivityString as
|
|
270
|
+
| "Low"
|
|
271
|
+
| "Medium"
|
|
272
|
+
| "High";
|
|
273
|
+
|
|
274
|
+
const requestedWindowDays: number = ToolArgs.getNumber(args, "windowDays", {
|
|
275
|
+
defaultValue: MetricBaselineServiceClass.DEFAULT_WINDOW_DAYS,
|
|
276
|
+
min: MetricBaselineServiceClass.DEFAULT_WINDOW_DAYS,
|
|
277
|
+
max: MetricBaselineServiceClass.MAX_WINDOW_DAYS,
|
|
278
|
+
});
|
|
279
|
+
// Snap to the supported window options (they match the table's TTL).
|
|
280
|
+
const windowDays: number =
|
|
281
|
+
[...MetricBaselineServiceClass.WINDOW_DAYS_OPTIONS]
|
|
282
|
+
.reverse()
|
|
283
|
+
.find((option: number) => {
|
|
284
|
+
return option <= requestedWindowDays;
|
|
285
|
+
}) || MetricBaselineServiceClass.DEFAULT_WINDOW_DAYS;
|
|
286
|
+
|
|
287
|
+
/*
|
|
288
|
+
* The baseline queries are raw ClickHouse SQL scoped only by projectId —
|
|
289
|
+
* they skip the model layer's owned-scope filter. A label/owned-restricted
|
|
290
|
+
* user must therefore be pinned to one of THEIR services: project-wide
|
|
291
|
+
* baselines (no entityId) and other services' baselines are refused, the
|
|
292
|
+
* same posture as the other raw-SQL tools (see LogTools/TraceTools).
|
|
293
|
+
*/
|
|
294
|
+
const accessibleServiceIds: Array<ObjectID> | null =
|
|
295
|
+
await ModelPermission.getAccessibleServiceIdsForAnalyticsModel(
|
|
296
|
+
Metric,
|
|
297
|
+
ctx.props,
|
|
298
|
+
DatabaseRequestType.Read,
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
if (accessibleServiceIds !== null) {
|
|
302
|
+
const isEntityAccessible: boolean = Boolean(
|
|
303
|
+
entityId &&
|
|
304
|
+
accessibleServiceIds.some((id: ObjectID) => {
|
|
305
|
+
return id.toString() === entityId.toString();
|
|
306
|
+
}),
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
if (!isEntityAccessible) {
|
|
310
|
+
throw new BadDataException(
|
|
311
|
+
"Your telemetry access is scoped to specific services, so a project-wide baseline is not available. Pass entityId set to the OneUptime ID of a service you can read (discover them via lookup_context).",
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const hourOfWeek: number =
|
|
317
|
+
MetricBaselineServiceClass.computeHourOfWeek(atTime);
|
|
318
|
+
|
|
319
|
+
const baseline: BaselineSummary | null =
|
|
320
|
+
await MetricBaselineService.getBaseline({
|
|
321
|
+
projectId: ctx.projectId,
|
|
322
|
+
metricName,
|
|
323
|
+
primaryEntityId: entityId,
|
|
324
|
+
hourOfWeek,
|
|
325
|
+
windowDays,
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
const citationLabel: string = `baseline_anomaly(${metricName}${
|
|
329
|
+
entityId ? ` · ${entityId.toString()}` : ""
|
|
330
|
+
}) @ ${atTime.toISOString()}`;
|
|
331
|
+
|
|
332
|
+
/*
|
|
333
|
+
* Cold start: no baseline (or too few samples) for this hour-of-week cell.
|
|
334
|
+
* Report it explicitly — a missing baseline must read as "cannot judge",
|
|
335
|
+
* never as "not anomalous".
|
|
336
|
+
*/
|
|
337
|
+
if (!baseline || !baseline.isReliable) {
|
|
338
|
+
const coverage: { totalSamples: number; oldestDay: Date | null } =
|
|
339
|
+
await MetricBaselineService.getCoverage({
|
|
340
|
+
projectId: ctx.projectId,
|
|
341
|
+
metricName,
|
|
342
|
+
primaryEntityId: entityId,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
const verdictRow: JSONObject = {
|
|
346
|
+
verdict: "insufficient baseline data",
|
|
347
|
+
detail: `The metric has ${
|
|
348
|
+
baseline
|
|
349
|
+
? `only ${baseline.sampleCount} sample(s)`
|
|
350
|
+
: "no baseline data"
|
|
351
|
+
} for this hour of week (needs at least ${MetricBaselineServiceClass.DEFAULT_MIN_SAMPLES}). Baseline coverage overall: ${coverage.totalSamples} total sample(s)${
|
|
352
|
+
coverage.oldestDay
|
|
353
|
+
? `, oldest day ${OneUptimeDate.getDateAsFormattedString(coverage.oldestDay)}`
|
|
354
|
+
: ""
|
|
355
|
+
}. Do NOT treat this as "not anomalous" — the baseline simply cannot judge yet.`,
|
|
356
|
+
metricName,
|
|
357
|
+
entityId: entityId?.toString(),
|
|
358
|
+
evaluatedAt: atTime.toISOString(),
|
|
359
|
+
hourOfWeek,
|
|
360
|
+
windowDays,
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const serializedColdStart: SerializedResult =
|
|
364
|
+
ToolResultSerializer.serializeRows([verdictRow]);
|
|
365
|
+
|
|
366
|
+
return {
|
|
367
|
+
dataForLlm: serializedColdStart.text,
|
|
368
|
+
rowCount: serializedColdStart.rowCount,
|
|
369
|
+
citationLabel,
|
|
370
|
+
citationTarget: { type: AIChatCitationTargetType.Metrics },
|
|
371
|
+
redactionCount: serializedColdStart.redactionCount,
|
|
372
|
+
isTruncated: serializedColdStart.isTruncated,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Current value: average over the recent window ending at atTime.
|
|
377
|
+
const currentWindowStart: Date = OneUptimeDate.addRemoveMinutes(
|
|
378
|
+
atTime,
|
|
379
|
+
-1 * BASELINE_CURRENT_WINDOW_MINUTES,
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const currentQuery: JSONObject = {
|
|
383
|
+
name: metricName,
|
|
384
|
+
time: new InBetween(currentWindowStart, atTime),
|
|
385
|
+
};
|
|
386
|
+
if (entityId) {
|
|
387
|
+
currentQuery["primaryEntityId"] = entityId;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const currentResult: AggregatedResult = await MetricService.aggregateBy({
|
|
391
|
+
aggregateColumnName: "value",
|
|
392
|
+
aggregationType: AggregationType.Avg,
|
|
393
|
+
aggregationTimestampColumnName: "time",
|
|
394
|
+
startTimestamp: currentWindowStart,
|
|
395
|
+
endTimestamp: atTime,
|
|
396
|
+
query: currentQuery as never,
|
|
397
|
+
limit: 200,
|
|
398
|
+
skip: 0,
|
|
399
|
+
props: ctx.props,
|
|
400
|
+
} as AggregateBy<Metric>);
|
|
401
|
+
|
|
402
|
+
const currentValues: Array<number> = currentResult.data
|
|
403
|
+
.map((item: AggregatedModel) => {
|
|
404
|
+
return item.value;
|
|
405
|
+
})
|
|
406
|
+
.filter((value: unknown): value is number => {
|
|
407
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
const sigma: number =
|
|
411
|
+
MetricBaselineServiceClass.sigmaForSensitivity(sensitivity);
|
|
412
|
+
const expectedLow: number = baseline.mean - sigma * baseline.stddev;
|
|
413
|
+
const expectedHigh: number = baseline.mean + sigma * baseline.stddev;
|
|
414
|
+
|
|
415
|
+
let verdict: string;
|
|
416
|
+
let currentValue: number | null = null;
|
|
417
|
+
let zScore: number | null = null;
|
|
418
|
+
|
|
419
|
+
if (currentValues.length === 0) {
|
|
420
|
+
verdict = `no data points in the last ${BASELINE_CURRENT_WINDOW_MINUTES} minutes — the metric may have STOPPED reporting, which can itself be the anomaly`;
|
|
421
|
+
} else {
|
|
422
|
+
currentValue =
|
|
423
|
+
currentValues.reduce((sum: number, value: number) => {
|
|
424
|
+
return sum + value;
|
|
425
|
+
}, 0) / currentValues.length;
|
|
426
|
+
|
|
427
|
+
if (baseline.stddev <= 0) {
|
|
428
|
+
/*
|
|
429
|
+
* Zero-variance baseline: the band collapses to a point and
|
|
430
|
+
* floating-point noise alone would flag every sample. The anomaly
|
|
431
|
+
* monitors refuse to classify here (MetricMonitorCriteria) — match
|
|
432
|
+
* them rather than emitting guaranteed-false ANOMALOUS verdicts.
|
|
433
|
+
*/
|
|
434
|
+
verdict = `cannot judge — the baseline has zero variance (the metric has been constant at ${baseline.mean}), so any band would flag every sample; compare the current value to the baseline mean directly instead`;
|
|
435
|
+
} else {
|
|
436
|
+
zScore = (currentValue - baseline.mean) / baseline.stddev;
|
|
437
|
+
|
|
438
|
+
if (currentValue > expectedHigh) {
|
|
439
|
+
verdict = `ANOMALOUS — above the expected range for this hour of week`;
|
|
440
|
+
} else if (currentValue < expectedLow) {
|
|
441
|
+
verdict = `ANOMALOUS — below the expected range for this hour of week`;
|
|
442
|
+
} else {
|
|
443
|
+
verdict = `normal — within the expected range for this hour of week`;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const row: JSONObject = {
|
|
449
|
+
verdict,
|
|
450
|
+
metricName,
|
|
451
|
+
entityId: entityId?.toString(),
|
|
452
|
+
evaluatedAt: atTime.toISOString(),
|
|
453
|
+
currentValue:
|
|
454
|
+
currentValue !== null
|
|
455
|
+
? `${currentValue} (avg over the last ${BASELINE_CURRENT_WINDOW_MINUTES} min)`
|
|
456
|
+
: null,
|
|
457
|
+
expectedRange: `${expectedLow} to ${expectedHigh} (mean ${baseline.mean} ± ${sigma}σ, σ=${baseline.stddev})`,
|
|
458
|
+
zScore,
|
|
459
|
+
baselineMedian: baseline.median,
|
|
460
|
+
baselineP95: baseline.p95,
|
|
461
|
+
baselineSampleCount: baseline.sampleCount,
|
|
462
|
+
baselineWindowDays: baseline.windowDays,
|
|
463
|
+
hourOfWeek,
|
|
464
|
+
sensitivity,
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
const serialized: SerializedResult = ToolResultSerializer.serializeRows([
|
|
468
|
+
row,
|
|
469
|
+
]);
|
|
470
|
+
|
|
471
|
+
// Expected-range band + actual values over the recent past, for the panel.
|
|
472
|
+
const chartStart: Date = OneUptimeDate.addRemoveHours(
|
|
473
|
+
atTime,
|
|
474
|
+
-1 * BASELINE_CHART_HOURS,
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
let bandSeries: Array<BandPoint> = [];
|
|
478
|
+
let actualPoints: Array<AIChatWidgetPoint> = [];
|
|
479
|
+
try {
|
|
480
|
+
bandSeries = await MetricBaselineService.getBandSeries({
|
|
481
|
+
projectId: ctx.projectId,
|
|
482
|
+
metricName,
|
|
483
|
+
primaryEntityId: entityId,
|
|
484
|
+
startTime: chartStart,
|
|
485
|
+
endTime: atTime,
|
|
486
|
+
intervalMinutes: 15,
|
|
487
|
+
sigmaCount: sigma,
|
|
488
|
+
windowDays,
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
const chartQuery: JSONObject = {
|
|
492
|
+
name: metricName,
|
|
493
|
+
time: new InBetween(chartStart, atTime),
|
|
494
|
+
};
|
|
495
|
+
if (entityId) {
|
|
496
|
+
chartQuery["primaryEntityId"] = entityId;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
const chartActualResult: AggregatedResult =
|
|
500
|
+
await MetricService.aggregateBy({
|
|
501
|
+
aggregateColumnName: "value",
|
|
502
|
+
aggregationType: AggregationType.Avg,
|
|
503
|
+
aggregationTimestampColumnName: "time",
|
|
504
|
+
startTimestamp: chartStart,
|
|
505
|
+
endTimestamp: atTime,
|
|
506
|
+
query: chartQuery as never,
|
|
507
|
+
limit: 200,
|
|
508
|
+
skip: 0,
|
|
509
|
+
props: ctx.props,
|
|
510
|
+
} as AggregateBy<Metric>);
|
|
511
|
+
|
|
512
|
+
actualPoints = chartActualResult.data.map((item: AggregatedModel) => {
|
|
513
|
+
return {
|
|
514
|
+
x: OneUptimeDate.toString(OneUptimeDate.fromString(item.timestamp)),
|
|
515
|
+
y: typeof item.value === "number" ? item.value : null,
|
|
516
|
+
};
|
|
517
|
+
});
|
|
518
|
+
} catch {
|
|
519
|
+
// The band chart is decorative — never fail the verdict for it.
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const toPoints: (
|
|
523
|
+
pick: (point: BandPoint) => number,
|
|
524
|
+
) => Array<AIChatWidgetPoint> = (
|
|
525
|
+
pick: (point: BandPoint) => number,
|
|
526
|
+
): Array<AIChatWidgetPoint> => {
|
|
527
|
+
return bandSeries.map((point: BandPoint) => {
|
|
528
|
+
return {
|
|
529
|
+
x: OneUptimeDate.toString(point.time),
|
|
530
|
+
y: pick(point),
|
|
531
|
+
};
|
|
532
|
+
});
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
dataForLlm: serialized.text,
|
|
537
|
+
rowCount: serialized.rowCount,
|
|
538
|
+
citationLabel,
|
|
539
|
+
citationTarget: { type: AIChatCitationTargetType.Metrics },
|
|
540
|
+
redactionCount: serialized.redactionCount,
|
|
541
|
+
isTruncated: serialized.isTruncated,
|
|
542
|
+
widget:
|
|
543
|
+
bandSeries.length > 0
|
|
544
|
+
? WidgetBuilder.timeSeries({
|
|
545
|
+
title: `${metricName} vs expected range`,
|
|
546
|
+
description: `Hour-of-week baseline (±${sigma}σ, ${windowDays}-day window), ${chartStart.toISOString()} – ${atTime.toISOString()}`,
|
|
547
|
+
series: [
|
|
548
|
+
{
|
|
549
|
+
name: "expected high",
|
|
550
|
+
points: toPoints((point: BandPoint) => {
|
|
551
|
+
return point.expectedHigh;
|
|
552
|
+
}),
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
name: "expected low",
|
|
556
|
+
points: toPoints((point: BandPoint) => {
|
|
557
|
+
return point.expectedLow;
|
|
558
|
+
}),
|
|
559
|
+
},
|
|
560
|
+
...(actualPoints.length > 0
|
|
561
|
+
? [{ name: "actual", points: actualPoints }]
|
|
562
|
+
: []),
|
|
563
|
+
],
|
|
564
|
+
valueLabel: metricName,
|
|
565
|
+
link: { type: AIChatCitationTargetType.Metrics },
|
|
566
|
+
})
|
|
567
|
+
: undefined,
|
|
568
|
+
};
|
|
569
|
+
},
|
|
570
|
+
};
|