@oneuptime/common 11.5.3 → 11.5.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/AIAgentTaskPullRequest.ts +56 -45
- package/Models/DatabaseModels/AIInsight.ts +748 -0
- package/Models/DatabaseModels/AIRun.ts +262 -0
- package/Models/DatabaseModels/CodeRepository.ts +42 -0
- package/Models/DatabaseModels/Dashboard.ts +3 -3
- package/Models/DatabaseModels/GlobalConfig.ts +105 -0
- package/Models/DatabaseModels/Index.ts +4 -8
- package/Models/DatabaseModels/InstanceHealthLog.ts +277 -0
- package/Models/DatabaseModels/LlmLog.ts +33 -0
- package/Models/DatabaseModels/Project.ts +123 -6
- package/Models/DatabaseModels/Runbook.ts +1 -1
- package/Server/API/AIAgentDataAPI.ts +802 -140
- package/Server/API/AIAgentTaskAPI.ts +132 -69
- package/Server/API/AIAgentTaskLogAPI.ts +65 -41
- package/Server/API/AIAgentTaskPullRequestAPI.ts +41 -0
- package/Server/API/AIInsightAPI.ts +220 -0
- package/Server/API/AIInvestigationAPI.ts +363 -1
- package/Server/API/CodeFixRunAPI.ts +251 -0
- package/Server/API/GitHubAPI.ts +246 -3
- package/Server/API/TelemetryExceptionAPI.ts +193 -48
- package/Server/EnvironmentConfig.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.ts +73 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.ts +53 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.ts +75 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.ts +203 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.ts +163 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +30 -0
- package/Server/Infrastructure/Queue.ts +82 -4
- package/Server/Infrastructure/Semaphore.ts +62 -1
- package/Server/Services/AIAgentService.ts +32 -0
- package/Server/Services/AIAgentTaskPullRequestService.ts +117 -0
- package/Server/Services/AIInsightService.ts +174 -0
- package/Server/Services/AIRunEventService.ts +63 -0
- package/Server/Services/AIRunService.ts +259 -1
- package/Server/Services/AIService.ts +249 -7
- package/Server/Services/AlertService.ts +4 -4
- package/Server/Services/CodeRepositoryService.ts +209 -0
- package/Server/Services/DashboardService.ts +11 -2
- package/Server/Services/GlobalConfigService.ts +148 -0
- package/Server/Services/IncidentService.ts +183 -38
- package/Server/Services/IncidentStateTimelineService.ts +24 -4
- package/Server/Services/Index.ts +4 -4
- package/Server/Services/{AIAgentTaskLogService.ts → InstanceHealthLogService.ts} +1 -1
- package/Server/Services/LlmLogService.ts +27 -0
- package/Server/Services/LlmProviderService.ts +108 -0
- package/Server/Services/MetricBaselineService.ts +123 -0
- package/Server/Services/MonitorService.ts +15 -0
- package/Server/Services/TelemetryExceptionService.ts +323 -116
- package/Server/Services/TraceAggregationService.ts +176 -0
- package/Server/Types/Workflow/ComponentCode.ts +6 -0
- package/Server/Types/Workflow/Components/AI/GenerateText.ts +326 -0
- package/Server/Types/Workflow/Components/Index.ts +2 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +1 -1
- package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +71 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +243 -0
- package/Server/Utils/AI/CodeFix/CodeFixRunQueue.ts +131 -0
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +148 -0
- package/Server/Utils/AI/CodeFix/OpenPullRequestCap.ts +117 -0
- package/Server/Utils/AI/Eval/EvalCorpus.ts +369 -0
- package/Server/Utils/AI/Eval/EvalScores.ts +172 -0
- package/Server/Utils/AI/Eval/ReplayInvestigation.ts +87 -0
- package/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.ts +676 -0
- package/Server/Utils/AI/{Sentinel/SentinelInvestigationEngine.ts → SRE/AIInvestigationEngine.ts} +58 -37
- package/Server/Utils/AI/{Sentinel/SentinelMemory.ts → SRE/AIMemory.ts} +3 -3
- package/Server/Utils/AI/{Sentinel → SRE}/AlertInvestigationRunner.ts +50 -20
- package/Server/Utils/AI/SRE/ConfidenceSignal.ts +293 -0
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +115 -0
- package/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.ts +223 -0
- package/Server/Utils/AI/{Sentinel → SRE}/IncidentInvestigationRunner.ts +71 -21
- package/Server/Utils/AI/{Sentinel → SRE}/IncidentPostmortemRunner.ts +8 -8
- package/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.ts +364 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +317 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/Index.ts +27 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.ts +221 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +238 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.ts +521 -0
- package/Server/Utils/AI/SRE/Insights/FixRouting.ts +242 -0
- package/Server/Utils/AI/SRE/Insights/InsightScanner.ts +290 -0
- package/Server/Utils/AI/SRE/Insights/InsightStore.ts +283 -0
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +242 -0
- package/Server/Utils/AI/SRE/Insights/Triage.ts +162 -0
- package/Server/Utils/AI/SRE/Insights/Types.ts +49 -0
- package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +212 -0
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +282 -0
- package/Server/Utils/AI/{Sentinel → SRE}/InvestigationQueue.ts +114 -19
- package/Server/Utils/AI/{Sentinel → SRE}/README.md +4 -4
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +172 -0
- package/Server/Utils/AI/Toolbox/{SentinelActionTools.ts → AIActionTools.ts} +22 -1
- package/Server/Utils/AI/Toolbox/Index.ts +2 -2
- package/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.ts +526 -0
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +319 -1
- package/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.ts +221 -0
- package/Server/Utils/CodeRepository/StackTraceRepoResolver.ts +571 -0
- package/Server/Utils/Execute.ts +34 -13
- package/Server/Utils/LLM/LLMService.ts +160 -30
- package/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.ts +152 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +29 -0
- package/Tests/Server/API/DashboardMasterPasswordAPI.test.ts +225 -0
- package/Tests/Server/Infrastructure/Queue.test.ts +227 -0
- package/Tests/Server/Infrastructure/SemaphorePermit.test.ts +159 -0
- package/Tests/Server/Services/AIAgentTaskPullRequestOutcomeStats.test.ts +154 -0
- package/Tests/Server/Services/AIInsightService.test.ts +324 -0
- package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +401 -0
- package/Tests/Server/Services/AIRunHumanVerdict.test.ts +161 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +95 -5
- package/Tests/Server/Services/AIServiceProjectAccess.test.ts +259 -0
- package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +249 -0
- package/Tests/Server/Services/FixPerformanceTaskTrigger.test.ts +274 -0
- package/Tests/Server/Services/GlobalConfigService.test.ts +80 -0
- package/Tests/Server/Services/IncidentInternalNoteAnnouncement.test.ts +1 -1
- package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +313 -0
- package/Tests/Server/Services/LlmProviderProjectOwned.test.ts +132 -0
- package/Tests/Server/Services/TelemetryExceptionAIFixReadiness.test.ts +405 -0
- package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +322 -0
- package/Tests/Server/Services/TraceServiceLatencyProfile.test.ts +278 -0
- package/Tests/Server/Types/Workflow/Components/AIGenerateText.test.ts +722 -0
- package/Tests/Server/Utils/AI/{SentinelAlertGating.test.ts → AIAlertGating.test.ts} +19 -19
- package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +362 -0
- package/Tests/Server/Utils/AI/{SentinelInvestigationQueue.test.ts → AIInvestigationQueue.test.ts} +19 -19
- package/Tests/Server/Utils/AI/CodeAgentWorkspaceGuard.test.ts +138 -0
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +335 -0
- package/Tests/Server/Utils/AI/CodeFixRunQueue.test.ts +134 -0
- package/Tests/Server/Utils/AI/EvalCorpus.test.ts +209 -0
- package/Tests/Server/Utils/AI/EvalScores.test.ts +343 -0
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +218 -0
- package/Tests/Server/Utils/AI/Insights/ErrorLogSpikeDetector.test.ts +437 -0
- package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +287 -0
- package/Tests/Server/Utils/AI/Insights/InsightDetectorsIndex.test.ts +34 -0
- package/Tests/Server/Utils/AI/Insights/InsightFixRouting.test.ts +572 -0
- package/Tests/Server/Utils/AI/Insights/InsightNeverThrowsHardening.test.ts +344 -0
- package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +720 -0
- package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +467 -0
- package/Tests/Server/Utils/AI/Insights/InsightStoreHardening.test.ts +370 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriage.test.ts +210 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +221 -0
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +328 -0
- package/Tests/Server/Utils/AI/Insights/MetricBaselineDrift.test.ts +182 -0
- package/Tests/Server/Utils/AI/Insights/MetricDriftDetector.test.ts +280 -0
- package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +259 -0
- package/Tests/Server/Utils/AI/Insights/TraceLatencyRegressionDetector.test.ts +770 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +343 -0
- package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +307 -0
- package/Tests/Server/Utils/AI/OpenPullRequestCap.test.ts +170 -0
- package/Tests/Server/Utils/AI/SpanTreeAnalyzer.test.ts +559 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.test.ts +158 -0
- package/Tests/Server/Utils/GitHubCheckRunsConclusion.test.ts +100 -0
- package/Tests/Server/Utils/GitHubPullRequestStateMapping.test.ts +50 -0
- package/Tests/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.test.ts +266 -0
- package/Tests/Server/Utils/ServiceRepoLinkSuggester.test.ts +167 -0
- package/Tests/Server/Utils/StackTraceRepoResolver.test.ts +527 -0
- package/Tests/Types/AI/AIChatPermissionMode.test.ts +112 -0
- package/Tests/Types/AI/CodeFixTaskType.test.ts +152 -0
- package/Tests/Types/AI/FixPullRequestCiStatus.test.ts +181 -0
- package/Tests/Types/Monitor/MonitorStepSqlMonitor.test.ts +110 -0
- package/Tests/Types/Monitor/SqlDatabaseType.test.ts +55 -0
- package/Tests/Types/Workflow/AIGenerateTextMetadata.test.ts +180 -0
- package/Tests/UI/Components/TableBulkCsvExport.test.tsx +168 -0
- package/Tests/UI/Utils/TableColumnsToCsv.test.ts +523 -0
- package/Types/AI/AIChatTypes.ts +8 -0
- package/Types/AI/AIInsightEvidence.ts +77 -0
- package/Types/AI/AIInsightHumanVerdict.ts +15 -0
- package/Types/AI/AIInsightSeverity.ts +13 -0
- package/Types/AI/AIInsightStatus.ts +38 -0
- package/Types/AI/AIInsightType.ts +41 -0
- package/Types/AI/AIRunAutoGrade.ts +18 -0
- package/Types/AI/AIRunEventType.ts +5 -0
- package/Types/AI/AIRunHumanVerdict.ts +17 -0
- package/Types/AI/AIRunType.ts +6 -0
- package/Types/AI/CodeFixTaskContext.ts +88 -0
- package/Types/AI/CodeFixTaskType.ts +132 -0
- package/Types/AI/FixPullRequestCiStatus.ts +132 -0
- package/Types/BaseDatabase/AggregationIntervalUtil.ts +67 -0
- package/Types/Incident/IncidentMetricType.ts +7 -0
- package/Types/Monitor/CriteriaFilter.ts +8 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
- package/Types/Monitor/MonitorStep.ts +38 -0
- package/Types/Monitor/MonitorStepSqlMonitor.ts +141 -0
- package/Types/Monitor/MonitorType.ts +17 -0
- package/Types/Monitor/SqlDatabaseType.ts +49 -0
- package/Types/Monitor/SqlMonitor/SqlMonitorResponse.ts +28 -0
- package/Types/Permission.ts +11 -95
- package/Types/Probe/ProbeMonitorResponse.ts +2 -0
- package/Types/Runbook/RunbookStep.ts +26 -2
- package/Types/Runbook/RunbookStepType.ts +1 -0
- package/Types/Workflow/Component.ts +13 -0
- package/Types/Workflow/ComponentID.ts +1 -0
- package/Types/Workflow/Components/AI.ts +148 -0
- package/Types/Workflow/Components.ts +8 -0
- package/UI/Components/AI/GenerateFromAIModal.tsx +1 -1
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +11 -0
- package/UI/Components/MoreMenu/MoreMenu.tsx +1 -1
- package/UI/Components/Table/Table.tsx +38 -2
- package/UI/Utils/TableColumnsToCsv.ts +385 -0
- package/Utils/Monitor/MonitorMetricType.ts +1 -0
- package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js +59 -45
- package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AIInsight.js +795 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +274 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +43 -0
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Dashboard.js +3 -3
- package/build/dist/Models/DatabaseModels/Dashboard.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +110 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +4 -8
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/InstanceHealthLog.js +304 -0
- package/build/dist/Models/DatabaseModels/InstanceHealthLog.js.map +1 -0
- package/build/dist/Models/DatabaseModels/LlmLog.js +35 -0
- package/build/dist/Models/DatabaseModels/LlmLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +127 -6
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Runbook.js +1 -1
- package/build/dist/Models/DatabaseModels/Runbook.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +568 -85
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskAPI.js +100 -44
- package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskLogAPI.js +49 -25
- package/build/dist/Server/API/AIAgentTaskLogAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js +27 -0
- package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js.map +1 -1
- package/build/dist/Server/API/AIInsightAPI.js +140 -0
- package/build/dist/Server/API/AIInsightAPI.js.map +1 -0
- package/build/dist/Server/API/AIInvestigationAPI.js +257 -1
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/CodeFixRunAPI.js +181 -0
- package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -0
- package/build/dist/Server/API/GitHubAPI.js +164 -2
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryExceptionAPI.js +148 -43
- package/build/dist/Server/API/TelemetryExceptionAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +1 -1
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.js +125 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js +62 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +73 -3
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +44 -1
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Services/AIAgentService.js +29 -0
- package/build/dist/Server/Services/AIAgentService.js.map +1 -1
- package/build/dist/Server/Services/AIAgentTaskPullRequestService.js +78 -0
- package/build/dist/Server/Services/AIAgentTaskPullRequestService.js.map +1 -1
- package/build/dist/Server/Services/AIInsightService.js +164 -0
- package/build/dist/Server/Services/AIInsightService.js.map +1 -0
- package/build/dist/Server/Services/AIRunEventService.js +49 -0
- package/build/dist/Server/Services/AIRunEventService.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +221 -0
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +198 -11
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +4 -4
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/CodeRepositoryService.js +180 -0
- package/build/dist/Server/Services/CodeRepositoryService.js.map +1 -1
- package/build/dist/Server/Services/DashboardService.js +8 -2
- package/build/dist/Server/Services/DashboardService.js.map +1 -1
- package/build/dist/Server/Services/GlobalConfigService.js +84 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +149 -37
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +24 -4
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +4 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/{AIAgentTaskLogService.js → InstanceHealthLogService.js} +2 -2
- package/build/dist/Server/Services/InstanceHealthLogService.js.map +1 -0
- package/build/dist/Server/Services/LlmLogService.js +23 -0
- package/build/dist/Server/Services/LlmLogService.js.map +1 -1
- package/build/dist/Server/Services/LlmProviderService.js +96 -0
- package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
- package/build/dist/Server/Services/MetricBaselineService.js +65 -0
- package/build/dist/Server/Services/MetricBaselineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +9 -1
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryExceptionService.js +243 -82
- package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +124 -0
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/ComponentCode.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/AI/GenerateText.js +240 -0
- package/build/dist/Server/Types/Workflow/Components/AI/GenerateText.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/Index.js +2 -0
- package/build/dist/Server/Types/Workflow/Components/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +48 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +174 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js +126 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +131 -0
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -0
- package/build/dist/Server/Utils/AI/CodeFix/OpenPullRequestCap.js +99 -0
- package/build/dist/Server/Utils/AI/CodeFix/OpenPullRequestCap.js.map +1 -0
- package/build/dist/Server/Utils/AI/Eval/EvalCorpus.js +245 -0
- package/build/dist/Server/Utils/AI/Eval/EvalCorpus.js.map +1 -0
- package/build/dist/Server/Utils/AI/Eval/EvalScores.js +83 -0
- package/build/dist/Server/Utils/AI/Eval/EvalScores.js.map +1 -0
- package/build/dist/Server/Utils/AI/Eval/ReplayInvestigation.js +12 -0
- package/build/dist/Server/Utils/AI/Eval/ReplayInvestigation.js.map +1 -0
- package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js +439 -0
- package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel/SentinelInvestigationEngine.js → SRE/AIInvestigationEngine.js} +47 -31
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel/SentinelMemory.js → SRE/AIMemory.js} +5 -5
- package/build/dist/Server/Utils/AI/SRE/AIMemory.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/AlertInvestigationRunner.js +42 -19
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +226 -0
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +100 -0
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.js +174 -0
- package/build/dist/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/IncidentInvestigationRunner.js +60 -22
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/IncidentPostmortemRunner.js +9 -9
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.js +268 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +226 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/Index.js +26 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/Index.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.js +159 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +177 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.js +384 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js +180 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js +269 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +231 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +206 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js +121 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Types.js +2 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Types.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +148 -0
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +231 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -0
- package/build/dist/Server/Utils/AI/{Sentinel → SRE}/InvestigationQueue.js +102 -23
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +167 -0
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/{SentinelActionTools.js → AIActionTools.js} +18 -2
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +2 -2
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js +301 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +240 -2
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.js +127 -0
- package/build/dist/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js +336 -0
- package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js.map +1 -0
- package/build/dist/Server/Utils/Execute.js +21 -11
- package/build/dist/Server/Utils/Execute.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +125 -25
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.js +120 -0
- package/build/dist/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +21 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Types/AI/AIInsightEvidence.js +2 -0
- package/build/dist/Types/AI/AIInsightEvidence.js.map +1 -0
- package/build/dist/Types/AI/AIInsightHumanVerdict.js +16 -0
- package/build/dist/Types/AI/AIInsightHumanVerdict.js.map +1 -0
- package/build/dist/Types/AI/AIInsightSeverity.js +14 -0
- package/build/dist/Types/AI/AIInsightSeverity.js.map +1 -0
- package/build/dist/Types/AI/AIInsightStatus.js +36 -0
- package/build/dist/Types/AI/AIInsightStatus.js.map +1 -0
- package/build/dist/Types/AI/AIInsightType.js +42 -0
- package/build/dist/Types/AI/AIInsightType.js.map +1 -0
- package/build/dist/Types/AI/AIRunAutoGrade.js +19 -0
- package/build/dist/Types/AI/AIRunAutoGrade.js.map +1 -0
- package/build/dist/Types/AI/AIRunEventType.js +5 -0
- package/build/dist/Types/AI/AIRunEventType.js.map +1 -1
- package/build/dist/Types/AI/AIRunHumanVerdict.js +18 -0
- package/build/dist/Types/AI/AIRunHumanVerdict.js.map +1 -0
- package/build/dist/Types/AI/AIRunType.js +6 -0
- package/build/dist/Types/AI/AIRunType.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskContext.js +29 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskType.js +122 -0
- package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -0
- package/build/dist/Types/AI/FixPullRequestCiStatus.js +102 -0
- package/build/dist/Types/AI/FixPullRequestCiStatus.js.map +1 -0
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +55 -0
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -1
- package/build/dist/Types/Incident/IncidentMetricType.js +7 -0
- package/build/dist/Types/Incident/IncidentMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +7 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +28 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js +93 -0
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +15 -0
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SqlDatabaseType.js +47 -0
- package/build/dist/Types/Monitor/SqlDatabaseType.js.map +1 -0
- package/build/dist/Types/Monitor/SqlMonitor/SqlMonitorResponse.js +2 -0
- package/build/dist/Types/Monitor/SqlMonitor/SqlMonitorResponse.js.map +1 -0
- package/build/dist/Types/Permission.js +10 -84
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Runbook/RunbookStepType.js +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
- package/build/dist/Types/Workflow/ComponentID.js +1 -0
- package/build/dist/Types/Workflow/ComponentID.js.map +1 -1
- package/build/dist/Types/Workflow/Components/AI.js +135 -0
- package/build/dist/Types/Workflow/Components/AI.js.map +1 -0
- package/build/dist/Types/Workflow/Components.js +7 -0
- package/build/dist/Types/Workflow/Components.js.map +1 -1
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -1
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +9 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +1 -1
- package/build/dist/UI/Components/Table/Table.js +28 -2
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Utils/TableColumnsToCsv.js +291 -0
- package/build/dist/UI/Utils/TableColumnsToCsv.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/package.json +1 -1
- package/Models/DatabaseModels/AIAgentTask.ts +0 -660
- package/Models/DatabaseModels/AIAgentTaskLog.ts +0 -426
- package/Models/DatabaseModels/AIAgentTaskTelemetryException.ts +0 -399
- package/Models/DatabaseModels/ServiceCodeRepository.ts +0 -647
- package/Server/Services/AIAgentTaskService.ts +0 -240
- package/Server/Services/AIAgentTaskTelemetryExceptionService.ts +0 -39
- package/Server/Services/ServiceCodeRepositoryService.ts +0 -55
- package/Tests/Server/Services/AIAgentTaskServiceClaim.test.ts +0 -146
- package/Types/AI/AIAgentTaskMetadata.ts +0 -25
- package/Types/AI/AIAgentTaskType.ts +0 -40
- package/build/dist/Models/DatabaseModels/AIAgentTask.js +0 -691
- package/build/dist/Models/DatabaseModels/AIAgentTask.js.map +0 -1
- package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js +0 -447
- package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js.map +0 -1
- package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js +0 -415
- package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js.map +0 -1
- package/build/dist/Models/DatabaseModels/ServiceCodeRepository.js +0 -665
- package/build/dist/Models/DatabaseModels/ServiceCodeRepository.js.map +0 -1
- package/build/dist/Server/Services/AIAgentTaskLogService.js.map +0 -1
- package/build/dist/Server/Services/AIAgentTaskService.js +0 -217
- package/build/dist/Server/Services/AIAgentTaskService.js.map +0 -1
- package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js +0 -36
- package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js.map +0 -1
- package/build/dist/Server/Services/ServiceCodeRepositoryService.js +0 -54
- package/build/dist/Server/Services/ServiceCodeRepositoryService.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/InvestigationQueue.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +0 -1
- package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js.map +0 -1
- package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js.map +0 -1
- package/build/dist/Types/AI/AIAgentTaskMetadata.js +0 -6
- package/build/dist/Types/AI/AIAgentTaskMetadata.js.map +0 -1
- package/build/dist/Types/AI/AIAgentTaskType.js +0 -29
- package/build/dist/Types/AI/AIAgentTaskType.js.map +0 -1
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import ObjectID from "../../../../../../Types/ObjectID";
|
|
2
|
+
import OneUptimeDate from "../../../../../../Types/Date";
|
|
3
|
+
import SortOrder from "../../../../../../Types/BaseDatabase/SortOrder";
|
|
4
|
+
import InBetween from "../../../../../../Types/BaseDatabase/InBetween";
|
|
5
|
+
import PositiveNumber from "../../../../../../Types/PositiveNumber";
|
|
6
|
+
import { JSONObject } from "../../../../../../Types/JSON";
|
|
7
|
+
import { LIMIT_PER_PROJECT } from "../../../../../../Types/Database/LimitMax";
|
|
8
|
+
import AIInsightType from "../../../../../../Types/AI/AIInsightType";
|
|
9
|
+
import AIInsightSeverity from "../../../../../../Types/AI/AIInsightSeverity";
|
|
10
|
+
import TelemetryException from "../../../../../../Models/DatabaseModels/TelemetryException";
|
|
11
|
+
import Service from "../../../../../../Models/DatabaseModels/Service";
|
|
12
|
+
import TelemetryExceptionService from "../../../../../Services/TelemetryExceptionService";
|
|
13
|
+
import ExceptionInstanceService from "../../../../../Services/ExceptionInstanceService";
|
|
14
|
+
import ServiceService from "../../../../../Services/ServiceService";
|
|
15
|
+
import QueryHelper from "../../../../../Types/Database/QueryHelper";
|
|
16
|
+
import {
|
|
17
|
+
InsightCandidate,
|
|
18
|
+
InsightDetector,
|
|
19
|
+
InsightScanContext,
|
|
20
|
+
} from "../Types";
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* ExceptionSpike — an ESTABLISHED exception (first seen more than a day
|
|
24
|
+
* ago) whose recent hourly occurrence rate blew past its own 24-hour
|
|
25
|
+
* baseline, including the dormant-awakening case (an old exception that was
|
|
26
|
+
* quiet all day suddenly firing). Candidates come cheap from Postgres
|
|
27
|
+
* (group table); the actual rates come from two ClickHouse counts per
|
|
28
|
+
* candidate (fingerprint bloom index + time range — the exception-monitor
|
|
29
|
+
* count idiom). Deterministic — no LLM anywhere in this detector.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
// The spike window: occurrences in the last hour, compared to...
|
|
33
|
+
export const EXCEPTION_SPIKE_RECENT_WINDOW_HOURS: number = 1;
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
* ...the exception's own average hourly rate over the 24 hours BEFORE the
|
|
37
|
+
* spike window. Self-baselining means a chronically noisy exception does
|
|
38
|
+
* not alert on its normal noise.
|
|
39
|
+
*/
|
|
40
|
+
export const EXCEPTION_SPIKE_BASELINE_WINDOW_HOURS: number = 24;
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* Absolute floor: below 10 occurrences/hour a "5x spike" can be 2→10 raw
|
|
44
|
+
* events — statistically meaningless and guaranteed inbox noise.
|
|
45
|
+
*/
|
|
46
|
+
export const EXCEPTION_SPIKE_MIN_RECENT_COUNT: number = 10;
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* Rate multiplier that counts as a spike. The baseline hourly average is
|
|
50
|
+
* floored at 1 (see evaluateSpike) so near-zero baselines don't produce
|
|
51
|
+
* infinite multipliers; the dormant case (prior24 == 0, recent >= 10) then
|
|
52
|
+
* falls out of the same rule automatically.
|
|
53
|
+
*/
|
|
54
|
+
export const EXCEPTION_SPIKE_MIN_MULTIPLIER: number = 5;
|
|
55
|
+
|
|
56
|
+
// A >= 10x spike is a step change, not a fluctuation — escalate to High.
|
|
57
|
+
export const EXCEPTION_SPIKE_HIGH_SEVERITY_MULTIPLIER: number = 10;
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
* Candidate cap per scan tick: two ClickHouse counts per candidate, so 25
|
|
61
|
+
* candidates = 50 bounded point queries. Sorted by lifetime occurrence
|
|
62
|
+
* count so the perennial heavy hitters are always inspected first.
|
|
63
|
+
*/
|
|
64
|
+
export const EXCEPTION_SPIKE_CANDIDATE_LIMIT: number = 25;
|
|
65
|
+
|
|
66
|
+
// Titles must stay scannable in a list — truncate long exception messages.
|
|
67
|
+
export const EXCEPTION_SPIKE_TITLE_MESSAGE_MAX_LENGTH: number = 80;
|
|
68
|
+
|
|
69
|
+
export interface ExceptionSpikeDecision {
|
|
70
|
+
isSpike: boolean;
|
|
71
|
+
// recent count / max(baseline hourly average, 1).
|
|
72
|
+
multiplier: number;
|
|
73
|
+
severity: AIInsightSeverity;
|
|
74
|
+
// prior-window count / EXCEPTION_SPIKE_BASELINE_WINDOW_HOURS (unfloored).
|
|
75
|
+
baselineHourlyAverage: number;
|
|
76
|
+
// Zero occurrences in the whole baseline window, then a burst.
|
|
77
|
+
isDormantAwakening: boolean;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default class ExceptionSpikeDetector implements InsightDetector {
|
|
81
|
+
public insightType: AIInsightType = AIInsightType.ExceptionSpike;
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* Pure decision: recent-hour count vs the prior 24h window count.
|
|
85
|
+
* Spike ⇔ recent >= EXCEPTION_SPIKE_MIN_RECENT_COUNT AND
|
|
86
|
+
* recent >= EXCEPTION_SPIKE_MIN_MULTIPLIER * max(prior/24, 1).
|
|
87
|
+
*/
|
|
88
|
+
public static evaluateSpike(
|
|
89
|
+
recentCount: number,
|
|
90
|
+
priorWindowCount: number,
|
|
91
|
+
): ExceptionSpikeDecision {
|
|
92
|
+
const baselineHourlyAverage: number =
|
|
93
|
+
priorWindowCount / EXCEPTION_SPIKE_BASELINE_WINDOW_HOURS;
|
|
94
|
+
const effectiveBaseline: number = Math.max(baselineHourlyAverage, 1);
|
|
95
|
+
const multiplier: number = recentCount / effectiveBaseline;
|
|
96
|
+
|
|
97
|
+
const isSpike: boolean =
|
|
98
|
+
recentCount >= EXCEPTION_SPIKE_MIN_RECENT_COUNT &&
|
|
99
|
+
multiplier >= EXCEPTION_SPIKE_MIN_MULTIPLIER;
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
isSpike,
|
|
103
|
+
multiplier,
|
|
104
|
+
severity:
|
|
105
|
+
multiplier >= EXCEPTION_SPIKE_HIGH_SEVERITY_MULTIPLIER
|
|
106
|
+
? AIInsightSeverity.High
|
|
107
|
+
: AIInsightSeverity.Medium,
|
|
108
|
+
baselineHourlyAverage,
|
|
109
|
+
isDormantAwakening:
|
|
110
|
+
priorWindowCount === 0 &&
|
|
111
|
+
recentCount >= EXCEPTION_SPIKE_MIN_RECENT_COUNT,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/*
|
|
116
|
+
* Human label for the exception: the type when present, else the first
|
|
117
|
+
* EXCEPTION_SPIKE_TITLE_MESSAGE_MAX_LENGTH characters of the message.
|
|
118
|
+
*/
|
|
119
|
+
public static buildExceptionLabel(
|
|
120
|
+
exceptionType: string | undefined,
|
|
121
|
+
message: string | undefined,
|
|
122
|
+
): string {
|
|
123
|
+
if (exceptionType && exceptionType.trim().length > 0) {
|
|
124
|
+
return exceptionType.trim();
|
|
125
|
+
}
|
|
126
|
+
const trimmedMessage: string = (message || "").trim();
|
|
127
|
+
if (trimmedMessage.length === 0) {
|
|
128
|
+
return "Unknown exception";
|
|
129
|
+
}
|
|
130
|
+
if (trimmedMessage.length <= EXCEPTION_SPIKE_TITLE_MESSAGE_MAX_LENGTH) {
|
|
131
|
+
return trimmedMessage;
|
|
132
|
+
}
|
|
133
|
+
return `${trimmedMessage.slice(0, EXCEPTION_SPIKE_TITLE_MESSAGE_MAX_LENGTH)}…`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Stable dedupe key, keyed on the exception GROUP id (ingest dedupe unit).
|
|
137
|
+
public static buildFingerprint(telemetryExceptionId: string): string {
|
|
138
|
+
return `exception-spike:${telemetryExceptionId}`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public async detect(
|
|
142
|
+
context: InsightScanContext,
|
|
143
|
+
): Promise<Array<InsightCandidate>> {
|
|
144
|
+
const recentWindowStart: Date = OneUptimeDate.addRemoveHours(
|
|
145
|
+
context.now,
|
|
146
|
+
-1 * EXCEPTION_SPIKE_RECENT_WINDOW_HOURS,
|
|
147
|
+
);
|
|
148
|
+
const priorWindowStart: Date = OneUptimeDate.addRemoveHours(
|
|
149
|
+
recentWindowStart,
|
|
150
|
+
-1 * EXCEPTION_SPIKE_BASELINE_WINDOW_HOURS,
|
|
151
|
+
);
|
|
152
|
+
const establishedBefore: Date = OneUptimeDate.addRemoveHours(
|
|
153
|
+
context.now,
|
|
154
|
+
-1 * EXCEPTION_SPIKE_BASELINE_WINDOW_HOURS,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* Candidates: established exception groups (born before the baseline
|
|
159
|
+
* window so they HAVE a baseline) that were active in the spike
|
|
160
|
+
* window. Anything younger is NewExceptionDetector's territory.
|
|
161
|
+
*/
|
|
162
|
+
const candidateQuery: JSONObject = {
|
|
163
|
+
projectId: context.projectId,
|
|
164
|
+
lastSeenAt: QueryHelper.greaterThanEqualTo(recentWindowStart),
|
|
165
|
+
firstSeenAt: QueryHelper.lessThan(establishedBefore),
|
|
166
|
+
isResolved: false,
|
|
167
|
+
isArchived: false,
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const exceptions: Array<TelemetryException> =
|
|
171
|
+
await TelemetryExceptionService.findBy({
|
|
172
|
+
query: candidateQuery as never,
|
|
173
|
+
select: {
|
|
174
|
+
_id: true,
|
|
175
|
+
message: true,
|
|
176
|
+
exceptionType: true,
|
|
177
|
+
fingerprint: true,
|
|
178
|
+
occuranceCount: true,
|
|
179
|
+
firstSeenAt: true,
|
|
180
|
+
primaryEntityId: true,
|
|
181
|
+
},
|
|
182
|
+
sort: {
|
|
183
|
+
occuranceCount: SortOrder.Descending,
|
|
184
|
+
},
|
|
185
|
+
limit: EXCEPTION_SPIKE_CANDIDATE_LIMIT,
|
|
186
|
+
skip: 0,
|
|
187
|
+
props: { isRoot: true },
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const candidates: Array<InsightCandidate> = [];
|
|
191
|
+
|
|
192
|
+
for (const exception of exceptions) {
|
|
193
|
+
if (!exception.id || !exception.fingerprint) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/*
|
|
198
|
+
* Two bounded ClickHouse counts (fingerprint bloom + time range —
|
|
199
|
+
* the MonitorTelemetryMonitor.monitorException idiom). Occurrence
|
|
200
|
+
* `time` is client-reported, so both windows use the same clock and
|
|
201
|
+
* skew cancels out within the comparison.
|
|
202
|
+
*/
|
|
203
|
+
const recentCount: PositiveNumber =
|
|
204
|
+
await ExceptionInstanceService.countBy({
|
|
205
|
+
query: {
|
|
206
|
+
projectId: context.projectId,
|
|
207
|
+
fingerprint: exception.fingerprint,
|
|
208
|
+
time: new InBetween(recentWindowStart, context.now),
|
|
209
|
+
} as never,
|
|
210
|
+
skip: 0,
|
|
211
|
+
limit: LIMIT_PER_PROJECT,
|
|
212
|
+
props: { isRoot: true },
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const priorCount: PositiveNumber = await ExceptionInstanceService.countBy(
|
|
216
|
+
{
|
|
217
|
+
query: {
|
|
218
|
+
projectId: context.projectId,
|
|
219
|
+
fingerprint: exception.fingerprint,
|
|
220
|
+
time: new InBetween(priorWindowStart, recentWindowStart),
|
|
221
|
+
} as never,
|
|
222
|
+
skip: 0,
|
|
223
|
+
limit: LIMIT_PER_PROJECT,
|
|
224
|
+
props: { isRoot: true },
|
|
225
|
+
},
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const decision: ExceptionSpikeDecision =
|
|
229
|
+
ExceptionSpikeDetector.evaluateSpike(
|
|
230
|
+
recentCount.toNumber(),
|
|
231
|
+
priorCount.toNumber(),
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
if (!decision.isSpike) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const serviceName: string | null = await this.resolveServiceName(
|
|
239
|
+
exception.primaryEntityId,
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const label: string = ExceptionSpikeDetector.buildExceptionLabel(
|
|
243
|
+
exception.exceptionType,
|
|
244
|
+
exception.message,
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const firstSeenAtIso: string | undefined = exception.firstSeenAt
|
|
248
|
+
? exception.firstSeenAt.toISOString()
|
|
249
|
+
: undefined;
|
|
250
|
+
|
|
251
|
+
const detailLines: Array<string> = [
|
|
252
|
+
decision.isDormantAwakening
|
|
253
|
+
? "**Dormant exception woke up**"
|
|
254
|
+
: "**Exception spike detected**",
|
|
255
|
+
"",
|
|
256
|
+
`- Exception: \`${label}\``,
|
|
257
|
+
];
|
|
258
|
+
if (exception.message) {
|
|
259
|
+
detailLines.push(`- Message: ${exception.message}`);
|
|
260
|
+
}
|
|
261
|
+
if (serviceName) {
|
|
262
|
+
detailLines.push(`- Service: ${serviceName}`);
|
|
263
|
+
}
|
|
264
|
+
detailLines.push(
|
|
265
|
+
`- Occurrences in the last ${EXCEPTION_SPIKE_RECENT_WINDOW_HOURS}h: ${recentCount.toNumber()}`,
|
|
266
|
+
`- Baseline: ${decision.baselineHourlyAverage.toFixed(2)}/hour over the prior ${EXCEPTION_SPIKE_BASELINE_WINDOW_HOURS}h (${priorCount.toNumber()} total)`,
|
|
267
|
+
`- Spike multiplier: ${decision.multiplier.toFixed(1)}x`,
|
|
268
|
+
`- Exception first seen: ${firstSeenAtIso || "unknown"} (lifetime occurrences: ${exception.occuranceCount || 0})`,
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
candidates.push({
|
|
272
|
+
insightType: AIInsightType.ExceptionSpike,
|
|
273
|
+
fingerprint: ExceptionSpikeDetector.buildFingerprint(
|
|
274
|
+
exception.id.toString(),
|
|
275
|
+
),
|
|
276
|
+
title: `Exception spike: ${label} at ${decision.multiplier.toFixed(1)}x normal rate${serviceName ? ` in ${serviceName}` : ""}`,
|
|
277
|
+
detailMarkdown: detailLines.join("\n"),
|
|
278
|
+
severity: decision.severity,
|
|
279
|
+
serviceName: serviceName || undefined,
|
|
280
|
+
telemetryServiceId: serviceName ? exception.primaryEntityId : undefined,
|
|
281
|
+
telemetryExceptionId: exception.id,
|
|
282
|
+
evidence: {
|
|
283
|
+
exception: {
|
|
284
|
+
exceptionMessage: exception.message,
|
|
285
|
+
exceptionType: exception.exceptionType,
|
|
286
|
+
recentOccurrenceCount: recentCount.toNumber(),
|
|
287
|
+
baselineHourlyAverage: decision.baselineHourlyAverage,
|
|
288
|
+
spikeMultiplier: decision.multiplier,
|
|
289
|
+
totalOccurrenceCount: exception.occuranceCount,
|
|
290
|
+
firstSeenAt: firstSeenAtIso,
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return candidates;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/*
|
|
300
|
+
* Best-effort service attribution: primaryEntityId is polymorphic and
|
|
301
|
+
* findOneById returns null for non-Service kinds — the insight then
|
|
302
|
+
* ships without a service name.
|
|
303
|
+
*/
|
|
304
|
+
private async resolveServiceName(
|
|
305
|
+
primaryEntityId: ObjectID | undefined,
|
|
306
|
+
): Promise<string | null> {
|
|
307
|
+
if (!primaryEntityId) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
const service: Service | null = await ServiceService.findOneById({
|
|
311
|
+
id: primaryEntityId,
|
|
312
|
+
select: { name: true },
|
|
313
|
+
props: { isRoot: true },
|
|
314
|
+
});
|
|
315
|
+
return service?.name || null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { InsightDetector } from "../Types";
|
|
2
|
+
import NewExceptionDetector from "./NewExceptionDetector";
|
|
3
|
+
import ExceptionSpikeDetector from "./ExceptionSpikeDetector";
|
|
4
|
+
import ErrorLogSpikeDetector from "./ErrorLogSpikeDetector";
|
|
5
|
+
import TraceLatencyRegressionDetector from "./TraceLatencyRegressionDetector";
|
|
6
|
+
import MetricDriftDetector from "./MetricDriftDetector";
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* The detector registry. All five deterministic sensors — no LLM in any of
|
|
10
|
+
* them. Order matters for the scanner's per-project new-insight cap: the
|
|
11
|
+
* signals most likely to be actionable code problems (exceptions, then
|
|
12
|
+
* latency) come before the softer volume/drift signals, so when the cap
|
|
13
|
+
* bites it drops the softest findings first. The scanner runs every
|
|
14
|
+
* detector with per-detector error isolation — a detector that throws
|
|
15
|
+
* must not silence its siblings.
|
|
16
|
+
*/
|
|
17
|
+
export default class InsightDetectors {
|
|
18
|
+
public static getAllDetectors(): Array<InsightDetector> {
|
|
19
|
+
return [
|
|
20
|
+
new NewExceptionDetector(),
|
|
21
|
+
new ExceptionSpikeDetector(),
|
|
22
|
+
new TraceLatencyRegressionDetector(),
|
|
23
|
+
new ErrorLogSpikeDetector(),
|
|
24
|
+
new MetricDriftDetector(),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import AIInsightType from "../../../../../../Types/AI/AIInsightType";
|
|
2
|
+
import AIInsightSeverity from "../../../../../../Types/AI/AIInsightSeverity";
|
|
3
|
+
import MetricBaselineService, {
|
|
4
|
+
MetricDriftWindowRow,
|
|
5
|
+
MetricBaselineService as MetricBaselineServiceClass,
|
|
6
|
+
} from "../../../../../Services/MetricBaselineService";
|
|
7
|
+
import {
|
|
8
|
+
InsightCandidate,
|
|
9
|
+
InsightDetector,
|
|
10
|
+
InsightScanContext,
|
|
11
|
+
} from "../Types";
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* MetricDrift — a metric's mean over the last 7 days drifted substantially
|
|
15
|
+
* from its mean over the prior 7 days, per (metric name, entity) cell. The
|
|
16
|
+
* data comes from two GROUP BY finalization queries over the
|
|
17
|
+
* MetricBaselineHourly materialized view (already maintained for anomaly
|
|
18
|
+
* monitors — this detector adds no write load); the recent/prior join and
|
|
19
|
+
* the drift decision are pure functions here so they are unit-testable
|
|
20
|
+
* without any ClickHouse.
|
|
21
|
+
*
|
|
22
|
+
* Drift severity is always Low and NEVER routes to an auto-fix: direction
|
|
23
|
+
* and goodness are unknowable without semantics (a 60% drop in latency is
|
|
24
|
+
* a win; a 60% drop in throughput is an outage). It is a "look here"
|
|
25
|
+
* signal, nothing more. Deterministic — no LLM anywhere in this detector.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
* Both windows need this many raw samples per cell before their means are
|
|
30
|
+
* comparable — below it a single noisy hour can swing the mean by more
|
|
31
|
+
* than the drift threshold.
|
|
32
|
+
*/
|
|
33
|
+
export const METRIC_DRIFT_MIN_SAMPLES_PER_WINDOW: number = 100;
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
* Relative mean change (|recent-prior| / |prior|) that counts as drift.
|
|
37
|
+
* 50% is far outside normal week-to-week variation for the sample-count-
|
|
38
|
+
* gated cells, so the inbox only sees step changes.
|
|
39
|
+
*/
|
|
40
|
+
export const METRIC_DRIFT_MIN_RELATIVE_CHANGE: number = 0.5;
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* At most this many drift insights per scan tick, ranked by |relative
|
|
44
|
+
* change|. A platform-wide shift moves hundreds of metrics at once — the
|
|
45
|
+
* top movers tell the story, the rest are echoes.
|
|
46
|
+
*/
|
|
47
|
+
export const METRIC_DRIFT_MAX_INSIGHTS: number = 5;
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
* Rows fetched per drift window (recent/prior), ranked by sample count.
|
|
51
|
+
* Bounded because the detector joins the windows in JS. Mirrors
|
|
52
|
+
* MetricBaselineService.DRIFT_MAX_ROWS_PER_WINDOW — the service clamps to
|
|
53
|
+
* that cap regardless.
|
|
54
|
+
*/
|
|
55
|
+
export const METRIC_DRIFT_ROWS_PER_WINDOW: number =
|
|
56
|
+
MetricBaselineServiceClass.DRIFT_MAX_ROWS_PER_WINDOW;
|
|
57
|
+
|
|
58
|
+
// One joined-and-qualified drift finding, ready to become an insight.
|
|
59
|
+
export interface MetricDriftFinding {
|
|
60
|
+
metricName: string;
|
|
61
|
+
primaryEntityId: string;
|
|
62
|
+
recentMean: number;
|
|
63
|
+
priorMean: number;
|
|
64
|
+
// Signed: (recent - prior) / |prior|. Positive = the mean went up.
|
|
65
|
+
relativeChange: number;
|
|
66
|
+
recentSampleCount: number;
|
|
67
|
+
priorSampleCount: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default class MetricDriftDetector implements InsightDetector {
|
|
71
|
+
public insightType: AIInsightType = AIInsightType.MetricDrift;
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* Pure join + decision: pair each (name, entity) cell's recent and
|
|
75
|
+
* prior rows, gate on sample counts, and keep cells whose relative mean
|
|
76
|
+
* change clears the threshold. Cells with a zero prior mean are skipped
|
|
77
|
+
* — relative change against a zero baseline is undefined, and
|
|
78
|
+
* "metric appeared" is NewException/ErrorLogSpike territory, not drift.
|
|
79
|
+
* Returns the top METRIC_DRIFT_MAX_INSIGHTS movers by |relative change|.
|
|
80
|
+
*/
|
|
81
|
+
public static evaluateDrift(
|
|
82
|
+
rows: Array<MetricDriftWindowRow>,
|
|
83
|
+
): Array<MetricDriftFinding> {
|
|
84
|
+
const recentByCell: Map<string, MetricDriftWindowRow> = new Map();
|
|
85
|
+
const priorByCell: Map<string, MetricDriftWindowRow> = new Map();
|
|
86
|
+
|
|
87
|
+
for (const row of rows) {
|
|
88
|
+
// \u0000 cannot appear in either component — collision-free key.
|
|
89
|
+
const cellKey: string = `${row.name}\u0000${row.primaryEntityId}`;
|
|
90
|
+
if (row.window === "recent") {
|
|
91
|
+
recentByCell.set(cellKey, row);
|
|
92
|
+
} else {
|
|
93
|
+
priorByCell.set(cellKey, row);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const findings: Array<MetricDriftFinding> = [];
|
|
98
|
+
|
|
99
|
+
for (const [cellKey, recent] of recentByCell) {
|
|
100
|
+
const prior: MetricDriftWindowRow | undefined = priorByCell.get(cellKey);
|
|
101
|
+
if (!prior) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (
|
|
105
|
+
recent.sampleCount < METRIC_DRIFT_MIN_SAMPLES_PER_WINDOW ||
|
|
106
|
+
prior.sampleCount < METRIC_DRIFT_MIN_SAMPLES_PER_WINDOW
|
|
107
|
+
) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (prior.mean === 0) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const relativeChange: number =
|
|
115
|
+
(recent.mean - prior.mean) / Math.abs(prior.mean);
|
|
116
|
+
|
|
117
|
+
if (Math.abs(relativeChange) < METRIC_DRIFT_MIN_RELATIVE_CHANGE) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
findings.push({
|
|
122
|
+
metricName: recent.name,
|
|
123
|
+
primaryEntityId: recent.primaryEntityId,
|
|
124
|
+
recentMean: recent.mean,
|
|
125
|
+
priorMean: prior.mean,
|
|
126
|
+
relativeChange,
|
|
127
|
+
recentSampleCount: recent.sampleCount,
|
|
128
|
+
priorSampleCount: prior.sampleCount,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
findings.sort((a: MetricDriftFinding, b: MetricDriftFinding): number => {
|
|
133
|
+
if (Math.abs(b.relativeChange) !== Math.abs(a.relativeChange)) {
|
|
134
|
+
return Math.abs(b.relativeChange) - Math.abs(a.relativeChange);
|
|
135
|
+
}
|
|
136
|
+
// Deterministic tie-break so scan ticks are reproducible.
|
|
137
|
+
const aKey: string = `${a.metricName}\u0000${a.primaryEntityId}`;
|
|
138
|
+
const bKey: string = `${b.metricName}\u0000${b.primaryEntityId}`;
|
|
139
|
+
return aKey.localeCompare(bKey);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return findings.slice(0, METRIC_DRIFT_MAX_INSIGHTS);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Signed percent label, e.g. "+62%" / "-71%".
|
|
146
|
+
public static formatChangePercent(relativeChange: number): string {
|
|
147
|
+
const percent: number = Math.round(relativeChange * 100);
|
|
148
|
+
return `${percent >= 0 ? "+" : ""}${percent}%`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Stable dedupe key per (metric name, entity) cell.
|
|
152
|
+
public static buildFingerprint(
|
|
153
|
+
metricName: string,
|
|
154
|
+
primaryEntityId: string,
|
|
155
|
+
): string {
|
|
156
|
+
return `metric-drift:${metricName}:${primaryEntityId}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public async detect(
|
|
160
|
+
context: InsightScanContext,
|
|
161
|
+
): Promise<Array<InsightCandidate>> {
|
|
162
|
+
const rows: Array<MetricDriftWindowRow> =
|
|
163
|
+
await MetricBaselineService.getWeekOverWeekDrift({
|
|
164
|
+
projectId: context.projectId,
|
|
165
|
+
limitPerWindow: METRIC_DRIFT_ROWS_PER_WINDOW,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const findings: Array<MetricDriftFinding> =
|
|
169
|
+
MetricDriftDetector.evaluateDrift(rows);
|
|
170
|
+
|
|
171
|
+
return findings.map((finding: MetricDriftFinding): InsightCandidate => {
|
|
172
|
+
const changeLabel: string = MetricDriftDetector.formatChangePercent(
|
|
173
|
+
finding.relativeChange,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const detailLines: Array<string> = [
|
|
177
|
+
"**Metric drift detected (week-over-week)**",
|
|
178
|
+
"",
|
|
179
|
+
`- Metric: \`${finding.metricName}\``,
|
|
180
|
+
];
|
|
181
|
+
if (finding.primaryEntityId) {
|
|
182
|
+
detailLines.push(`- Entity: \`${finding.primaryEntityId}\``);
|
|
183
|
+
}
|
|
184
|
+
detailLines.push(
|
|
185
|
+
`- Recent 7-day mean: ${finding.recentMean.toFixed(4)} (${finding.recentSampleCount} samples)`,
|
|
186
|
+
`- Prior 7-day mean: ${finding.priorMean.toFixed(4)} (${finding.priorSampleCount} samples)`,
|
|
187
|
+
`- Relative change: ${changeLabel}`,
|
|
188
|
+
"",
|
|
189
|
+
"Direction and goodness are metric-specific — this is a heads-up, not an alarm.",
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
insightType: AIInsightType.MetricDrift,
|
|
194
|
+
fingerprint: MetricDriftDetector.buildFingerprint(
|
|
195
|
+
finding.metricName,
|
|
196
|
+
finding.primaryEntityId,
|
|
197
|
+
),
|
|
198
|
+
title: `Metric drift: ${finding.metricName} ${changeLabel} week-over-week`,
|
|
199
|
+
detailMarkdown: detailLines.join("\n"),
|
|
200
|
+
/*
|
|
201
|
+
* Always Low: without metric semantics the detector cannot know
|
|
202
|
+
* whether the drift is good or bad — it must never outrank a
|
|
203
|
+
* concrete exception or latency finding.
|
|
204
|
+
*/
|
|
205
|
+
severity: AIInsightSeverity.Low,
|
|
206
|
+
metricName: finding.metricName,
|
|
207
|
+
evidence: {
|
|
208
|
+
metricDrift: {
|
|
209
|
+
metricName: finding.metricName,
|
|
210
|
+
primaryEntityId: finding.primaryEntityId || undefined,
|
|
211
|
+
recentWeekMean: finding.recentMean,
|
|
212
|
+
priorWeekMean: finding.priorMean,
|
|
213
|
+
relativeChangePercent: finding.relativeChange * 100,
|
|
214
|
+
recentSampleCount: finding.recentSampleCount,
|
|
215
|
+
priorSampleCount: finding.priorSampleCount,
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|