@oneuptime/common 11.3.28 → 11.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/AIRun.ts +50 -0
- package/Models/DatabaseModels/Project.ts +60 -0
- package/Server/API/AIAgentTaskAPI.ts +10 -24
- package/Server/API/AIInvestigationAPI.ts +148 -0
- package/Server/API/TelemetryAPI.ts +4 -3
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/AIAgentTaskService.ts +62 -0
- package/Server/Services/AlertService.ts +25 -0
- package/Server/Services/AnalyticsDatabaseService.ts +27 -0
- package/Server/Services/IncidentService.ts +25 -0
- package/Server/Services/IncidentStateTimelineService.ts +19 -0
- package/Server/Services/LogAggregationService.ts +29 -11
- package/Server/Services/MetricService.ts +603 -13
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +119 -11
- package/Server/Utils/AI/Sentinel/AlertInvestigationRunner.ts +141 -0
- package/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.ts +178 -0
- package/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.ts +105 -0
- package/Server/Utils/AI/Sentinel/README.md +10 -0
- package/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.ts +405 -0
- package/Server/Utils/AI/Sentinel/SentinelMemory.ts +167 -0
- package/Server/Utils/AI/Toolbox/Index.ts +11 -0
- package/Server/Utils/AI/Toolbox/SentinelActionTools.ts +577 -0
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +44 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +108 -2
- package/Tests/Server/API/BaseAPI.test.ts +1 -0
- package/Tests/Server/Services/AIAgentTaskServiceClaim.test.ts +146 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +22 -0
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +194 -0
- package/Tests/Types/AI/AIAgentTaskStatus.test.ts +86 -0
- package/Tests/Types/BaseDatabase/AggregationIntervalUtil.test.ts +127 -0
- package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.test.ts +152 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtil.test.ts +260 -0
- package/Tests/Types/Trace/TraceRecordingRuleDefinition.test.ts +308 -0
- package/Tests/UI/Components/Dropdown.test.tsx +17 -0
- package/Tests/UI/Components/EntityDropdown.test.tsx +130 -0
- package/Tests/UI/Components/Modal.test.tsx +144 -2
- package/Tests/UI/Components/TelemetrySearchBar.test.tsx +90 -0
- package/Tests/UI/Utils/Theme.test.ts +161 -0
- package/Types/BaseDatabase/AggregateBy.ts +12 -0
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.ts +19 -0
- package/Types/Dashboard/DashboardTemplates.ts +9 -1
- package/Types/Date.ts +46 -0
- package/Types/Monitor/CriteriaFilter.ts +4 -0
- package/Types/Monitor/HttpPhaseTimings.ts +16 -0
- package/Types/Monitor/MonitorMetricType.ts +17 -0
- package/Types/Monitor/PingMonitor/PingMonitorResponse.ts +20 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +257 -0
- package/Types/Probe/ProbeMonitorResponse.ts +14 -0
- package/UI/Components/Calendar/Calendar.tsx +8 -2
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +5 -5
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +8 -5
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +4 -1
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +6 -3
- package/UI/Components/CodeBlock/CodeBlock.tsx +2 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
- package/UI/Components/Divider/Divider.tsx +1 -1
- package/UI/Components/Dropdown/Dropdown.tsx +13 -4
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +110 -2
- package/UI/Components/ErrorBoundary.tsx +2 -1
- package/UI/Components/EventItem/EventItem.tsx +2 -2
- package/UI/Components/GanttChart/Bar/Index.tsx +1 -1
- package/UI/Components/Graphs/UptimeBarTooltip.tsx +30 -23
- package/UI/Components/Header/Header.tsx +7 -0
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +2 -0
- package/UI/Components/Label/Label.tsx +2 -2
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +22 -10
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +9 -3
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +8 -8
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +44 -20
- package/UI/Components/Modal/ConfirmModal.tsx +1 -1
- package/UI/Components/Modal/Modal.tsx +213 -121
- package/UI/Components/Modal/ModalFooter.tsx +33 -22
- package/UI/Components/ModelTable/TableView.tsx +1 -1
- package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +20 -12
- package/UI/Components/Pill/Pill.tsx +21 -13
- package/UI/Components/StatusBubble/StatusBubble.tsx +3 -3
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +7 -1
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +9 -3
- package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +62 -4
- package/UI/Components/Workflow/Component.tsx +53 -33
- package/UI/Components/Workflow/ComponentPortViewer.tsx +6 -6
- package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +8 -8
- package/UI/Components/Workflow/ComponentsModal.tsx +16 -9
- package/UI/Components/Workflow/Workflow.tsx +13 -11
- package/UI/Utils/Theme.ts +140 -0
- package/Utils/Dashboard/Components/DashboardLogChartComponent.ts +104 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/Monitor/MonitorMetricType.ts +70 -2
- package/build/dist/Models/DatabaseModels/AIRun.js +52 -0
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +62 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Server/API/AIAgentTaskAPI.js +8 -23
- package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +107 -0
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -0
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIAgentTaskService.js +59 -0
- package/build/dist/Server/Services/AIAgentTaskService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +24 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +19 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +24 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +21 -7
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +449 -7
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +59 -11
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js +119 -0
- package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js +147 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js +93 -0
- package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js +311 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +1 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js +143 -0
- package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +6 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js +451 -0
- package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +29 -0
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +86 -2
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +9 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Date.js +32 -0
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/HttpPhaseTimings.js +2 -0
- package/build/dist/Types/Monitor/HttpPhaseTimings.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js +15 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js +2 -0
- package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +159 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -0
- package/build/dist/UI/Components/Calendar/Calendar.js +2 -2
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +7 -4
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +4 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +6 -3
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +3 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/Divider/Divider.js +1 -1
- package/build/dist/UI/Components/Divider/Divider.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +10 -4
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +76 -3
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +2 -1
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
- package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js +1 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +1 -1
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +29 -23
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
- package/build/dist/UI/Components/Header/Header.js +1 -0
- package/build/dist/UI/Components/Header/Header.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Label/Label.js +2 -2
- package/build/dist/UI/Components/Label/Label.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +20 -8
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +8 -2
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +8 -8
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +40 -20
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +109 -51
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +13 -10
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +17 -12
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
- package/build/dist/UI/Components/Pill/Pill.js +12 -13
- package/build/dist/UI/Components/Pill/Pill.js.map +1 -1
- package/build/dist/UI/Components/StatusBubble/StatusBubble.js +3 -3
- package/build/dist/UI/Components/StatusBubble/StatusBubble.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -2
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +36 -6
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Component.js +43 -33
- package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentPortViewer.js +6 -6
- package/build/dist/UI/Components/Workflow/ComponentPortViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +8 -8
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +15 -9
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +13 -11
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Utils/Theme.js +106 -0
- package/build/dist/UI/Utils/Theme.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js +92 -0
- package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +70 -3
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/package.json +1 -1
|
@@ -284,6 +284,56 @@ export default class AIRun extends BaseModel {
|
|
|
284
284
|
})
|
|
285
285
|
public conversationId?: ObjectID = undefined;
|
|
286
286
|
|
|
287
|
+
@ColumnAccessControl({
|
|
288
|
+
create: [],
|
|
289
|
+
read: [
|
|
290
|
+
Permission.ProjectOwner,
|
|
291
|
+
Permission.ProjectAdmin,
|
|
292
|
+
Permission.ProjectMember,
|
|
293
|
+
],
|
|
294
|
+
update: [],
|
|
295
|
+
})
|
|
296
|
+
@Index()
|
|
297
|
+
@TableColumn({
|
|
298
|
+
type: TableColumnType.ObjectID,
|
|
299
|
+
required: false,
|
|
300
|
+
canReadOnRelationQuery: true,
|
|
301
|
+
title: "Triggered By Incident ID",
|
|
302
|
+
description:
|
|
303
|
+
"The incident that triggered this run (for autonomous investigations).",
|
|
304
|
+
})
|
|
305
|
+
@Column({
|
|
306
|
+
type: ColumnType.ObjectID,
|
|
307
|
+
nullable: true,
|
|
308
|
+
transformer: ObjectID.getDatabaseTransformer(),
|
|
309
|
+
})
|
|
310
|
+
public triggeredByIncidentId?: ObjectID = undefined;
|
|
311
|
+
|
|
312
|
+
@ColumnAccessControl({
|
|
313
|
+
create: [],
|
|
314
|
+
read: [
|
|
315
|
+
Permission.ProjectOwner,
|
|
316
|
+
Permission.ProjectAdmin,
|
|
317
|
+
Permission.ProjectMember,
|
|
318
|
+
],
|
|
319
|
+
update: [],
|
|
320
|
+
})
|
|
321
|
+
@Index()
|
|
322
|
+
@TableColumn({
|
|
323
|
+
type: TableColumnType.ObjectID,
|
|
324
|
+
required: false,
|
|
325
|
+
canReadOnRelationQuery: true,
|
|
326
|
+
title: "Triggered By Alert ID",
|
|
327
|
+
description:
|
|
328
|
+
"The alert that triggered this run (for autonomous investigations).",
|
|
329
|
+
})
|
|
330
|
+
@Column({
|
|
331
|
+
type: ColumnType.ObjectID,
|
|
332
|
+
nullable: true,
|
|
333
|
+
transformer: ObjectID.getDatabaseTransformer(),
|
|
334
|
+
})
|
|
335
|
+
public triggeredByAlertId?: ObjectID = undefined;
|
|
336
|
+
|
|
287
337
|
@ColumnAccessControl({
|
|
288
338
|
create: [],
|
|
289
339
|
read: [
|
|
@@ -1422,6 +1422,66 @@ export default class Project extends TenantModel {
|
|
|
1422
1422
|
})
|
|
1423
1423
|
public enableAi?: boolean = undefined;
|
|
1424
1424
|
|
|
1425
|
+
@ColumnAccessControl({
|
|
1426
|
+
create: [],
|
|
1427
|
+
read: [
|
|
1428
|
+
Permission.ProjectOwner,
|
|
1429
|
+
Permission.ProjectAdmin,
|
|
1430
|
+
Permission.ProjectMember,
|
|
1431
|
+
Permission.Viewer,
|
|
1432
|
+
Permission.ReadProject,
|
|
1433
|
+
Permission.UnAuthorizedSsoUser,
|
|
1434
|
+
Permission.ProjectUser,
|
|
1435
|
+
],
|
|
1436
|
+
update: [Permission.ProjectOwner, Permission.ProjectAdmin],
|
|
1437
|
+
})
|
|
1438
|
+
@TableColumn({
|
|
1439
|
+
required: true,
|
|
1440
|
+
isDefaultValueColumn: true,
|
|
1441
|
+
type: TableColumnType.Boolean,
|
|
1442
|
+
title: "Enable Automatic Incident Investigation",
|
|
1443
|
+
description:
|
|
1444
|
+
"When enabled, OneUptime's AI SRE (Sentinel) automatically investigates every new incident and posts a cited root cause analysis to the incident timeline. Requires AI to be enabled and an LLM provider to be configured.",
|
|
1445
|
+
defaultValue: false,
|
|
1446
|
+
example: true,
|
|
1447
|
+
})
|
|
1448
|
+
@Column({
|
|
1449
|
+
nullable: false,
|
|
1450
|
+
default: false,
|
|
1451
|
+
type: ColumnType.Boolean,
|
|
1452
|
+
})
|
|
1453
|
+
public enableAutomaticIncidentInvestigation?: boolean = undefined;
|
|
1454
|
+
|
|
1455
|
+
@ColumnAccessControl({
|
|
1456
|
+
create: [],
|
|
1457
|
+
read: [
|
|
1458
|
+
Permission.ProjectOwner,
|
|
1459
|
+
Permission.ProjectAdmin,
|
|
1460
|
+
Permission.ProjectMember,
|
|
1461
|
+
Permission.Viewer,
|
|
1462
|
+
Permission.ReadProject,
|
|
1463
|
+
Permission.UnAuthorizedSsoUser,
|
|
1464
|
+
Permission.ProjectUser,
|
|
1465
|
+
],
|
|
1466
|
+
update: [Permission.ProjectOwner, Permission.ProjectAdmin],
|
|
1467
|
+
})
|
|
1468
|
+
@TableColumn({
|
|
1469
|
+
required: true,
|
|
1470
|
+
isDefaultValueColumn: true,
|
|
1471
|
+
type: TableColumnType.Boolean,
|
|
1472
|
+
title: "Enable Automatic Alert Investigation",
|
|
1473
|
+
description:
|
|
1474
|
+
"When enabled, OneUptime's AI SRE (Sentinel) automatically investigates every new alert and posts a cited root cause analysis to the alert timeline. Requires AI to be enabled and an LLM provider to be configured.",
|
|
1475
|
+
defaultValue: false,
|
|
1476
|
+
example: true,
|
|
1477
|
+
})
|
|
1478
|
+
@Column({
|
|
1479
|
+
nullable: false,
|
|
1480
|
+
default: false,
|
|
1481
|
+
type: ColumnType.Boolean,
|
|
1482
|
+
})
|
|
1483
|
+
public enableAutomaticAlertInvestigation?: boolean = undefined;
|
|
1484
|
+
|
|
1425
1485
|
@ColumnAccessControl({
|
|
1426
1486
|
create: [],
|
|
1427
1487
|
read: [
|
|
@@ -16,7 +16,6 @@ import { JSONObject } from "../../Types/JSON";
|
|
|
16
16
|
import ObjectID from "../../Types/ObjectID";
|
|
17
17
|
import OneUptimeDate from "../../Types/Date";
|
|
18
18
|
import AIAgentTaskStatus from "../../Types/AI/AIAgentTaskStatus";
|
|
19
|
-
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
20
19
|
import PositiveNumber from "../../Types/PositiveNumber";
|
|
21
20
|
|
|
22
21
|
export default class AIAgentTaskAPI extends BaseAPI<
|
|
@@ -27,8 +26,10 @@ export default class AIAgentTaskAPI extends BaseAPI<
|
|
|
27
26
|
super(AIAgentTask, AIAgentTaskService);
|
|
28
27
|
|
|
29
28
|
/*
|
|
30
|
-
*
|
|
31
|
-
* Validates aiAgentId and aiAgentKey before
|
|
29
|
+
* Claim the next pending (scheduled) task for processing.
|
|
30
|
+
* Validates aiAgentId and aiAgentKey before claiming. The task is
|
|
31
|
+
* atomically transitioned Scheduled -> InProgress before it is
|
|
32
|
+
* returned, so concurrent workers can never receive the same task.
|
|
32
33
|
*/
|
|
33
34
|
this.router.post(
|
|
34
35
|
`${new this.entityType().getCrudApiPath()?.toString()}/get-pending-task`,
|
|
@@ -39,7 +40,7 @@ export default class AIAgentTaskAPI extends BaseAPI<
|
|
|
39
40
|
/* Validate AI Agent credentials */
|
|
40
41
|
const aiAgent: AIAgent | null = await this.validateAIAgent(data);
|
|
41
42
|
|
|
42
|
-
if (!aiAgent) {
|
|
43
|
+
if (!aiAgent || !aiAgent.id) {
|
|
43
44
|
return Response.sendErrorResponse(
|
|
44
45
|
req,
|
|
45
46
|
res,
|
|
@@ -47,25 +48,10 @@ export default class AIAgentTaskAPI extends BaseAPI<
|
|
|
47
48
|
);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
},
|
|
55
|
-
sort: {
|
|
56
|
-
createdAt: SortOrder.Ascending,
|
|
57
|
-
},
|
|
58
|
-
select: {
|
|
59
|
-
_id: true,
|
|
60
|
-
projectId: true,
|
|
61
|
-
taskType: true,
|
|
62
|
-
metadata: true,
|
|
63
|
-
createdAt: true,
|
|
64
|
-
},
|
|
65
|
-
props: {
|
|
66
|
-
isRoot: true,
|
|
67
|
-
},
|
|
68
|
-
});
|
|
51
|
+
const task: AIAgentTask | null =
|
|
52
|
+
await AIAgentTaskService.claimNextScheduledTask({
|
|
53
|
+
aiAgentId: aiAgent.id,
|
|
54
|
+
});
|
|
69
55
|
|
|
70
56
|
if (!task) {
|
|
71
57
|
return Response.sendJsonObjectResponse(req, res, {
|
|
@@ -82,7 +68,7 @@ export default class AIAgentTaskAPI extends BaseAPI<
|
|
|
82
68
|
metadata: task.metadata as JSONObject | undefined,
|
|
83
69
|
createdAt: task.createdAt,
|
|
84
70
|
},
|
|
85
|
-
message: "Task
|
|
71
|
+
message: "Task claimed successfully",
|
|
86
72
|
});
|
|
87
73
|
} catch (err) {
|
|
88
74
|
next(err);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
2
|
+
import CommonAPI from "./CommonAPI";
|
|
3
|
+
import Express, {
|
|
4
|
+
ExpressRequest,
|
|
5
|
+
ExpressResponse,
|
|
6
|
+
ExpressRouter,
|
|
7
|
+
NextFunction,
|
|
8
|
+
} from "../Utils/Express";
|
|
9
|
+
import Response from "../Utils/Response";
|
|
10
|
+
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
11
|
+
import ObjectID from "../../Types/ObjectID";
|
|
12
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
13
|
+
import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
|
|
14
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
15
|
+
import { JSONArray, JSONObject } from "../../Types/JSON";
|
|
16
|
+
import AIRunType from "../../Types/AI/AIRunType";
|
|
17
|
+
import AIRun from "../../Models/DatabaseModels/AIRun";
|
|
18
|
+
import AIRunEvent from "../../Models/DatabaseModels/AIRunEvent";
|
|
19
|
+
import Incident from "../../Models/DatabaseModels/Incident";
|
|
20
|
+
import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
21
|
+
import IncidentService from "../Services/IncidentService";
|
|
22
|
+
import AIRunService from "../Services/AIRunService";
|
|
23
|
+
import AIRunEventService from "../Services/AIRunEventService";
|
|
24
|
+
|
|
25
|
+
const router: ExpressRouter = Express.getRouter();
|
|
26
|
+
|
|
27
|
+
const MAX_EVENTS: number = 500;
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* Returns the latest Sentinel investigation (the AIRun + its ordered
|
|
31
|
+
* AIRunEvents) for an incident, so the dashboard can render a live "watch it
|
|
32
|
+
* think" panel.
|
|
33
|
+
*
|
|
34
|
+
* Investigation runs are system-authored (userId = null) and are therefore
|
|
35
|
+
* hidden by the per-user privacy pin on the generic AIRun / AIRunEvent CRUD. So
|
|
36
|
+
* we gate access explicitly here: first confirm the caller can read the incident
|
|
37
|
+
* under THEIR permissions, then read the run + events as root.
|
|
38
|
+
*/
|
|
39
|
+
router.post(
|
|
40
|
+
"/ai-investigation/incident",
|
|
41
|
+
UserMiddleware.getUserMiddleware,
|
|
42
|
+
async (
|
|
43
|
+
req: ExpressRequest,
|
|
44
|
+
res: ExpressResponse,
|
|
45
|
+
next: NextFunction,
|
|
46
|
+
): Promise<void> => {
|
|
47
|
+
try {
|
|
48
|
+
const props: DatabaseCommonInteractionProps =
|
|
49
|
+
await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
50
|
+
|
|
51
|
+
if (!props.userId) {
|
|
52
|
+
throw new NotAuthorizedException(
|
|
53
|
+
"A logged-in user session is required.",
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const incidentIdString: string | undefined = req.body["incidentId"] as
|
|
58
|
+
| string
|
|
59
|
+
| undefined;
|
|
60
|
+
|
|
61
|
+
if (!incidentIdString) {
|
|
62
|
+
throw new BadDataException("incidentId is required.");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const incidentId: ObjectID = new ObjectID(incidentIdString);
|
|
66
|
+
|
|
67
|
+
// Access check under the USER's permissions (null when not allowed).
|
|
68
|
+
const incident: Incident | null = await IncidentService.findOneById({
|
|
69
|
+
id: incidentId,
|
|
70
|
+
select: { _id: true },
|
|
71
|
+
props,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (!incident) {
|
|
75
|
+
throw new BadDataException(
|
|
76
|
+
"Incident not found (or you do not have access to it).",
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Read the latest investigation run as root (bypasses the per-user pin).
|
|
81
|
+
const runs: Array<AIRun> = await AIRunService.findBy({
|
|
82
|
+
query: {
|
|
83
|
+
triggeredByIncidentId: incidentId,
|
|
84
|
+
runType: AIRunType.Investigation,
|
|
85
|
+
},
|
|
86
|
+
select: {
|
|
87
|
+
_id: true,
|
|
88
|
+
status: true,
|
|
89
|
+
startedAt: true,
|
|
90
|
+
completedAt: true,
|
|
91
|
+
errorMessage: true,
|
|
92
|
+
llmCallCount: true,
|
|
93
|
+
toolCallCount: true,
|
|
94
|
+
totalTokens: true,
|
|
95
|
+
createdAt: true,
|
|
96
|
+
},
|
|
97
|
+
sort: { createdAt: SortOrder.Descending },
|
|
98
|
+
limit: 1,
|
|
99
|
+
skip: 0,
|
|
100
|
+
props: { isRoot: true },
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const run: AIRun | undefined = runs[0];
|
|
104
|
+
|
|
105
|
+
if (!run) {
|
|
106
|
+
Response.sendJsonObjectResponse(req, res, {
|
|
107
|
+
run: null,
|
|
108
|
+
events: [],
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const events: Array<AIRunEvent> = await AIRunEventService.findBy({
|
|
114
|
+
query: { aiRunId: run.id! },
|
|
115
|
+
select: {
|
|
116
|
+
_id: true,
|
|
117
|
+
sequence: true,
|
|
118
|
+
eventType: true,
|
|
119
|
+
toolName: true,
|
|
120
|
+
resultSummary: true,
|
|
121
|
+
createdAt: true,
|
|
122
|
+
},
|
|
123
|
+
sort: { sequence: SortOrder.Ascending },
|
|
124
|
+
limit: MAX_EVENTS,
|
|
125
|
+
skip: 0,
|
|
126
|
+
props: { isRoot: true },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const runJson: JSONObject | undefined = BaseModel.toJSONArray(
|
|
130
|
+
[run],
|
|
131
|
+
AIRun,
|
|
132
|
+
)[0];
|
|
133
|
+
|
|
134
|
+
const eventsJson: JSONArray = BaseModel.toJSONArray(events, AIRunEvent);
|
|
135
|
+
|
|
136
|
+
Response.sendJsonObjectResponse(req, res, {
|
|
137
|
+
run: runJson || null,
|
|
138
|
+
events: eventsJson,
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
} catch (err) {
|
|
142
|
+
next(err);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
export default router;
|
|
@@ -404,9 +404,10 @@ router.post(
|
|
|
404
404
|
? (body["spanIds"] as Array<string>)
|
|
405
405
|
: undefined;
|
|
406
406
|
|
|
407
|
-
const attributes: Record<string, string
|
|
408
|
-
|
|
409
|
-
|
|
407
|
+
const attributes: Record<string, string | Array<string>> | undefined =
|
|
408
|
+
body["attributes"]
|
|
409
|
+
? (body["attributes"] as Record<string, string | Array<string>>)
|
|
410
|
+
: undefined;
|
|
410
411
|
|
|
411
412
|
const request: HistogramRequest = {
|
|
412
413
|
projectId: databaseProps.tenantId,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddEnableAutomaticIncidentInvestigationToProject1783598145111
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
public name = "AddEnableAutomaticIncidentInvestigationToProject1783598145111";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "Project" ADD "enableAutomaticIncidentInvestigation" boolean NOT NULL DEFAULT false`,
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`ALTER TABLE "Project" DROP COLUMN "enableAutomaticIncidentInvestigation"`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddInvestigationSubjectToAIRun1783615884106
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
public name = "AddInvestigationSubjectToAIRun1783615884106";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "AIRun" ADD "triggeredByIncidentId" uuid`,
|
|
11
|
+
);
|
|
12
|
+
await queryRunner.query(
|
|
13
|
+
`ALTER TABLE "AIRun" ADD "triggeredByAlertId" uuid`,
|
|
14
|
+
);
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`CREATE INDEX "IDX_AIRun_triggeredByIncidentId" ON "AIRun" ("triggeredByIncidentId")`,
|
|
17
|
+
);
|
|
18
|
+
await queryRunner.query(
|
|
19
|
+
`CREATE INDEX "IDX_AIRun_triggeredByAlertId" ON "AIRun" ("triggeredByAlertId")`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
24
|
+
await queryRunner.query(`DROP INDEX "IDX_AIRun_triggeredByAlertId"`);
|
|
25
|
+
await queryRunner.query(`DROP INDEX "IDX_AIRun_triggeredByIncidentId"`);
|
|
26
|
+
await queryRunner.query(
|
|
27
|
+
`ALTER TABLE "AIRun" DROP COLUMN "triggeredByAlertId"`,
|
|
28
|
+
);
|
|
29
|
+
await queryRunner.query(
|
|
30
|
+
`ALTER TABLE "AIRun" DROP COLUMN "triggeredByIncidentId"`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class AddEnableAutomaticAlertInvestigationToProject1783632447975
|
|
4
|
+
implements MigrationInterface
|
|
5
|
+
{
|
|
6
|
+
public name = "AddEnableAutomaticAlertInvestigationToProject1783632447975";
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(
|
|
10
|
+
`ALTER TABLE "Project" ADD "enableAutomaticAlertInvestigation" boolean NOT NULL DEFAULT false`,
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
15
|
+
await queryRunner.query(
|
|
16
|
+
`ALTER TABLE "Project" DROP COLUMN "enableAutomaticAlertInvestigation"`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -417,6 +417,9 @@ import { AddIncomingCallPolicyRoutingPhoneNumberUnique1783470000000 } from "./17
|
|
|
417
417
|
import { FixNotNullForeignKeysOnDelete1783510935686 } from "./1783510935686-FixNotNullForeignKeysOnDelete";
|
|
418
418
|
import { MigrationName1783515836148 } from "./1783515836148-MigrationName";
|
|
419
419
|
import { AddMigrationFailureTable1783523076215 } from "./1783523076215-AddMigrationFailureTable";
|
|
420
|
+
import { AddEnableAutomaticIncidentInvestigationToProject1783598145111 } from "./1783598145111-AddEnableAutomaticIncidentInvestigationToProject";
|
|
421
|
+
import { AddInvestigationSubjectToAIRun1783615884106 } from "./1783615884106-AddInvestigationSubjectToAIRun";
|
|
422
|
+
import { AddEnableAutomaticAlertInvestigationToProject1783632447975 } from "./1783632447975-AddEnableAutomaticAlertInvestigationToProject";
|
|
420
423
|
|
|
421
424
|
export default [
|
|
422
425
|
InitialMigration,
|
|
@@ -838,4 +841,7 @@ export default [
|
|
|
838
841
|
FixNotNullForeignKeysOnDelete1783510935686,
|
|
839
842
|
MigrationName1783515836148,
|
|
840
843
|
AddMigrationFailureTable1783523076215,
|
|
844
|
+
AddEnableAutomaticIncidentInvestigationToProject1783598145111,
|
|
845
|
+
AddInvestigationSubjectToAIRun1783615884106,
|
|
846
|
+
AddEnableAutomaticAlertInvestigationToProject1783632447975,
|
|
841
847
|
];
|
|
@@ -11,6 +11,7 @@ import Semaphore, { SemaphoreMutex } from "../Infrastructure/Semaphore";
|
|
|
11
11
|
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
12
12
|
import logger from "../Utils/Logger";
|
|
13
13
|
import OneUptimeDate from "../../Types/Date";
|
|
14
|
+
import AIAgentTaskStatus from "../../Types/AI/AIAgentTaskStatus";
|
|
14
15
|
|
|
15
16
|
export class Service extends DatabaseService<Model> {
|
|
16
17
|
public constructor() {
|
|
@@ -80,6 +81,67 @@ export class Service extends DatabaseService<Model> {
|
|
|
80
81
|
return { createBy, carryForward: null };
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
/*
|
|
85
|
+
* Atomically claim the oldest Scheduled task for a worker: the
|
|
86
|
+
* Scheduled -> InProgress transition is guarded on status, so when
|
|
87
|
+
* multiple workers poll concurrently only one claim succeeds
|
|
88
|
+
* (updateOneBy returns the number of rows changed — zero means another
|
|
89
|
+
* worker won the race, so we retry with the next candidate). The
|
|
90
|
+
* returned task is already InProgress and owned by the given agent.
|
|
91
|
+
*/
|
|
92
|
+
@CaptureSpan()
|
|
93
|
+
public async claimNextScheduledTask(data: {
|
|
94
|
+
aiAgentId: ObjectID;
|
|
95
|
+
}): Promise<Model | null> {
|
|
96
|
+
const maxClaimAttempts: number = 5;
|
|
97
|
+
|
|
98
|
+
for (let attempt: number = 0; attempt < maxClaimAttempts; attempt++) {
|
|
99
|
+
const task: Model | null = await this.findOneBy({
|
|
100
|
+
query: {
|
|
101
|
+
status: AIAgentTaskStatus.Scheduled,
|
|
102
|
+
},
|
|
103
|
+
sort: {
|
|
104
|
+
createdAt: SortOrder.Ascending,
|
|
105
|
+
},
|
|
106
|
+
select: {
|
|
107
|
+
_id: true,
|
|
108
|
+
projectId: true,
|
|
109
|
+
taskType: true,
|
|
110
|
+
metadata: true,
|
|
111
|
+
createdAt: true,
|
|
112
|
+
},
|
|
113
|
+
props: {
|
|
114
|
+
isRoot: true,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (!task || !task.id) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const claimedCount: number = await this.updateOneBy({
|
|
123
|
+
query: {
|
|
124
|
+
_id: task.id.toString(),
|
|
125
|
+
status: AIAgentTaskStatus.Scheduled,
|
|
126
|
+
},
|
|
127
|
+
data: {
|
|
128
|
+
status: AIAgentTaskStatus.InProgress,
|
|
129
|
+
aiAgentId: data.aiAgentId,
|
|
130
|
+
startedAt: OneUptimeDate.getCurrentDate(),
|
|
131
|
+
},
|
|
132
|
+
props: {
|
|
133
|
+
isRoot: true,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (claimedCount > 0) {
|
|
138
|
+
return task;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
83
145
|
@CaptureSpan()
|
|
84
146
|
public async getExistingTaskNumberForProject(data: {
|
|
85
147
|
projectId: ObjectID;
|
|
@@ -67,6 +67,7 @@ import AlertLabelRuleEngineService from "./AlertLabelRuleEngineService";
|
|
|
67
67
|
import AlertOnCallRuleEngineService from "./AlertOnCallRuleEngineService";
|
|
68
68
|
import AlertOwnerRuleEngineService from "./AlertOwnerRuleEngineService";
|
|
69
69
|
import RunbookRuleEngineService from "./RunbookRuleEngineService";
|
|
70
|
+
import SentinelAlertInvestigationRunner from "../Utils/AI/Sentinel/AlertInvestigationRunner";
|
|
70
71
|
import AlertPrivacyRuleEngineService from "./AlertPrivacyRuleEngineService";
|
|
71
72
|
import ProjectService from "./ProjectService";
|
|
72
73
|
|
|
@@ -558,6 +559,30 @@ export class Service extends DatabaseService<Model> {
|
|
|
558
559
|
);
|
|
559
560
|
}
|
|
560
561
|
})
|
|
562
|
+
.then(async () => {
|
|
563
|
+
/*
|
|
564
|
+
* Sentinel (AI SRE): automatically investigate the new alert and post a
|
|
565
|
+
* cited root cause analysis to the alert timeline + Slack/Teams. Runs
|
|
566
|
+
* last, is gated per project (opt-in) + requires an LLM provider, and is
|
|
567
|
+
* read-only.
|
|
568
|
+
*/
|
|
569
|
+
try {
|
|
570
|
+
if (createdItem.projectId && createdItem.id) {
|
|
571
|
+
await SentinelAlertInvestigationRunner.investigateNewAlert({
|
|
572
|
+
alertId: createdItem.id,
|
|
573
|
+
projectId: createdItem.projectId,
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
} catch (error) {
|
|
577
|
+
logger.error(
|
|
578
|
+
`Sentinel alert investigation failed in AlertService.onCreateSuccess: ${error}`,
|
|
579
|
+
{
|
|
580
|
+
projectId: createdItem.projectId?.toString(),
|
|
581
|
+
alertId: createdItem.id?.toString(),
|
|
582
|
+
} as LogAttributes,
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
})
|
|
561
586
|
.catch((error: Error) => {
|
|
562
587
|
logger.error(
|
|
563
588
|
`Critical error in AlertService sequential operations: ${error}`,
|
|
@@ -813,6 +813,19 @@ export default class AnalyticsDatabaseService<
|
|
|
813
813
|
? Object.keys(aggregateBy.groupBy)
|
|
814
814
|
: [];
|
|
815
815
|
|
|
816
|
+
/*
|
|
817
|
+
* Attribute-key grouping returns the selected keys folded into a
|
|
818
|
+
* single `attributes` map column (see MetricService); carry it
|
|
819
|
+
* onto the aggregated rows so series splitters can read labels.
|
|
820
|
+
*/
|
|
821
|
+
if (
|
|
822
|
+
aggregateBy.groupByAttributeKeys &&
|
|
823
|
+
aggregateBy.groupByAttributeKeys.length > 0 &&
|
|
824
|
+
!groupByColumnNames.includes("attributes")
|
|
825
|
+
) {
|
|
826
|
+
groupByColumnNames.push("attributes");
|
|
827
|
+
}
|
|
828
|
+
|
|
816
829
|
for (const item of items) {
|
|
817
830
|
if (
|
|
818
831
|
!(item as JSONObject)[
|
|
@@ -1171,6 +1184,20 @@ export default class AnalyticsDatabaseService<
|
|
|
1171
1184
|
statement: Statement;
|
|
1172
1185
|
columns: Array<string>;
|
|
1173
1186
|
} {
|
|
1187
|
+
/*
|
|
1188
|
+
* Attribute-key grouping needs model-specific SQL over a map column
|
|
1189
|
+
* (MetricService builds it); reaching this generic path with keys
|
|
1190
|
+
* set would silently return ungrouped results.
|
|
1191
|
+
*/
|
|
1192
|
+
if (
|
|
1193
|
+
aggregateBy.groupByAttributeKeys &&
|
|
1194
|
+
aggregateBy.groupByAttributeKeys.length > 0
|
|
1195
|
+
) {
|
|
1196
|
+
throw new BadDataException(
|
|
1197
|
+
`groupByAttributeKeys is not supported for ${this.model.tableName}.`,
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1174
1201
|
if (!this.database) {
|
|
1175
1202
|
this.useDefaultDatabase();
|
|
1176
1203
|
}
|
|
@@ -89,6 +89,7 @@ import LLMService, {
|
|
|
89
89
|
} from "../Utils/LLM/LLMService";
|
|
90
90
|
import LlmProviderService from "./LlmProviderService";
|
|
91
91
|
import LlmProvider from "../../Models/DatabaseModels/LlmProvider";
|
|
92
|
+
import SentinelIncidentInvestigationRunner from "../Utils/AI/Sentinel/IncidentInvestigationRunner";
|
|
92
93
|
import IncidentAIContextBuilder, {
|
|
93
94
|
AIGenerationContext,
|
|
94
95
|
IncidentContextData,
|
|
@@ -1241,6 +1242,30 @@ export class Service extends DatabaseService<Model> {
|
|
|
1241
1242
|
);
|
|
1242
1243
|
}
|
|
1243
1244
|
})
|
|
1245
|
+
.then(async () => {
|
|
1246
|
+
/*
|
|
1247
|
+
* Sentinel (AI SRE): automatically investigate the new incident and post
|
|
1248
|
+
* a cited root cause analysis to the incident timeline + Slack/Teams.
|
|
1249
|
+
* Runs last so the workspace channels already exist, and is gated per
|
|
1250
|
+
* project (opt-in) + requires a configured LLM provider. Read-only.
|
|
1251
|
+
*/
|
|
1252
|
+
try {
|
|
1253
|
+
if (createdItem.projectId && createdItem.id) {
|
|
1254
|
+
await SentinelIncidentInvestigationRunner.investigateNewIncident({
|
|
1255
|
+
incidentId: createdItem.id,
|
|
1256
|
+
projectId: createdItem.projectId,
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
} catch (error) {
|
|
1260
|
+
logger.error(
|
|
1261
|
+
`Sentinel incident investigation failed in IncidentService.onCreateSuccess: ${error}`,
|
|
1262
|
+
{
|
|
1263
|
+
projectId: createdItem.projectId?.toString(),
|
|
1264
|
+
incidentId: createdItem.id?.toString(),
|
|
1265
|
+
} as LogAttributes,
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
})
|
|
1244
1269
|
.catch((error: Error) => {
|
|
1245
1270
|
logger.error(
|
|
1246
1271
|
`Critical error in IncidentService sequential operations: ${error}`,
|
|
@@ -27,6 +27,7 @@ import IncidentRole from "../../Models/DatabaseModels/IncidentRole";
|
|
|
27
27
|
import { IsBillingEnabled } from "../EnvironmentConfig";
|
|
28
28
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
29
29
|
import IncidentFeedService from "./IncidentFeedService";
|
|
30
|
+
import SentinelIncidentPostmortemRunner from "../Utils/AI/Sentinel/IncidentPostmortemRunner";
|
|
30
31
|
import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
|
|
31
32
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
32
33
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
@@ -555,6 +556,24 @@ ${createdItem.rootCause}`,
|
|
|
555
556
|
createdItem.startsAt || undefined,
|
|
556
557
|
);
|
|
557
558
|
}
|
|
559
|
+
|
|
560
|
+
/*
|
|
561
|
+
* Sentinel: auto-draft a postmortem now that the incident is resolved
|
|
562
|
+
* (gated per project; never overwrites an existing postmortem).
|
|
563
|
+
*/
|
|
564
|
+
SentinelIncidentPostmortemRunner.draftPostmortemOnResolve({
|
|
565
|
+
incidentId: createdItem.incidentId!,
|
|
566
|
+
projectId: createdItem.projectId!,
|
|
567
|
+
}).catch((error: Error) => {
|
|
568
|
+
logger.error(`Sentinel auto-postmortem failed on resolve:`, {
|
|
569
|
+
projectId: createdItem.projectId?.toString(),
|
|
570
|
+
incidentId: createdItem.incidentId?.toString(),
|
|
571
|
+
} as LogAttributes);
|
|
572
|
+
logger.error(error, {
|
|
573
|
+
projectId: createdItem.projectId?.toString(),
|
|
574
|
+
incidentId: createdItem.incidentId?.toString(),
|
|
575
|
+
} as LogAttributes);
|
|
576
|
+
});
|
|
558
577
|
}
|
|
559
578
|
|
|
560
579
|
if (onCreate.carryForward.publicNote) {
|