@oneuptime/common 11.5.4 → 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/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/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 +2 -1
- 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/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/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/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.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,322 @@
|
|
|
1
|
+
import TelemetryExceptionService from "../../../Server/Services/TelemetryExceptionService";
|
|
2
|
+
import FixRunBudget from "../../../Server/Utils/AI/CodeFix/FixRunBudget";
|
|
3
|
+
import LlmProviderService from "../../../Server/Services/LlmProviderService";
|
|
4
|
+
import ServiceService from "../../../Server/Services/ServiceService";
|
|
5
|
+
import CodeRepositoryService from "../../../Server/Services/CodeRepositoryService";
|
|
6
|
+
import AIAgentService from "../../../Server/Services/AIAgentService";
|
|
7
|
+
import AIRunService from "../../../Server/Services/AIRunService";
|
|
8
|
+
import { RepoResolution } from "../../../Server/Utils/CodeRepository/StackTraceRepoResolver";
|
|
9
|
+
import FindOneBy from "../../../Server/Types/Database/FindOneBy";
|
|
10
|
+
import TelemetryException from "../../../Models/DatabaseModels/TelemetryException";
|
|
11
|
+
import TelemetryService from "../../../Models/DatabaseModels/Service";
|
|
12
|
+
import LlmProvider from "../../../Models/DatabaseModels/LlmProvider";
|
|
13
|
+
import AIRun from "../../../Models/DatabaseModels/AIRun";
|
|
14
|
+
import AIAgent, {
|
|
15
|
+
AIAgentConnectionStatus,
|
|
16
|
+
} from "../../../Models/DatabaseModels/AIAgent";
|
|
17
|
+
import AIRunType from "../../../Types/AI/AIRunType";
|
|
18
|
+
import AIRunStatus from "../../../Types/AI/AIRunStatus";
|
|
19
|
+
import CodeFixTaskType from "../../../Types/AI/CodeFixTaskType";
|
|
20
|
+
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
21
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
22
|
+
import { describe, expect, test, afterEach, beforeEach } from "@jest/globals";
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* "Fix with AI Agent" on the AIRun substrate: creation records a Queued
|
|
26
|
+
* CodeFix run carrying triggeredByTelemetryExceptionId (the link table is
|
|
27
|
+
* gone) and the task recipe (codeFixTaskType), and the duplicate guard
|
|
28
|
+
* blocks a second run of the SAME recipe while one is still in a
|
|
29
|
+
* non-terminal status — per (exception, taskType), so a live FixException
|
|
30
|
+
* run does not block queuing a WriteRegressionTest run and vice versa.
|
|
31
|
+
* Recipes that are declared but not yet user-triggerable are rejected
|
|
32
|
+
* before any run is created.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
36
|
+
const exceptionId: ObjectID = ObjectID.generate();
|
|
37
|
+
const serviceId: ObjectID = ObjectID.generate();
|
|
38
|
+
|
|
39
|
+
function fakeException(): TelemetryException {
|
|
40
|
+
return {
|
|
41
|
+
id: exceptionId,
|
|
42
|
+
projectId: projectId,
|
|
43
|
+
primaryEntityId: serviceId,
|
|
44
|
+
stackTrace: "at charge (/app/src/billing/charge.ts:12:5)",
|
|
45
|
+
} as unknown as TelemetryException;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function fakeResolution(): RepoResolution {
|
|
49
|
+
return {
|
|
50
|
+
codeRepositoryId: ObjectID.generate().toString(),
|
|
51
|
+
organizationName: "acme",
|
|
52
|
+
repositoryName: "checkout",
|
|
53
|
+
servicePathInRepository: null,
|
|
54
|
+
method: "stack-trace",
|
|
55
|
+
evidence: "Matched src/billing/charge.ts in acme/checkout",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// All three readiness checks pass; run creation is gated only by the guard.
|
|
60
|
+
function mockReadinessOk(): void {
|
|
61
|
+
jest
|
|
62
|
+
.spyOn(TelemetryExceptionService, "findOneById")
|
|
63
|
+
.mockResolvedValue(fakeException());
|
|
64
|
+
jest
|
|
65
|
+
.spyOn(LlmProviderService, "getLlmProviderForMeteredAgentPath")
|
|
66
|
+
.mockResolvedValue({
|
|
67
|
+
id: ObjectID.generate(),
|
|
68
|
+
name: "BYO",
|
|
69
|
+
} as unknown as LlmProvider);
|
|
70
|
+
jest.spyOn(ServiceService, "findOneById").mockResolvedValue({
|
|
71
|
+
id: serviceId,
|
|
72
|
+
name: "checkout",
|
|
73
|
+
} as unknown as TelemetryService);
|
|
74
|
+
jest
|
|
75
|
+
.spyOn(CodeRepositoryService, "resolveRepositoryForException")
|
|
76
|
+
.mockResolvedValue(fakeResolution());
|
|
77
|
+
jest.spyOn(AIAgentService, "getAIAgentForProject").mockResolvedValue({
|
|
78
|
+
id: ObjectID.generate(),
|
|
79
|
+
name: "agent",
|
|
80
|
+
connectionStatus: AIAgentConnectionStatus.Connected,
|
|
81
|
+
} as unknown as AIAgent);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
describe("TelemetryExceptionService.createCodeFixRunForException", () => {
|
|
85
|
+
beforeEach(() => {
|
|
86
|
+
// The daily fix-run budget has its own suite (FixRunBudget.test.ts).
|
|
87
|
+
jest.spyOn(FixRunBudget, "assertWithinBudget").mockResolvedValue();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
afterEach(() => {
|
|
91
|
+
jest.restoreAllMocks();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("records a Queued CodeFix AIRun carrying the triggering exception", async () => {
|
|
95
|
+
mockReadinessOk();
|
|
96
|
+
|
|
97
|
+
// Duplicate guard finds nothing.
|
|
98
|
+
jest.spyOn(AIRunService, "findOneBy").mockResolvedValue(null);
|
|
99
|
+
const createdId: ObjectID = ObjectID.generate();
|
|
100
|
+
const create: jest.SpyInstance = jest
|
|
101
|
+
.spyOn(AIRunService, "create")
|
|
102
|
+
.mockResolvedValue({ id: createdId } as unknown as AIRun);
|
|
103
|
+
|
|
104
|
+
const run: AIRun =
|
|
105
|
+
await TelemetryExceptionService.createCodeFixRunForException({
|
|
106
|
+
telemetryExceptionId: exceptionId,
|
|
107
|
+
props: { isRoot: true },
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(run.id).toBe(createdId);
|
|
111
|
+
expect(create).toHaveBeenCalledWith(
|
|
112
|
+
expect.objectContaining({
|
|
113
|
+
data: expect.objectContaining({
|
|
114
|
+
projectId: projectId,
|
|
115
|
+
runType: AIRunType.CodeFix,
|
|
116
|
+
status: AIRunStatus.Queued,
|
|
117
|
+
triggeredByTelemetryExceptionId: exceptionId,
|
|
118
|
+
// New rows are stamped explicitly; only legacy rows are null.
|
|
119
|
+
codeFixTaskType: CodeFixTaskType.FixException,
|
|
120
|
+
}),
|
|
121
|
+
props: expect.objectContaining({ isRoot: true }),
|
|
122
|
+
}),
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("over the daily fix-run budget: rejects BEFORE the readiness probes, nothing created", async () => {
|
|
127
|
+
mockReadinessOk();
|
|
128
|
+
|
|
129
|
+
jest
|
|
130
|
+
.spyOn(FixRunBudget, "assertWithinBudget")
|
|
131
|
+
.mockRejectedValue(
|
|
132
|
+
new BadDataException(
|
|
133
|
+
"The project's daily AI fix task limit has been reached",
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
const readinessProbe: jest.SpyInstance = jest.spyOn(
|
|
137
|
+
LlmProviderService,
|
|
138
|
+
"getLlmProviderForMeteredAgentPath",
|
|
139
|
+
);
|
|
140
|
+
const create: jest.SpyInstance = jest.spyOn(AIRunService, "create");
|
|
141
|
+
|
|
142
|
+
await expect(
|
|
143
|
+
TelemetryExceptionService.createCodeFixRunForException({
|
|
144
|
+
telemetryExceptionId: exceptionId,
|
|
145
|
+
props: { isRoot: true },
|
|
146
|
+
}),
|
|
147
|
+
).rejects.toThrow(/daily AI fix task limit/);
|
|
148
|
+
|
|
149
|
+
// Budget is the cheaper gate — the readiness checks never ran.
|
|
150
|
+
expect(readinessProbe).not.toHaveBeenCalled();
|
|
151
|
+
expect(create).not.toHaveBeenCalled();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("duplicate guard: an active (non-terminal) run for the exception blocks creation", async () => {
|
|
155
|
+
mockReadinessOk();
|
|
156
|
+
|
|
157
|
+
const findActiveRun: jest.SpyInstance = jest
|
|
158
|
+
.spyOn(AIRunService, "findOneBy")
|
|
159
|
+
.mockResolvedValue({ id: ObjectID.generate() } as unknown as AIRun);
|
|
160
|
+
const create: jest.SpyInstance = jest.spyOn(AIRunService, "create");
|
|
161
|
+
|
|
162
|
+
await expect(
|
|
163
|
+
TelemetryExceptionService.createCodeFixRunForException({
|
|
164
|
+
telemetryExceptionId: exceptionId,
|
|
165
|
+
props: { isRoot: true },
|
|
166
|
+
}),
|
|
167
|
+
).rejects.toThrow(/already in progress/);
|
|
168
|
+
|
|
169
|
+
expect(create).not.toHaveBeenCalled();
|
|
170
|
+
// The guard queries by run type + triggering exception, not a link table.
|
|
171
|
+
expect(findActiveRun).toHaveBeenCalledWith(
|
|
172
|
+
expect.objectContaining({
|
|
173
|
+
query: expect.objectContaining({
|
|
174
|
+
runType: AIRunType.CodeFix,
|
|
175
|
+
triggeredByTelemetryExceptionId: exceptionId,
|
|
176
|
+
}),
|
|
177
|
+
}),
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("duplicate guard is per task type: an active FixException run blocks another FixException but not a WriteRegressionTest", async () => {
|
|
182
|
+
mockReadinessOk();
|
|
183
|
+
|
|
184
|
+
/*
|
|
185
|
+
* The guard queries codeFixTaskType per recipe: WriteRegressionTest as
|
|
186
|
+
* the plain enum value, FixException as a null-inclusive operator
|
|
187
|
+
* (legacy rows predate the column). Simulate a live FixException run
|
|
188
|
+
* and nothing else.
|
|
189
|
+
*/
|
|
190
|
+
jest
|
|
191
|
+
.spyOn(AIRunService, "findOneBy")
|
|
192
|
+
.mockImplementation(
|
|
193
|
+
async (findOneBy: FindOneBy<AIRun>): Promise<AIRun | null> => {
|
|
194
|
+
if (
|
|
195
|
+
findOneBy.query.codeFixTaskType ===
|
|
196
|
+
CodeFixTaskType.WriteRegressionTest
|
|
197
|
+
) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return { id: ObjectID.generate() } as unknown as AIRun;
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const create: jest.SpyInstance = jest
|
|
206
|
+
.spyOn(AIRunService, "create")
|
|
207
|
+
.mockResolvedValue({ id: ObjectID.generate() } as unknown as AIRun);
|
|
208
|
+
|
|
209
|
+
// The same recipe is blocked while its run is live...
|
|
210
|
+
await expect(
|
|
211
|
+
TelemetryExceptionService.createCodeFixRunForException({
|
|
212
|
+
telemetryExceptionId: exceptionId,
|
|
213
|
+
props: { isRoot: true },
|
|
214
|
+
taskType: CodeFixTaskType.FixException,
|
|
215
|
+
}),
|
|
216
|
+
).rejects.toThrow(/already in progress/);
|
|
217
|
+
expect(create).not.toHaveBeenCalled();
|
|
218
|
+
|
|
219
|
+
// ...but a different recipe for the same exception is not.
|
|
220
|
+
await expect(
|
|
221
|
+
TelemetryExceptionService.createCodeFixRunForException({
|
|
222
|
+
telemetryExceptionId: exceptionId,
|
|
223
|
+
props: { isRoot: true },
|
|
224
|
+
taskType: CodeFixTaskType.WriteRegressionTest,
|
|
225
|
+
}),
|
|
226
|
+
).resolves.toBeDefined();
|
|
227
|
+
expect(create).toHaveBeenCalledWith(
|
|
228
|
+
expect.objectContaining({
|
|
229
|
+
data: expect.objectContaining({
|
|
230
|
+
codeFixTaskType: CodeFixTaskType.WriteRegressionTest,
|
|
231
|
+
triggeredByTelemetryExceptionId: exceptionId,
|
|
232
|
+
}),
|
|
233
|
+
}),
|
|
234
|
+
);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
test("rejects task recipes that are not user-triggerable yet, before touching anything", async () => {
|
|
238
|
+
const findOneBy: jest.SpyInstance = jest.spyOn(AIRunService, "findOneBy");
|
|
239
|
+
const create: jest.SpyInstance = jest.spyOn(AIRunService, "create");
|
|
240
|
+
|
|
241
|
+
await expect(
|
|
242
|
+
TelemetryExceptionService.createCodeFixRunForException({
|
|
243
|
+
telemetryExceptionId: exceptionId,
|
|
244
|
+
props: { isRoot: true },
|
|
245
|
+
taskType: CodeFixTaskType.ImproveInstrumentation,
|
|
246
|
+
}),
|
|
247
|
+
).rejects.toThrow(/not user-triggerable yet/);
|
|
248
|
+
|
|
249
|
+
expect(findOneBy).not.toHaveBeenCalled();
|
|
250
|
+
expect(create).not.toHaveBeenCalled();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("attributes the run to the requesting user when one is present", async () => {
|
|
254
|
+
mockReadinessOk();
|
|
255
|
+
|
|
256
|
+
jest.spyOn(AIRunService, "findOneBy").mockResolvedValue(null);
|
|
257
|
+
const create: jest.SpyInstance = jest
|
|
258
|
+
.spyOn(AIRunService, "create")
|
|
259
|
+
.mockResolvedValue({ id: ObjectID.generate() } as unknown as AIRun);
|
|
260
|
+
|
|
261
|
+
const userId: ObjectID = ObjectID.generate();
|
|
262
|
+
|
|
263
|
+
await TelemetryExceptionService.createCodeFixRunForException({
|
|
264
|
+
telemetryExceptionId: exceptionId,
|
|
265
|
+
props: { isRoot: true, userId },
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
expect(create).toHaveBeenCalledWith(
|
|
269
|
+
expect.objectContaining({
|
|
270
|
+
data: expect.objectContaining({ userId }),
|
|
271
|
+
}),
|
|
272
|
+
);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
/*
|
|
277
|
+
* The worker dispatches its task handler on the claimed run's taskType
|
|
278
|
+
* (POST /ai-agent-task/get-pending-task), so the claim must normalize the
|
|
279
|
+
* legacy null column to FixException before the run leaves the service.
|
|
280
|
+
*/
|
|
281
|
+
describe("AIRunService.claimNextQueuedCodeFixRun task recipe", () => {
|
|
282
|
+
afterEach(() => {
|
|
283
|
+
jest.restoreAllMocks();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
function fakeQueuedRun(codeFixTaskType?: CodeFixTaskType): AIRun {
|
|
287
|
+
return {
|
|
288
|
+
id: ObjectID.generate(),
|
|
289
|
+
projectId: projectId,
|
|
290
|
+
triggeredByTelemetryExceptionId: exceptionId,
|
|
291
|
+
attemptCount: 0,
|
|
292
|
+
codeFixTaskType: codeFixTaskType,
|
|
293
|
+
} as unknown as AIRun;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
test("a claimed legacy run (null codeFixTaskType) carries FixException", async () => {
|
|
297
|
+
jest
|
|
298
|
+
.spyOn(AIRunService, "findOneBy")
|
|
299
|
+
.mockResolvedValue(fakeQueuedRun(undefined));
|
|
300
|
+
jest.spyOn(AIRunService, "attemptStatusTransition").mockResolvedValue(1);
|
|
301
|
+
|
|
302
|
+
const claimed: AIRun | null = await AIRunService.claimNextQueuedCodeFixRun({
|
|
303
|
+
aiAgentId: ObjectID.generate(),
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
expect(claimed).not.toBeNull();
|
|
307
|
+
expect(claimed?.codeFixTaskType).toBe(CodeFixTaskType.FixException);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
test("a claimed run keeps its explicit task recipe", async () => {
|
|
311
|
+
jest
|
|
312
|
+
.spyOn(AIRunService, "findOneBy")
|
|
313
|
+
.mockResolvedValue(fakeQueuedRun(CodeFixTaskType.WriteRegressionTest));
|
|
314
|
+
jest.spyOn(AIRunService, "attemptStatusTransition").mockResolvedValue(1);
|
|
315
|
+
|
|
316
|
+
const claimed: AIRun | null = await AIRunService.claimNextQueuedCodeFixRun({
|
|
317
|
+
aiAgentId: ObjectID.generate(),
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
expect(claimed?.codeFixTaskType).toBe(CodeFixTaskType.WriteRegressionTest);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import TraceAggregationService, {
|
|
2
|
+
ServiceLatencyProfile,
|
|
3
|
+
} from "../../../Server/Services/TraceAggregationService";
|
|
4
|
+
import SpanService from "../../../Server/Services/SpanService";
|
|
5
|
+
import { Results } from "../../../Server/Services/AnalyticsDatabaseService";
|
|
6
|
+
import { Statement } from "../../../Server/Utils/AnalyticsDatabase/Statement";
|
|
7
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
8
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
9
|
+
import { afterEach, describe, expect, test } from "@jest/globals";
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* getServiceLatencyProfile is the ONLY query the unattended insight scanner
|
|
13
|
+
* runs against the full Span table every 15 minutes for every opted-in
|
|
14
|
+
* project. It is affordable exactly and only while ClickHouse can serve it
|
|
15
|
+
* from the proj_agg_by_service aggregate projection
|
|
16
|
+
* (projectId, primaryEntityId, toStartOfMinute(startTime) -> count() /
|
|
17
|
+
* avg(durationUnixNano) / quantile(0.99)(durationUnixNano)).
|
|
18
|
+
*
|
|
19
|
+
* The projection match is a BYTE-MATCH on the aggregate expressions and the
|
|
20
|
+
* key expression: fold a `/ 1000000` into the quantile, compare raw
|
|
21
|
+
* startTime instead of toStartOfMinute(startTime), add the retentionDate
|
|
22
|
+
* filter or group by anything outside the projection's keys, and ClickHouse
|
|
23
|
+
* silently reverts to a 25-hour raw-span scan — which then trips the
|
|
24
|
+
* execution cap and returns partial aggregates. Nothing in the query plan is
|
|
25
|
+
* observable from TypeScript, so these SQL-shape assertions are the guard.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
29
|
+
const startTime: Date = new Date("2026-07-14T11:00:00.000Z");
|
|
30
|
+
const endTime: Date = new Date("2026-07-14T12:00:00.000Z");
|
|
31
|
+
|
|
32
|
+
const stubQuery: (response: {
|
|
33
|
+
rows?: Array<JSONObject>;
|
|
34
|
+
elapsedSeconds?: number;
|
|
35
|
+
throwOnParse?: boolean;
|
|
36
|
+
}) => jest.SpyInstance = (response: {
|
|
37
|
+
rows?: Array<JSONObject>;
|
|
38
|
+
elapsedSeconds?: number;
|
|
39
|
+
throwOnParse?: boolean;
|
|
40
|
+
}): jest.SpyInstance => {
|
|
41
|
+
const fakeResult: Results = {
|
|
42
|
+
json: (): Promise<unknown> => {
|
|
43
|
+
if (response.throwOnParse) {
|
|
44
|
+
return Promise.reject(new Error("Unexpected end of JSON input"));
|
|
45
|
+
}
|
|
46
|
+
return Promise.resolve({
|
|
47
|
+
data: response.rows || [],
|
|
48
|
+
statistics: {
|
|
49
|
+
elapsed: response.elapsedSeconds ?? 0.004,
|
|
50
|
+
rows_read: 10,
|
|
51
|
+
bytes_read: 100,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
} as unknown as Results;
|
|
56
|
+
|
|
57
|
+
return jest
|
|
58
|
+
.spyOn(SpanService, "executeQuery")
|
|
59
|
+
.mockResolvedValue(fakeResult as never);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const capturedQuery: (spy: jest.SpyInstance) => string = (
|
|
63
|
+
spy: jest.SpyInstance,
|
|
64
|
+
): string => {
|
|
65
|
+
const statement: Statement = spy.mock.calls[0]![0] as Statement;
|
|
66
|
+
// The query getter dedents — normalize whitespace before matching SQL.
|
|
67
|
+
return statement.query.replace(/\s+/g, " ");
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
describe("TraceAggregationService.getServiceLatencyProfile (projection-served SQL shape)", () => {
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
jest.restoreAllMocks();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("selects ONLY the aggregates proj_agg_by_service stores, byte-for-byte", async () => {
|
|
76
|
+
const spy: jest.SpyInstance = stubQuery({ rows: [] });
|
|
77
|
+
|
|
78
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
79
|
+
projectId,
|
|
80
|
+
startTime,
|
|
81
|
+
endTime,
|
|
82
|
+
limit: 25,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const query: string = capturedQuery(spy);
|
|
86
|
+
|
|
87
|
+
expect(query).toContain("count() AS cnt");
|
|
88
|
+
expect(query).toContain("quantile(0.99)(durationUnixNano) AS p99_ns");
|
|
89
|
+
|
|
90
|
+
/*
|
|
91
|
+
* The ns->ms division MUST stay in TypeScript: `quantile(0.99)(x) /
|
|
92
|
+
* 1000000` is not the stored expression, so it disqualifies the
|
|
93
|
+
* projection.
|
|
94
|
+
*/
|
|
95
|
+
expect(query).not.toContain("1000000");
|
|
96
|
+
|
|
97
|
+
// Every other stat in getAnalyticsTable's set has no stored state.
|
|
98
|
+
expect(query).not.toContain("countIf");
|
|
99
|
+
expect(query).not.toContain("quantile(0.95)");
|
|
100
|
+
expect(query).not.toContain("quantile(0.9)(");
|
|
101
|
+
expect(query).not.toContain("quantile(0.5)");
|
|
102
|
+
expect(query).not.toContain("min(durationUnixNano)");
|
|
103
|
+
expect(query).not.toContain("max(durationUnixNano)");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("filters on the projection key expression, never raw startTime, and never retentionDate", async () => {
|
|
107
|
+
const spy: jest.SpyInstance = stubQuery({ rows: [] });
|
|
108
|
+
|
|
109
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
110
|
+
projectId,
|
|
111
|
+
startTime,
|
|
112
|
+
endTime,
|
|
113
|
+
limit: 25,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const query: string = capturedQuery(spy);
|
|
117
|
+
|
|
118
|
+
expect(query).toContain("toStartOfMinute(startTime) >= toStartOfMinute(");
|
|
119
|
+
// Half-open: the boundary minute must not be counted in both windows.
|
|
120
|
+
expect(query).toContain("toStartOfMinute(startTime) < toStartOfMinute(");
|
|
121
|
+
|
|
122
|
+
// A bare `startTime <op>` comparison would reject the projection.
|
|
123
|
+
expect(query).not.toMatch(/startTime\s*(>=|<=|>|<)/);
|
|
124
|
+
|
|
125
|
+
// retentionDate is not stored by the aggregate projection.
|
|
126
|
+
expect(query).not.toContain("retentionDate");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("groups by a subset of the projection keys and caps the row count", async () => {
|
|
130
|
+
const spy: jest.SpyInstance = stubQuery({ rows: [] });
|
|
131
|
+
|
|
132
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
133
|
+
projectId,
|
|
134
|
+
startTime,
|
|
135
|
+
endTime,
|
|
136
|
+
limit: 25,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const query: string = capturedQuery(spy);
|
|
140
|
+
|
|
141
|
+
/*
|
|
142
|
+
* primaryEntityId only — dropping the `minute` key merges the stored
|
|
143
|
+
* per-minute aggregate states into a whole-window value. Any dimension
|
|
144
|
+
* outside (projectId, primaryEntityId, minute) forces a full scan.
|
|
145
|
+
*/
|
|
146
|
+
expect(query).toContain("GROUP BY primaryEntityId ORDER BY cnt DESC LIMIT");
|
|
147
|
+
expect(query).not.toContain("statusCode");
|
|
148
|
+
expect(query).not.toContain("attributes[");
|
|
149
|
+
|
|
150
|
+
const statement: Statement = spy.mock.calls[0]![0] as Statement;
|
|
151
|
+
expect(Object.values(statement.query_params)).toContain(25);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("caps execution at 45s and explicitly enables projections", async () => {
|
|
155
|
+
const spy: jest.SpyInstance = stubQuery({ rows: [] });
|
|
156
|
+
|
|
157
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
158
|
+
projectId,
|
|
159
|
+
startTime,
|
|
160
|
+
endTime,
|
|
161
|
+
limit: 25,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const query: string = capturedQuery(spy);
|
|
165
|
+
|
|
166
|
+
expect(query).toContain("max_execution_time = 45");
|
|
167
|
+
expect(query).toContain("timeout_overflow_mode = 'break'");
|
|
168
|
+
expect(query).toContain("optimize_use_projections = 1");
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("converts ns to ms in TS and drops rows without an entity id", async () => {
|
|
172
|
+
stubQuery({
|
|
173
|
+
rows: [
|
|
174
|
+
{ primaryEntityId: "svc-1", cnt: "500", p99_ns: "2300000000" },
|
|
175
|
+
{ primaryEntityId: "", cnt: "9", p99_ns: "1000000" },
|
|
176
|
+
],
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const result: ServiceLatencyProfile =
|
|
180
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
181
|
+
projectId,
|
|
182
|
+
startTime,
|
|
183
|
+
endTime,
|
|
184
|
+
limit: 25,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(result.rows).toEqual([
|
|
188
|
+
{ primaryEntityId: "svc-1", count: 500, p99DurationMs: 2300 },
|
|
189
|
+
]);
|
|
190
|
+
expect(result.isPartial).toBe(false);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
/*
|
|
195
|
+
* With timeout_overflow_mode='break' a cut-off query returns a well-formed
|
|
196
|
+
* body holding PARTIAL aggregates — no exception, no marker. The insight
|
|
197
|
+
* scanner compares two windows, so partial data is not "less data", it is a
|
|
198
|
+
* wrong p99. `statistics.elapsed` at the cap is the only available signal
|
|
199
|
+
* that this happened, and the caller is contractually required to discard
|
|
200
|
+
* the tick when it is set.
|
|
201
|
+
*/
|
|
202
|
+
describe("TraceAggregationService.getServiceLatencyProfile (partial-result detection)", () => {
|
|
203
|
+
afterEach(() => {
|
|
204
|
+
jest.restoreAllMocks();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("a query that burned its whole execution budget is reported as partial", async () => {
|
|
208
|
+
stubQuery({
|
|
209
|
+
rows: [{ primaryEntityId: "svc-1", cnt: "500", p99_ns: "2300000000" }],
|
|
210
|
+
elapsedSeconds: 45,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const result: ServiceLatencyProfile =
|
|
214
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
215
|
+
projectId,
|
|
216
|
+
startTime,
|
|
217
|
+
endTime,
|
|
218
|
+
limit: 25,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
expect(result.isPartial).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("break fires slightly before the cap — 90% of the budget already counts as partial", async () => {
|
|
225
|
+
stubQuery({
|
|
226
|
+
rows: [{ primaryEntityId: "svc-1", cnt: "500", p99_ns: "2300000000" }],
|
|
227
|
+
elapsedSeconds: 40.5,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const result: ServiceLatencyProfile =
|
|
231
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
232
|
+
projectId,
|
|
233
|
+
startTime,
|
|
234
|
+
endTime,
|
|
235
|
+
limit: 25,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
expect(result.isPartial).toBe(true);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("a fast projection-served query is complete", async () => {
|
|
242
|
+
stubQuery({
|
|
243
|
+
rows: [{ primaryEntityId: "svc-1", cnt: "500", p99_ns: "2300000000" }],
|
|
244
|
+
elapsedSeconds: 0.006,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const result: ServiceLatencyProfile =
|
|
248
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
249
|
+
projectId,
|
|
250
|
+
startTime,
|
|
251
|
+
endTime,
|
|
252
|
+
limit: 25,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
expect(result.isPartial).toBe(false);
|
|
256
|
+
expect(result.rows).toHaveLength(1);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
/*
|
|
260
|
+
* 'break' can also truncate the JSON body outright. An unparseable body is
|
|
261
|
+
* partial — NOT an empty profile, which the caller would read as "this
|
|
262
|
+
* project has no traffic".
|
|
263
|
+
*/
|
|
264
|
+
test("an unparseable (truncated) response is partial, not empty-and-trusted", async () => {
|
|
265
|
+
stubQuery({ throwOnParse: true });
|
|
266
|
+
|
|
267
|
+
const result: ServiceLatencyProfile =
|
|
268
|
+
await TraceAggregationService.getServiceLatencyProfile({
|
|
269
|
+
projectId,
|
|
270
|
+
startTime,
|
|
271
|
+
endTime,
|
|
272
|
+
limit: 25,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
expect(result.rows).toEqual([]);
|
|
276
|
+
expect(result.isPartial).toBe(true);
|
|
277
|
+
});
|
|
278
|
+
});
|