@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.
Files changed (244) hide show
  1. package/Models/DatabaseModels/AIRun.ts +50 -0
  2. package/Models/DatabaseModels/Project.ts +60 -0
  3. package/Server/API/AIAgentTaskAPI.ts +10 -24
  4. package/Server/API/AIInvestigationAPI.ts +148 -0
  5. package/Server/API/TelemetryAPI.ts +4 -3
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.ts +19 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.ts +33 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.ts +19 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  10. package/Server/Services/AIAgentTaskService.ts +62 -0
  11. package/Server/Services/AlertService.ts +25 -0
  12. package/Server/Services/AnalyticsDatabaseService.ts +27 -0
  13. package/Server/Services/IncidentService.ts +25 -0
  14. package/Server/Services/IncidentStateTimelineService.ts +19 -0
  15. package/Server/Services/LogAggregationService.ts +29 -11
  16. package/Server/Services/MetricService.ts +603 -13
  17. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +119 -11
  18. package/Server/Utils/AI/Sentinel/AlertInvestigationRunner.ts +141 -0
  19. package/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.ts +178 -0
  20. package/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.ts +105 -0
  21. package/Server/Utils/AI/Sentinel/README.md +10 -0
  22. package/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.ts +405 -0
  23. package/Server/Utils/AI/Sentinel/SentinelMemory.ts +167 -0
  24. package/Server/Utils/AI/Toolbox/Index.ts +11 -0
  25. package/Server/Utils/AI/Toolbox/SentinelActionTools.ts +577 -0
  26. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +44 -0
  27. package/Server/Utils/Monitor/MonitorMetricUtil.ts +108 -2
  28. package/Tests/Server/API/BaseAPI.test.ts +1 -0
  29. package/Tests/Server/Services/AIAgentTaskServiceClaim.test.ts +146 -0
  30. package/Tests/Server/Services/LogAggregationService.test.ts +22 -0
  31. package/Tests/Server/Services/MetricServiceAggregate.test.ts +194 -0
  32. package/Tests/Types/AI/AIAgentTaskStatus.test.ts +86 -0
  33. package/Tests/Types/BaseDatabase/AggregationIntervalUtil.test.ts +127 -0
  34. package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.test.ts +152 -0
  35. package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtil.test.ts +260 -0
  36. package/Tests/Types/Trace/TraceRecordingRuleDefinition.test.ts +308 -0
  37. package/Tests/UI/Components/Dropdown.test.tsx +17 -0
  38. package/Tests/UI/Components/EntityDropdown.test.tsx +130 -0
  39. package/Tests/UI/Components/Modal.test.tsx +144 -2
  40. package/Tests/UI/Components/TelemetrySearchBar.test.tsx +90 -0
  41. package/Tests/UI/Utils/Theme.test.ts +161 -0
  42. package/Types/BaseDatabase/AggregateBy.ts +12 -0
  43. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  44. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  45. package/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.ts +19 -0
  46. package/Types/Dashboard/DashboardTemplates.ts +9 -1
  47. package/Types/Date.ts +46 -0
  48. package/Types/Monitor/CriteriaFilter.ts +4 -0
  49. package/Types/Monitor/HttpPhaseTimings.ts +16 -0
  50. package/Types/Monitor/MonitorMetricType.ts +17 -0
  51. package/Types/Monitor/PingMonitor/PingMonitorResponse.ts +20 -0
  52. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +257 -0
  53. package/Types/Probe/ProbeMonitorResponse.ts +14 -0
  54. package/UI/Components/Calendar/Calendar.tsx +8 -2
  55. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +5 -5
  56. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +8 -5
  57. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +4 -1
  58. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +6 -3
  59. package/UI/Components/CodeBlock/CodeBlock.tsx +2 -1
  60. package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
  61. package/UI/Components/Divider/Divider.tsx +1 -1
  62. package/UI/Components/Dropdown/Dropdown.tsx +13 -4
  63. package/UI/Components/EntityDropdown/EntityDropdown.tsx +110 -2
  64. package/UI/Components/ErrorBoundary.tsx +2 -1
  65. package/UI/Components/EventItem/EventItem.tsx +2 -2
  66. package/UI/Components/GanttChart/Bar/Index.tsx +1 -1
  67. package/UI/Components/Graphs/UptimeBarTooltip.tsx +30 -23
  68. package/UI/Components/Header/Header.tsx +7 -0
  69. package/UI/Components/Header/HeaderIconDropdownButton.tsx +2 -0
  70. package/UI/Components/Label/Label.tsx +2 -2
  71. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +22 -10
  72. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +9 -3
  73. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +8 -8
  74. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +44 -20
  75. package/UI/Components/Modal/ConfirmModal.tsx +1 -1
  76. package/UI/Components/Modal/Modal.tsx +213 -121
  77. package/UI/Components/Modal/ModalFooter.tsx +33 -22
  78. package/UI/Components/ModelTable/TableView.tsx +1 -1
  79. package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +20 -12
  80. package/UI/Components/Pill/Pill.tsx +21 -13
  81. package/UI/Components/StatusBubble/StatusBubble.tsx +3 -3
  82. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +7 -1
  83. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +9 -3
  84. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +62 -4
  85. package/UI/Components/Workflow/Component.tsx +53 -33
  86. package/UI/Components/Workflow/ComponentPortViewer.tsx +6 -6
  87. package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +8 -8
  88. package/UI/Components/Workflow/ComponentsModal.tsx +16 -9
  89. package/UI/Components/Workflow/Workflow.tsx +13 -11
  90. package/UI/Utils/Theme.ts +140 -0
  91. package/Utils/Dashboard/Components/DashboardLogChartComponent.ts +104 -0
  92. package/Utils/Dashboard/Components/Index.ts +7 -0
  93. package/Utils/Monitor/MonitorMetricType.ts +70 -2
  94. package/build/dist/Models/DatabaseModels/AIRun.js +52 -0
  95. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  96. package/build/dist/Models/DatabaseModels/Project.js +62 -0
  97. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  98. package/build/dist/Server/API/AIAgentTaskAPI.js +8 -23
  99. package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
  100. package/build/dist/Server/API/AIInvestigationAPI.js +107 -0
  101. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -0
  102. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  103. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js +12 -0
  104. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783598145111-AddEnableAutomaticIncidentInvestigationToProject.js.map +1 -0
  105. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js +18 -0
  106. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783615884106-AddInvestigationSubjectToAIRun.js.map +1 -0
  107. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js +12 -0
  108. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783632447975-AddEnableAutomaticAlertInvestigationToProject.js.map +1 -0
  109. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  110. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  111. package/build/dist/Server/Services/AIAgentTaskService.js +59 -0
  112. package/build/dist/Server/Services/AIAgentTaskService.js.map +1 -1
  113. package/build/dist/Server/Services/AlertService.js +24 -0
  114. package/build/dist/Server/Services/AlertService.js.map +1 -1
  115. package/build/dist/Server/Services/AnalyticsDatabaseService.js +19 -0
  116. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  117. package/build/dist/Server/Services/IncidentService.js +24 -0
  118. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  119. package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
  120. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  121. package/build/dist/Server/Services/LogAggregationService.js +21 -7
  122. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  123. package/build/dist/Server/Services/MetricService.js +449 -7
  124. package/build/dist/Server/Services/MetricService.js.map +1 -1
  125. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +59 -11
  126. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  127. package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js +119 -0
  128. package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +1 -0
  129. package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js +147 -0
  130. package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +1 -0
  131. package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js +93 -0
  132. package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js.map +1 -0
  133. package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js +311 -0
  134. package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +1 -0
  135. package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js +143 -0
  136. package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js.map +1 -0
  137. package/build/dist/Server/Utils/AI/Toolbox/Index.js +6 -0
  138. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  139. package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js +451 -0
  140. package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js.map +1 -0
  141. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +29 -0
  142. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
  143. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +86 -2
  144. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  145. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  146. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  147. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  148. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  149. package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js +2 -0
  150. package/build/dist/Types/Dashboard/DashboardComponents/DashboardLogChartComponent.js.map +1 -0
  151. package/build/dist/Types/Dashboard/DashboardTemplates.js +9 -1
  152. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  153. package/build/dist/Types/Date.js +32 -0
  154. package/build/dist/Types/Date.js.map +1 -1
  155. package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
  156. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  157. package/build/dist/Types/Monitor/HttpPhaseTimings.js +2 -0
  158. package/build/dist/Types/Monitor/HttpPhaseTimings.js.map +1 -0
  159. package/build/dist/Types/Monitor/MonitorMetricType.js +15 -0
  160. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  161. package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js +2 -0
  162. package/build/dist/Types/Monitor/PingMonitor/PingMonitorResponse.js.map +1 -0
  163. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +159 -0
  164. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -0
  165. package/build/dist/UI/Components/Calendar/Calendar.js +2 -2
  166. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  167. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
  168. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  169. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +7 -4
  170. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  171. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +4 -1
  172. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  173. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +6 -3
  174. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  175. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +1 -1
  176. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  177. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +3 -1
  178. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  179. package/build/dist/UI/Components/Divider/Divider.js +1 -1
  180. package/build/dist/UI/Components/Divider/Divider.js.map +1 -1
  181. package/build/dist/UI/Components/Dropdown/Dropdown.js +10 -4
  182. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  183. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +76 -3
  184. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  185. package/build/dist/UI/Components/ErrorBoundary.js +2 -1
  186. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  187. package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
  188. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  189. package/build/dist/UI/Components/GanttChart/Bar/Index.js +1 -1
  190. package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +1 -1
  191. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +29 -23
  192. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
  193. package/build/dist/UI/Components/Header/Header.js +1 -0
  194. package/build/dist/UI/Components/Header/Header.js.map +1 -1
  195. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
  196. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  197. package/build/dist/UI/Components/Label/Label.js +2 -2
  198. package/build/dist/UI/Components/Label/Label.js.map +1 -1
  199. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +20 -8
  200. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  201. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +8 -2
  202. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  203. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +8 -8
  204. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +40 -20
  205. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  206. package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
  207. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  208. package/build/dist/UI/Components/Modal/Modal.js +109 -51
  209. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  210. package/build/dist/UI/Components/Modal/ModalFooter.js +13 -10
  211. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  212. package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
  213. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  214. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +17 -12
  215. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
  216. package/build/dist/UI/Components/Pill/Pill.js +12 -13
  217. package/build/dist/UI/Components/Pill/Pill.js.map +1 -1
  218. package/build/dist/UI/Components/StatusBubble/StatusBubble.js +3 -3
  219. package/build/dist/UI/Components/StatusBubble/StatusBubble.js.map +1 -1
  220. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
  221. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  222. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -2
  223. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  224. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +36 -6
  225. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  226. package/build/dist/UI/Components/Workflow/Component.js +43 -33
  227. package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
  228. package/build/dist/UI/Components/Workflow/ComponentPortViewer.js +6 -6
  229. package/build/dist/UI/Components/Workflow/ComponentPortViewer.js.map +1 -1
  230. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +8 -8
  231. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
  232. package/build/dist/UI/Components/Workflow/ComponentsModal.js +15 -9
  233. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  234. package/build/dist/UI/Components/Workflow/Workflow.js +13 -11
  235. package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
  236. package/build/dist/UI/Utils/Theme.js +106 -0
  237. package/build/dist/UI/Utils/Theme.js.map +1 -0
  238. package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js +92 -0
  239. package/build/dist/Utils/Dashboard/Components/DashboardLogChartComponent.js.map +1 -0
  240. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  241. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  242. package/build/dist/Utils/Monitor/MonitorMetricType.js +70 -3
  243. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  244. 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
  }
@@ -5,6 +5,7 @@ enum DashboardComponentType {
5
5
  Table = `Table`,
6
6
  Gauge = `Gauge`,
7
7
  LogStream = `LogStream`,
8
+ LogChart = `LogChart`,
8
9
  TraceList = `TraceList`,
9
10
  TraceChart = `TraceChart`,
10
11
  TraceTable = `TraceTable`,
@@ -27,6 +27,7 @@ export enum EntityFilterModelType {
27
27
  AlertState = "AlertState",
28
28
  MonitorStatus = "MonitorStatus",
29
29
  Monitor = "Monitor",
30
+ Service = "Service",
30
31
  Label = "Label",
31
32
  KubernetesCluster = "KubernetesCluster",
32
33
  DockerHost = "DockerHost",
@@ -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
- groupBy: config.groupByAttributeKeys ? { attributes: true } : undefined,
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
+ }