@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
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import TelemetrySearchBar from "../../../UI/Components/TelemetryViewer/components/TelemetrySearchBar";
|
|
2
|
+
import "@testing-library/jest-dom/extend-expect";
|
|
3
|
+
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
6
|
+
|
|
7
|
+
describe("TelemetrySearchBar", () => {
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
cleanup();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("shows the results loader inside the search box while loading", () => {
|
|
13
|
+
const { rerender } = render(
|
|
14
|
+
<TelemetrySearchBar
|
|
15
|
+
value="service:api"
|
|
16
|
+
onChange={jest.fn()}
|
|
17
|
+
onSubmit={jest.fn()}
|
|
18
|
+
isLoading={false}
|
|
19
|
+
/>,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
expect(
|
|
23
|
+
screen.queryByRole("status", { name: "Loading results" }),
|
|
24
|
+
).toBeNull();
|
|
25
|
+
|
|
26
|
+
rerender(
|
|
27
|
+
<TelemetrySearchBar
|
|
28
|
+
value="service:api"
|
|
29
|
+
onChange={jest.fn()}
|
|
30
|
+
onSubmit={jest.fn()}
|
|
31
|
+
isLoading={true}
|
|
32
|
+
/>,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const input: HTMLElement = screen.getByRole("textbox");
|
|
36
|
+
const loader: HTMLElement = screen.getByRole("status", {
|
|
37
|
+
name: "Loading results",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(input.parentElement?.contains(loader)).toBe(true);
|
|
41
|
+
expect(input.parentElement?.getAttribute("aria-busy")).toBe("true");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("Enter submits and keeps the token when onFieldValueSelect returns false", () => {
|
|
45
|
+
const onChange: (value: string) => void = jest.fn();
|
|
46
|
+
const onSubmit: () => void = jest.fn();
|
|
47
|
+
const onFieldValueSelect: (fieldKey: string, value: string) => boolean =
|
|
48
|
+
jest.fn((_fieldKey: string, _value: string): boolean => {
|
|
49
|
+
return false;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
render(
|
|
53
|
+
<TelemetrySearchBar
|
|
54
|
+
value="name:process"
|
|
55
|
+
onChange={onChange}
|
|
56
|
+
onSubmit={onSubmit}
|
|
57
|
+
onFieldValueSelect={onFieldValueSelect}
|
|
58
|
+
/>,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Enter" });
|
|
62
|
+
|
|
63
|
+
expect(onFieldValueSelect).toHaveBeenCalledWith("name", "process");
|
|
64
|
+
expect(onSubmit).toHaveBeenCalledTimes(1);
|
|
65
|
+
// The token must stay in the input — clearing it would drop the filter.
|
|
66
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("Enter clears the token when onFieldValueSelect consumes it as a chip", () => {
|
|
70
|
+
const onChange: (value: string) => void = jest.fn();
|
|
71
|
+
const onSubmit: () => void = jest.fn();
|
|
72
|
+
const onFieldValueSelect: (fieldKey: string, value: string) => void =
|
|
73
|
+
jest.fn();
|
|
74
|
+
|
|
75
|
+
render(
|
|
76
|
+
<TelemetrySearchBar
|
|
77
|
+
value="@http.method:GET"
|
|
78
|
+
onChange={onChange}
|
|
79
|
+
onSubmit={onSubmit}
|
|
80
|
+
onFieldValueSelect={onFieldValueSelect}
|
|
81
|
+
/>,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Enter" });
|
|
85
|
+
|
|
86
|
+
expect(onFieldValueSelect).toHaveBeenCalledWith("http.method", "GET");
|
|
87
|
+
expect(onChange).toHaveBeenCalledWith("");
|
|
88
|
+
expect(onSubmit).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test } from "@jest/globals";
|
|
2
|
+
import ThemeUtil, { THEME_STORAGE_KEY, Theme } from "../../../UI/Utils/Theme";
|
|
3
|
+
|
|
4
|
+
const LIGHT_THEME_COLOR: string = "#f9fafb";
|
|
5
|
+
const DARK_THEME_COLOR: string = "#0f172a";
|
|
6
|
+
|
|
7
|
+
const getThemeColorMeta: () => HTMLMetaElement = (): HTMLMetaElement => {
|
|
8
|
+
const themeColor: HTMLMetaElement | null = document.querySelector(
|
|
9
|
+
'meta[name="theme-color"]:not([media])',
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
expect(themeColor).not.toBeNull();
|
|
13
|
+
return themeColor as HTMLMetaElement;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const dispatchStorageEvent: (
|
|
17
|
+
key: string | null,
|
|
18
|
+
newValue: string | null,
|
|
19
|
+
) => void = (key: string | null, newValue: string | null): void => {
|
|
20
|
+
window.dispatchEvent(
|
|
21
|
+
new StorageEvent("storage", {
|
|
22
|
+
key,
|
|
23
|
+
newValue,
|
|
24
|
+
storageArea: window.localStorage,
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const makeLocalStorageUnavailable: () => () => void = (): (() => void) => {
|
|
30
|
+
const descriptor: PropertyDescriptor | undefined =
|
|
31
|
+
Object.getOwnPropertyDescriptor(window, "localStorage");
|
|
32
|
+
|
|
33
|
+
if (!descriptor) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
"Expected window.localStorage to have a property descriptor",
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
Object.defineProperty(window, "localStorage", {
|
|
40
|
+
configurable: true,
|
|
41
|
+
get: (): never => {
|
|
42
|
+
throw new Error("Storage is unavailable");
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return (): void => {
|
|
47
|
+
Object.defineProperty(window, "localStorage", descriptor);
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
describe("ThemeUtil", () => {
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
window.localStorage.clear();
|
|
54
|
+
|
|
55
|
+
const root: HTMLElement = document.documentElement;
|
|
56
|
+
root.removeAttribute("class");
|
|
57
|
+
root.removeAttribute("data-theme");
|
|
58
|
+
root.style.removeProperty("color-scheme");
|
|
59
|
+
|
|
60
|
+
document.head.innerHTML = [
|
|
61
|
+
'<meta name="theme-color" content="initial">',
|
|
62
|
+
'<meta name="theme-color" media="(prefers-color-scheme: dark)" content="media-theme">',
|
|
63
|
+
].join("");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("defaults to light when no preference has been saved", () => {
|
|
67
|
+
document.documentElement.classList.add(Theme.Dark);
|
|
68
|
+
|
|
69
|
+
expect(ThemeUtil.getStoredTheme()).toBe(Theme.Light);
|
|
70
|
+
|
|
71
|
+
ThemeUtil.initialize();
|
|
72
|
+
|
|
73
|
+
expect(ThemeUtil.getAppliedTheme()).toBe(Theme.Light);
|
|
74
|
+
expect(document.documentElement.classList.contains(Theme.Dark)).toBe(false);
|
|
75
|
+
expect(document.documentElement.dataset["theme"]).toBe(Theme.Light);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("restores an exactly persisted dark preference", () => {
|
|
79
|
+
window.localStorage.setItem(THEME_STORAGE_KEY, Theme.Dark);
|
|
80
|
+
|
|
81
|
+
expect(ThemeUtil.getStoredTheme()).toBe(Theme.Dark);
|
|
82
|
+
|
|
83
|
+
ThemeUtil.initialize();
|
|
84
|
+
|
|
85
|
+
expect(ThemeUtil.getAppliedTheme()).toBe(Theme.Dark);
|
|
86
|
+
expect(document.documentElement.classList.contains(Theme.Dark)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test.each([Theme.Light, "Dark", "DARK", " dark ", "invalid", ""])(
|
|
90
|
+
"treats the persisted value %p as light",
|
|
91
|
+
(persistedValue: string) => {
|
|
92
|
+
window.localStorage.setItem(THEME_STORAGE_KEY, persistedValue);
|
|
93
|
+
|
|
94
|
+
expect(ThemeUtil.getStoredTheme()).toBe(Theme.Light);
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
test("updates the root class, data attribute, color scheme, and theme-color meta", () => {
|
|
99
|
+
const mediaThemeColor: HTMLMetaElement = document.querySelector(
|
|
100
|
+
'meta[name="theme-color"][media]',
|
|
101
|
+
) as HTMLMetaElement;
|
|
102
|
+
|
|
103
|
+
ThemeUtil.setTheme(Theme.Dark);
|
|
104
|
+
|
|
105
|
+
expect(window.localStorage.getItem(THEME_STORAGE_KEY)).toBe(Theme.Dark);
|
|
106
|
+
expect(document.documentElement.classList.contains(Theme.Dark)).toBe(true);
|
|
107
|
+
expect(document.documentElement.dataset["theme"]).toBe(Theme.Dark);
|
|
108
|
+
expect(document.documentElement.style.colorScheme).toBe(Theme.Dark);
|
|
109
|
+
expect(getThemeColorMeta().getAttribute("content")).toBe(DARK_THEME_COLOR);
|
|
110
|
+
expect(mediaThemeColor.getAttribute("content")).toBe("media-theme");
|
|
111
|
+
|
|
112
|
+
ThemeUtil.setTheme(Theme.Light);
|
|
113
|
+
|
|
114
|
+
expect(window.localStorage.getItem(THEME_STORAGE_KEY)).toBe(Theme.Light);
|
|
115
|
+
expect(document.documentElement.classList.contains(Theme.Dark)).toBe(false);
|
|
116
|
+
expect(document.documentElement.dataset["theme"]).toBe(Theme.Light);
|
|
117
|
+
expect(document.documentElement.style.colorScheme).toBe(Theme.Light);
|
|
118
|
+
expect(getThemeColorMeta().getAttribute("content")).toBe(LIGHT_THEME_COLOR);
|
|
119
|
+
expect(mediaThemeColor.getAttribute("content")).toBe("media-theme");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("falls back to light when reading storage fails", () => {
|
|
123
|
+
const restoreLocalStorage: () => void = makeLocalStorageUnavailable();
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
expect(ThemeUtil.getStoredTheme()).toBe(Theme.Light);
|
|
127
|
+
} finally {
|
|
128
|
+
restoreLocalStorage();
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("still applies the visual theme when writing storage fails", () => {
|
|
133
|
+
const restoreLocalStorage: () => void = makeLocalStorageUnavailable();
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
expect(() => {
|
|
137
|
+
ThemeUtil.setTheme(Theme.Dark);
|
|
138
|
+
}).not.toThrow();
|
|
139
|
+
expect(ThemeUtil.getAppliedTheme()).toBe(Theme.Dark);
|
|
140
|
+
expect(document.documentElement.dataset["theme"]).toBe(Theme.Dark);
|
|
141
|
+
} finally {
|
|
142
|
+
restoreLocalStorage();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("synchronizes dark and cleared preferences from other tabs", () => {
|
|
147
|
+
ThemeUtil.initialize();
|
|
148
|
+
|
|
149
|
+
dispatchStorageEvent(THEME_STORAGE_KEY, Theme.Dark);
|
|
150
|
+
expect(ThemeUtil.getAppliedTheme()).toBe(Theme.Dark);
|
|
151
|
+
|
|
152
|
+
dispatchStorageEvent(THEME_STORAGE_KEY, null);
|
|
153
|
+
expect(ThemeUtil.getAppliedTheme()).toBe(Theme.Light);
|
|
154
|
+
|
|
155
|
+
dispatchStorageEvent(THEME_STORAGE_KEY, Theme.Dark);
|
|
156
|
+
expect(ThemeUtil.getAppliedTheme()).toBe(Theme.Dark);
|
|
157
|
+
|
|
158
|
+
dispatchStorageEvent(null, null);
|
|
159
|
+
expect(ThemeUtil.getAppliedTheme()).toBe(Theme.Light);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -16,4 +16,16 @@ export default interface AggregateBy<TBaseModel extends GenericObject> {
|
|
|
16
16
|
skip: number;
|
|
17
17
|
sort?: Sort<TBaseModel> | undefined;
|
|
18
18
|
groupBy?: GroupBy<TBaseModel> | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* OpenTelemetry attribute keys (e.g. "service.name") to group the
|
|
21
|
+
* aggregation by. Grouping happens on the individual map entries —
|
|
22
|
+
* `attributes['service.name']` — so all rows sharing the selected
|
|
23
|
+
* key values are pooled into one series per bucket. This is distinct
|
|
24
|
+
* from `groupBy: { attributes: true }`, which groups by the ENTIRE
|
|
25
|
+
* attribute map and therefore fragments the result into one series
|
|
26
|
+
* per unique attribute combination. Only supported by models with an
|
|
27
|
+
* `attributes` map column (currently Metric); result rows carry an
|
|
28
|
+
* `attributes` object containing exactly these keys.
|
|
29
|
+
*/
|
|
30
|
+
groupByAttributeKeys?: Array<string> | undefined;
|
|
19
31
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import ObjectID from "../../ObjectID";
|
|
2
|
+
import DashboardComponentType from "../DashboardComponentType";
|
|
3
|
+
import BaseComponent from "./DashboardBaseComponent";
|
|
4
|
+
|
|
5
|
+
export default interface DashboardLogChartComponent extends BaseComponent {
|
|
6
|
+
componentType: DashboardComponentType.LogChart;
|
|
7
|
+
componentId: ObjectID;
|
|
8
|
+
arguments: {
|
|
9
|
+
title?: string | undefined;
|
|
10
|
+
serviceIds?: Array<string> | undefined;
|
|
11
|
+
severityFilters?: Array<string> | undefined;
|
|
12
|
+
bodyContains?: string | undefined;
|
|
13
|
+
/*
|
|
14
|
+
* Exact attribute matches in the log-search syntax used by Log Stream,
|
|
15
|
+
* for example: @service.name:checkout @deployment.environment:production.
|
|
16
|
+
*/
|
|
17
|
+
attributeFilterQuery?: string | undefined;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -192,7 +192,15 @@ function buildMetricQueryConfig(config: MetricConfig): Record<string, unknown> {
|
|
|
192
192
|
metricName: config.metricName,
|
|
193
193
|
aggegationType: config.aggregationType,
|
|
194
194
|
},
|
|
195
|
-
|
|
195
|
+
/*
|
|
196
|
+
* groupByAttributeKeys alone drives per-series grouping — the
|
|
197
|
+
* fetch layer compiles it to `GROUP BY attributes['<key>']`.
|
|
198
|
+
* Baking a whole-map `groupBy: { attributes: true }` alongside
|
|
199
|
+
* it (the old approach) fragmented results into one series per
|
|
200
|
+
* unique attribute combination; older stored configs that still
|
|
201
|
+
* carry it are stripped at fetch time (MetricUtil.fetchResults).
|
|
202
|
+
*/
|
|
203
|
+
groupBy: undefined,
|
|
196
204
|
groupByAttributeKeys: config.groupByAttributeKeys,
|
|
197
205
|
},
|
|
198
206
|
transformAsRate: config.transformAsRate,
|
package/Types/Date.ts
CHANGED
|
@@ -286,6 +286,52 @@ export default class OneUptimeDate {
|
|
|
286
286
|
.format(use12HourFormat ? "h:mm A" : "HH:mm");
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Format a single instant as a human-readable "weekday, month day, time"
|
|
291
|
+
* string resolved in a specific IANA timezone (e.g. "America/New_York").
|
|
292
|
+
*
|
|
293
|
+
* Used by the on-call schedule summaries to render each shift's start / end in
|
|
294
|
+
* the SAME zone the rotation engine schedules people in, with a DST-aware zone
|
|
295
|
+
* abbreviation appended so the reader is never in doubt which wall clock the
|
|
296
|
+
* time refers to. When `timezone` is omitted the instant is formatted in the
|
|
297
|
+
* viewer's local zone (matching the rest of the local-time UI).
|
|
298
|
+
*/
|
|
299
|
+
public static getDateAsFormattedStringInTimezone(data: {
|
|
300
|
+
date: Date | string;
|
|
301
|
+
timezone?: string | undefined;
|
|
302
|
+
onlyShowDate?: boolean | undefined;
|
|
303
|
+
showWeekday?: boolean | undefined;
|
|
304
|
+
use12HourFormat?: boolean | undefined;
|
|
305
|
+
}): string {
|
|
306
|
+
const date: Date = this.fromString(data.date);
|
|
307
|
+
const use12HourFormat: boolean =
|
|
308
|
+
data.use12HourFormat ?? this.getUserPrefers12HourFormat();
|
|
309
|
+
|
|
310
|
+
const timePart: string = use12HourFormat ? "h:mm A" : "HH:mm";
|
|
311
|
+
const datePart: string = data.showWeekday
|
|
312
|
+
? "ddd, MMM D, YYYY"
|
|
313
|
+
: "MMM D, YYYY";
|
|
314
|
+
const formatString: string = data.onlyShowDate
|
|
315
|
+
? datePart
|
|
316
|
+
: `${datePart}, ${timePart}`;
|
|
317
|
+
|
|
318
|
+
if (!data.timezone) {
|
|
319
|
+
const local: moment.Moment = moment(date).local();
|
|
320
|
+
return (
|
|
321
|
+
local.format(formatString) +
|
|
322
|
+
(data.onlyShowDate ? "" : " " + this.getCurrentTimezoneString())
|
|
323
|
+
).trim();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const zoned: moment.Moment = moment(date).tz(data.timezone);
|
|
327
|
+
return (
|
|
328
|
+
zoned.format(formatString) +
|
|
329
|
+
(data.onlyShowDate
|
|
330
|
+
? ""
|
|
331
|
+
: " " + this.getZoneAbbrByTimezone(data.timezone as Timezone, date))
|
|
332
|
+
).trim();
|
|
333
|
+
}
|
|
334
|
+
|
|
289
335
|
/**
|
|
290
336
|
* Reinterpret the wall-clock components of `date` — read in the process /
|
|
291
337
|
* browser local zone — as the SAME wall-clock in `timezone`, and return that
|
|
@@ -3,6 +3,8 @@ import MetricCriteriaContext from "./MetricMonitor/MetricCriteriaContext";
|
|
|
3
3
|
|
|
4
4
|
export enum CheckOn {
|
|
5
5
|
ResponseTime = "Response Time (in ms)",
|
|
6
|
+
PacketLossPercent = "Packet Loss (in %)",
|
|
7
|
+
Jitter = "Jitter (in ms)",
|
|
6
8
|
ResponseStatusCode = "Response Status Code",
|
|
7
9
|
ResponseHeader = "Response Header",
|
|
8
10
|
ResponseHeaderValue = "Response Header Value",
|
|
@@ -374,6 +376,8 @@ export class CriteriaFilterUtil {
|
|
|
374
376
|
return (
|
|
375
377
|
checkOn === CheckOn.ResponseStatusCode ||
|
|
376
378
|
checkOn === CheckOn.ResponseTime ||
|
|
379
|
+
checkOn === CheckOn.PacketLossPercent ||
|
|
380
|
+
checkOn === CheckOn.Jitter ||
|
|
377
381
|
checkOn === CheckOn.DiskUsagePercent ||
|
|
378
382
|
checkOn === CheckOn.CPUUsagePercent ||
|
|
379
383
|
checkOn === CheckOn.MemoryUsagePercent ||
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Per-phase breakdown of an HTTP(S) check, all in milliseconds. Captured by
|
|
3
|
+
* the probe from socket events on the initial connection of the request.
|
|
4
|
+
* Every field is optional: phases are absent when they don't apply (no TLS
|
|
5
|
+
* on plain HTTP, no DNS lookup when the target is an IP address) or when the
|
|
6
|
+
* request went through a proxy, where per-phase timing would be misleading.
|
|
7
|
+
* When the check follows redirects, the phases describe the first connection
|
|
8
|
+
* and the download phase absorbs the rest of the exchange.
|
|
9
|
+
*/
|
|
10
|
+
export default interface HttpPhaseTimings {
|
|
11
|
+
dnsLookupInMs?: number | undefined;
|
|
12
|
+
tcpConnectInMs?: number | undefined;
|
|
13
|
+
tlsHandshakeInMs?: number | undefined;
|
|
14
|
+
timeToFirstByteInMs?: number | undefined;
|
|
15
|
+
downloadInMs?: number | undefined;
|
|
16
|
+
}
|
|
@@ -7,6 +7,23 @@ enum MonitorMetricType {
|
|
|
7
7
|
IsOnline = "oneuptime.monitor.online",
|
|
8
8
|
ExecutionTime = "oneuptime.monitor.execution.time",
|
|
9
9
|
|
|
10
|
+
/*
|
|
11
|
+
* Packet-level network metrics. Emitted by Ping/IP monitors when the
|
|
12
|
+
* probe sends multiple echo requests per check; absent for older probes.
|
|
13
|
+
*/
|
|
14
|
+
PacketLossPercent = "oneuptime.monitor.ping.packet.loss.percent",
|
|
15
|
+
Jitter = "oneuptime.monitor.ping.jitter",
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* HTTP(S) phase breakdown. Emitted by Website/API monitors when the probe
|
|
19
|
+
* captured socket-level timings; absent behind proxies and on older probes.
|
|
20
|
+
*/
|
|
21
|
+
DnsLookupTime = "oneuptime.monitor.http.dns.lookup.time",
|
|
22
|
+
TcpConnectTime = "oneuptime.monitor.http.tcp.connect.time",
|
|
23
|
+
TlsHandshakeTime = "oneuptime.monitor.http.tls.handshake.time",
|
|
24
|
+
TimeToFirstByte = "oneuptime.monitor.http.time.to.first.byte",
|
|
25
|
+
DownloadTime = "oneuptime.monitor.http.download.time",
|
|
26
|
+
|
|
10
27
|
/*
|
|
11
28
|
* Extended server/VM metrics. Emitted when the agent payload contains them;
|
|
12
29
|
* absent for older agents, which keeps the pipeline backwards-compatible.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Packet-level statistics captured by the Ping/IP monitor. Populated when
|
|
3
|
+
* the probe sends multiple ICMP echo requests per check. All RTT values
|
|
4
|
+
* are in milliseconds. Absent on older probes (single-echo pings) and when
|
|
5
|
+
* ICMP is blocked and the probe falls back to TCP port checks, which keeps
|
|
6
|
+
* the pipeline backwards-compatible.
|
|
7
|
+
*/
|
|
8
|
+
export default interface PingMonitorResponse {
|
|
9
|
+
packetsSent: number;
|
|
10
|
+
packetsReceived: number;
|
|
11
|
+
packetLossPercent: number;
|
|
12
|
+
minRoundTripTimeInMs?: number | undefined;
|
|
13
|
+
maxRoundTripTimeInMs?: number | undefined;
|
|
14
|
+
avgRoundTripTimeInMs?: number | undefined;
|
|
15
|
+
/*
|
|
16
|
+
* Jitter is the standard deviation of round-trip times across the
|
|
17
|
+
* packets sent in this check.
|
|
18
|
+
*/
|
|
19
|
+
jitterInMs?: number | undefined;
|
|
20
|
+
}
|