@oneuptime/common 10.4.8 → 10.4.9
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/Server/API/TelemetryExceptionAPI.ts +62 -0
- package/Server/Services/TelemetryExceptionService.ts +225 -0
- package/Server/Types/Database/QueryHelper.ts +35 -0
- package/Server/Types/Database/QueryUtil.ts +74 -2
- package/Types/Dashboard/DashboardComponents/DashboardAlertListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardDockerContainerListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardDockerHostListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardDockerImageListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardDockerNetworkListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardDockerVolumeListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardHostListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardIncidentListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesCronJobListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesDaemonSetListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesDeploymentListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesJobListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesNamespaceListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesNodeListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesPodListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardKubernetesStatefulSetListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardMonitorListComponent.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardTraceListComponent.ts +1 -0
- package/Types/Time/RangeStartAndEndDateTime.ts +8 -0
- package/Types/Time/TimeRange.ts +1 -0
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +1 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +64 -17
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +1 -0
- package/Utils/Dashboard/Components/DashboardAlertListComponent.ts +5 -0
- package/Utils/Dashboard/Components/DashboardDockerContainerListComponent.ts +7 -0
- package/Utils/Dashboard/Components/DashboardDockerHostListComponent.ts +5 -0
- package/Utils/Dashboard/Components/DashboardDockerImageListComponent.ts +5 -0
- package/Utils/Dashboard/Components/DashboardDockerNetworkListComponent.ts +5 -0
- package/Utils/Dashboard/Components/DashboardDockerVolumeListComponent.ts +5 -0
- package/Utils/Dashboard/Components/DashboardHostListComponent.ts +3 -0
- package/Utils/Dashboard/Components/DashboardIncidentListComponent.ts +5 -0
- package/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.ts +3 -0
- package/Utils/Dashboard/Components/DashboardListSharedArgs.ts +31 -0
- package/Utils/Dashboard/Components/DashboardMonitorListComponent.ts +5 -0
- package/Utils/Dashboard/Components/DashboardTraceListComponent.ts +5 -0
- package/build/dist/Server/API/TelemetryExceptionAPI.js +37 -1
- package/build/dist/Server/API/TelemetryExceptionAPI.js.map +1 -1
- package/build/dist/Server/Services/TelemetryExceptionService.js +175 -0
- package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +35 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryUtil.js +58 -2
- package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
- package/build/dist/Types/Time/RangeStartAndEndDateTime.js +4 -0
- package/build/dist/Types/Time/RangeStartAndEndDateTime.js.map +1 -1
- package/build/dist/Types/Time/TimeRange.js +1 -0
- package/build/dist/Types/Time/TimeRange.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +48 -13
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardAlertListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardAlertListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardDockerContainerListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDockerContainerListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardDockerHostListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDockerHostListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardDockerImageListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDockerImageListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardDockerNetworkListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDockerNetworkListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardDockerVolumeListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardDockerVolumeListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardHostListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardHostListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardIncidentListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardIncidentListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardListSharedArgs.js +21 -0
- package/build/dist/Utils/Dashboard/Components/DashboardListSharedArgs.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardTraceListComponent.js +2 -0
- package/build/dist/Utils/Dashboard/Components/DashboardTraceListComponent.js.map +1 -1
- package/package.json +1 -1
|
@@ -1807,17 +1807,21 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
|
|
|
1807
1807
|
(): BulkActionButtonSchema<TBaseModel> => {
|
|
1808
1808
|
return {
|
|
1809
1809
|
title: "Delete",
|
|
1810
|
-
buttonStyleType: ButtonStyleType.
|
|
1810
|
+
buttonStyleType: ButtonStyleType.DANGER,
|
|
1811
1811
|
icon: IconProp.Trash,
|
|
1812
1812
|
confirmMessage: (items: Array<TBaseModel>) => {
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1813
|
+
const itemLabel: string =
|
|
1814
|
+
items.length === 1
|
|
1815
|
+
? props.singularName || model.singularName || "item"
|
|
1816
|
+
: props.pluralName || model.pluralName || "items";
|
|
1817
|
+
return `Are you sure you want to delete ${items.length} ${itemLabel}? This action cannot be undone.`;
|
|
1816
1818
|
},
|
|
1817
1819
|
confirmTitle: (items: Array<TBaseModel>) => {
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1820
|
+
const itemLabel: string =
|
|
1821
|
+
items.length === 1
|
|
1822
|
+
? props.singularName || model.singularName || "item"
|
|
1823
|
+
: props.pluralName || model.pluralName || "items";
|
|
1824
|
+
return `Delete ${items.length} ${itemLabel}`;
|
|
1821
1825
|
},
|
|
1822
1826
|
confirmButtonStyleType: ButtonStyleType.DANGER,
|
|
1823
1827
|
onClick: async ({
|
|
@@ -1908,25 +1912,68 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
|
|
|
1908
1912
|
onFilterRefreshClick={async () => {
|
|
1909
1913
|
await getFilterDropdownItems();
|
|
1910
1914
|
}}
|
|
1911
|
-
bulkActions={{
|
|
1912
|
-
|
|
1915
|
+
bulkActions={(() => {
|
|
1916
|
+
const permissions: Array<Permission> =
|
|
1917
|
+
PermissionUtil.getAllPermissions();
|
|
1918
|
+
const userCanDelete: boolean =
|
|
1919
|
+
model.hasDeletePermissions(permissions);
|
|
1920
|
+
|
|
1921
|
+
const sourceButtons: Array<
|
|
1922
|
+
BulkActionButtonSchema<TBaseModel> | ModalTableBulkDefaultActions
|
|
1923
|
+
> = [...(props.bulkActions?.buttons ?? [])];
|
|
1924
|
+
|
|
1925
|
+
/*
|
|
1926
|
+
* Auto-include the default Delete bulk action whenever the user has
|
|
1927
|
+
* model-level delete permission, so every table that exposes row
|
|
1928
|
+
* selection also exposes a way to delete the selected rows. This is
|
|
1929
|
+
* intentionally decoupled from `isDeleteable` — that flag governs the
|
|
1930
|
+
* per-row Delete button in the Actions column, not bulk operations.
|
|
1931
|
+
* The confirmation modal is wired up via the schema's confirmMessage
|
|
1932
|
+
* / confirmTitle below. Skip if the table author already added it.
|
|
1933
|
+
*/
|
|
1934
|
+
const alreadyHasDeleteAction: boolean = sourceButtons.some(
|
|
1913
1935
|
(
|
|
1914
1936
|
action:
|
|
1915
1937
|
| BulkActionButtonSchema<TBaseModel>
|
|
1916
1938
|
| ModalTableBulkDefaultActions,
|
|
1917
1939
|
) => {
|
|
1918
|
-
|
|
1919
|
-
|
|
1940
|
+
if (action === ModalTableBulkDefaultActions.Delete) {
|
|
1941
|
+
return true;
|
|
1942
|
+
}
|
|
1920
1943
|
if (
|
|
1921
|
-
action ===
|
|
1922
|
-
|
|
1944
|
+
typeof action === "object" &&
|
|
1945
|
+
action !== null &&
|
|
1946
|
+
"title" in action &&
|
|
1947
|
+
(action as BulkActionButtonSchema<TBaseModel>).title ===
|
|
1948
|
+
"Delete"
|
|
1923
1949
|
) {
|
|
1924
|
-
return
|
|
1950
|
+
return true;
|
|
1925
1951
|
}
|
|
1926
|
-
return
|
|
1952
|
+
return false;
|
|
1927
1953
|
},
|
|
1928
|
-
)
|
|
1929
|
-
|
|
1954
|
+
);
|
|
1955
|
+
if (userCanDelete && !alreadyHasDeleteAction) {
|
|
1956
|
+
sourceButtons.push(ModalTableBulkDefaultActions.Delete);
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
return {
|
|
1960
|
+
buttons: sourceButtons.map(
|
|
1961
|
+
(
|
|
1962
|
+
action:
|
|
1963
|
+
| BulkActionButtonSchema<TBaseModel>
|
|
1964
|
+
| ModalTableBulkDefaultActions,
|
|
1965
|
+
) => {
|
|
1966
|
+
if (
|
|
1967
|
+
action === ModalTableBulkDefaultActions.Delete &&
|
|
1968
|
+
userCanDelete
|
|
1969
|
+
) {
|
|
1970
|
+
return getDeleteBulkAction();
|
|
1971
|
+
}
|
|
1972
|
+
return action;
|
|
1973
|
+
},
|
|
1974
|
+
) as Array<BulkActionButtonSchema<TBaseModel>>,
|
|
1975
|
+
};
|
|
1976
|
+
})()}
|
|
1930
1977
|
onBulkActionEnd={async () => {
|
|
1931
1978
|
setBulkSelectedItems([]);
|
|
1932
1979
|
await fetchItems();
|
|
@@ -21,6 +21,7 @@ export interface TelemetryTimeRangePickerProps {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const PRESET_OPTIONS: Array<{ range: TimeRange; label: string }> = [
|
|
24
|
+
{ range: TimeRange.PAST_FIVE_MINS, label: "Past 5 Minutes" },
|
|
24
25
|
{ range: TimeRange.PAST_THIRTY_MINS, label: "Past 30 Minutes" },
|
|
25
26
|
{ range: TimeRange.PAST_ONE_HOUR, label: "Past 1 Hour" },
|
|
26
27
|
{ range: TimeRange.PAST_TWO_HOURS, label: "Past 2 Hours" },
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
EntityFilterModelType,
|
|
10
10
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
11
11
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
12
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
12
13
|
|
|
13
14
|
const DisplaySection: ComponentArgumentSection = {
|
|
14
15
|
name: "Display Options",
|
|
@@ -67,6 +68,10 @@ export default class DashboardAlertListComponentUtil extends DashboardBaseCompon
|
|
|
67
68
|
section: DisplaySection,
|
|
68
69
|
});
|
|
69
70
|
|
|
71
|
+
componentArguments.push(
|
|
72
|
+
getViewModeArgument<DashboardAlertListComponent>(DisplaySection),
|
|
73
|
+
);
|
|
74
|
+
|
|
70
75
|
componentArguments.push({
|
|
71
76
|
name: "Lifecycle State",
|
|
72
77
|
description: "Quick filter by lifecycle state",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
EntityFilterModelType,
|
|
10
10
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
11
11
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
12
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
12
13
|
|
|
13
14
|
const DisplaySection: ComponentArgumentSection = {
|
|
14
15
|
name: "Display Options",
|
|
@@ -67,6 +68,12 @@ export default class DashboardDockerContainerListComponentUtil extends Dashboard
|
|
|
67
68
|
section: DisplaySection,
|
|
68
69
|
});
|
|
69
70
|
|
|
71
|
+
args.push(
|
|
72
|
+
getViewModeArgument<DashboardDockerContainerListComponent>(
|
|
73
|
+
DisplaySection,
|
|
74
|
+
),
|
|
75
|
+
);
|
|
76
|
+
|
|
70
77
|
args.push({
|
|
71
78
|
name: "Hosts",
|
|
72
79
|
description: "Show only containers from the selected hosts",
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ComponentInputType,
|
|
9
9
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
10
10
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
11
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
11
12
|
|
|
12
13
|
const DisplaySection: ComponentArgumentSection = {
|
|
13
14
|
name: "Display Options",
|
|
@@ -64,6 +65,10 @@ export default class DashboardDockerHostListComponentUtil extends DashboardBaseC
|
|
|
64
65
|
section: DisplaySection,
|
|
65
66
|
});
|
|
66
67
|
|
|
68
|
+
args.push(
|
|
69
|
+
getViewModeArgument<DashboardDockerHostListComponent>(DisplaySection),
|
|
70
|
+
);
|
|
71
|
+
|
|
67
72
|
args.push({
|
|
68
73
|
name: "Connection Status",
|
|
69
74
|
description: "Quick filter by OTel collector status",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
EntityFilterModelType,
|
|
10
10
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
11
11
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
12
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
12
13
|
|
|
13
14
|
const DisplaySection: ComponentArgumentSection = {
|
|
14
15
|
name: "Display Options",
|
|
@@ -66,6 +67,10 @@ export default class DashboardDockerImageListComponentUtil extends DashboardBase
|
|
|
66
67
|
section: DisplaySection,
|
|
67
68
|
});
|
|
68
69
|
|
|
70
|
+
args.push(
|
|
71
|
+
getViewModeArgument<DashboardDockerImageListComponent>(DisplaySection),
|
|
72
|
+
);
|
|
73
|
+
|
|
69
74
|
args.push({
|
|
70
75
|
name: "Hosts",
|
|
71
76
|
description: "Show only images from the selected hosts",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
EntityFilterModelType,
|
|
10
10
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
11
11
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
12
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
12
13
|
|
|
13
14
|
const DisplaySection: ComponentArgumentSection = {
|
|
14
15
|
name: "Display Options",
|
|
@@ -66,6 +67,10 @@ export default class DashboardDockerNetworkListComponentUtil extends DashboardBa
|
|
|
66
67
|
section: DisplaySection,
|
|
67
68
|
});
|
|
68
69
|
|
|
70
|
+
args.push(
|
|
71
|
+
getViewModeArgument<DashboardDockerNetworkListComponent>(DisplaySection),
|
|
72
|
+
);
|
|
73
|
+
|
|
69
74
|
args.push({
|
|
70
75
|
name: "Hosts",
|
|
71
76
|
description: "Show only networks from the selected hosts",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
EntityFilterModelType,
|
|
10
10
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
11
11
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
12
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
12
13
|
|
|
13
14
|
const DisplaySection: ComponentArgumentSection = {
|
|
14
15
|
name: "Display Options",
|
|
@@ -66,6 +67,10 @@ export default class DashboardDockerVolumeListComponentUtil extends DashboardBas
|
|
|
66
67
|
section: DisplaySection,
|
|
67
68
|
});
|
|
68
69
|
|
|
70
|
+
args.push(
|
|
71
|
+
getViewModeArgument<DashboardDockerVolumeListComponent>(DisplaySection),
|
|
72
|
+
);
|
|
73
|
+
|
|
69
74
|
args.push({
|
|
70
75
|
name: "Hosts",
|
|
71
76
|
description: "Show only volumes from the selected hosts",
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ComponentInputType,
|
|
9
9
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
10
10
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
11
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
11
12
|
|
|
12
13
|
const DisplaySection: ComponentArgumentSection = {
|
|
13
14
|
name: "Display Options",
|
|
@@ -64,6 +65,8 @@ export default class DashboardHostListComponentUtil extends DashboardBaseCompone
|
|
|
64
65
|
section: DisplaySection,
|
|
65
66
|
});
|
|
66
67
|
|
|
68
|
+
args.push(getViewModeArgument<DashboardHostListComponent>(DisplaySection));
|
|
69
|
+
|
|
67
70
|
args.push({
|
|
68
71
|
name: "Connection Status",
|
|
69
72
|
description: "Quick filter by OTel collector status",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
EntityFilterModelType,
|
|
10
10
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
11
11
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
12
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
12
13
|
|
|
13
14
|
const DisplaySection: ComponentArgumentSection = {
|
|
14
15
|
name: "Display Options",
|
|
@@ -67,6 +68,10 @@ export default class DashboardIncidentListComponentUtil extends DashboardBaseCom
|
|
|
67
68
|
section: DisplaySection,
|
|
68
69
|
});
|
|
69
70
|
|
|
71
|
+
componentArguments.push(
|
|
72
|
+
getViewModeArgument<DashboardIncidentListComponent>(DisplaySection),
|
|
73
|
+
);
|
|
74
|
+
|
|
70
75
|
componentArguments.push({
|
|
71
76
|
name: "Lifecycle State",
|
|
72
77
|
description: "Quick filter by lifecycle state",
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
EntityFilterModelType,
|
|
6
6
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
7
7
|
import DashboardBaseComponent from "../../../Types/Dashboard/DashboardComponents/DashboardBaseComponent";
|
|
8
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
8
9
|
|
|
9
10
|
export const KubernetesDisplaySection: ComponentArgumentSection = {
|
|
10
11
|
name: "Display Options",
|
|
@@ -47,6 +48,8 @@ export function getKubernetesCommonArguments<T extends DashboardBaseComponent>(
|
|
|
47
48
|
section: KubernetesDisplaySection,
|
|
48
49
|
});
|
|
49
50
|
|
|
51
|
+
args.push(getViewModeArgument<T>(KubernetesDisplaySection));
|
|
52
|
+
|
|
50
53
|
args.push({
|
|
51
54
|
name: "Clusters",
|
|
52
55
|
description: "Show only resources from the selected clusters",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ComponentArgument,
|
|
3
|
+
ComponentArgumentSection,
|
|
4
|
+
ComponentInputType,
|
|
5
|
+
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
6
|
+
import DashboardBaseComponent from "../../../Types/Dashboard/DashboardComponents/DashboardBaseComponent";
|
|
7
|
+
|
|
8
|
+
export type DashboardListViewMode = "list" | "honeycomb";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns the `viewMode` dropdown argument used by every dashboard list
|
|
12
|
+
* component to switch between the default table view and a status-colored
|
|
13
|
+
* honeycomb view.
|
|
14
|
+
*/
|
|
15
|
+
export function getViewModeArgument<T extends DashboardBaseComponent>(
|
|
16
|
+
section: ComponentArgumentSection,
|
|
17
|
+
): ComponentArgument<T> {
|
|
18
|
+
return {
|
|
19
|
+
name: "View Mode",
|
|
20
|
+
description:
|
|
21
|
+
"Show entries as a list (default) or as a honeycomb where each cell is colored by status.",
|
|
22
|
+
required: false,
|
|
23
|
+
type: ComponentInputType.Dropdown,
|
|
24
|
+
id: "viewMode" as keyof T["arguments"],
|
|
25
|
+
section: section,
|
|
26
|
+
dropdownOptions: [
|
|
27
|
+
{ label: "List", value: "list" },
|
|
28
|
+
{ label: "Honeycomb", value: "honeycomb" },
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
MonitorTypeProps,
|
|
15
15
|
} from "../../../Types/Monitor/MonitorType";
|
|
16
16
|
import { DropdownOption } from "../../../UI/Components/Dropdown/Dropdown";
|
|
17
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
17
18
|
|
|
18
19
|
const DisplaySection: ComponentArgumentSection = {
|
|
19
20
|
name: "Display Options",
|
|
@@ -90,6 +91,10 @@ export default class DashboardMonitorListComponentUtil extends DashboardBaseComp
|
|
|
90
91
|
section: DisplaySection,
|
|
91
92
|
});
|
|
92
93
|
|
|
94
|
+
componentArguments.push(
|
|
95
|
+
getViewModeArgument<DashboardMonitorListComponent>(DisplaySection),
|
|
96
|
+
);
|
|
97
|
+
|
|
93
98
|
componentArguments.push({
|
|
94
99
|
name: "Operational Status",
|
|
95
100
|
description: "Quick filter by operational state",
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ComponentInputType,
|
|
9
9
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
10
10
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
11
|
+
import { getViewModeArgument } from "./DashboardListSharedArgs";
|
|
11
12
|
|
|
12
13
|
const DisplaySection: ComponentArgumentSection = {
|
|
13
14
|
name: "Display Options",
|
|
@@ -66,6 +67,10 @@ export default class DashboardTraceListComponentUtil extends DashboardBaseCompon
|
|
|
66
67
|
section: DisplaySection,
|
|
67
68
|
});
|
|
68
69
|
|
|
70
|
+
componentArguments.push(
|
|
71
|
+
getViewModeArgument<DashboardTraceListComponent>(DisplaySection),
|
|
72
|
+
);
|
|
73
|
+
|
|
69
74
|
componentArguments.push({
|
|
70
75
|
name: "Status",
|
|
71
76
|
description: "Show only traces with this status",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import TelemetryException from "../../Models/DatabaseModels/TelemetryException";
|
|
2
|
+
import TelemetryServiceModel from "../../Models/DatabaseModels/Service";
|
|
2
3
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
3
4
|
import ObjectID from "../../Types/ObjectID";
|
|
5
|
+
import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
4
6
|
import TelemetryExceptionService from "../Services/TelemetryExceptionService";
|
|
5
7
|
import AIAgentTaskTelemetryExceptionService from "../Services/AIAgentTaskTelemetryExceptionService";
|
|
6
8
|
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
@@ -11,7 +13,7 @@ import AIAgentTaskStatus, { AIAgentTaskStatusHelper, } from "../../Types/AI/AIAg
|
|
|
11
13
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
12
14
|
export default class TelemetryExceptionAPI extends BaseAPI {
|
|
13
15
|
constructor() {
|
|
14
|
-
var _a, _b;
|
|
16
|
+
var _a, _b, _c;
|
|
15
17
|
super(TelemetryException, TelemetryExceptionService);
|
|
16
18
|
// Create AI Agent Task for an exception
|
|
17
19
|
this.router.post(`${(_a = new this.entityType()
|
|
@@ -33,6 +35,19 @@ export default class TelemetryExceptionAPI extends BaseAPI {
|
|
|
33
35
|
next(err);
|
|
34
36
|
}
|
|
35
37
|
});
|
|
38
|
+
/*
|
|
39
|
+
* Aggregated dashboard summary for the Exceptions overview page.
|
|
40
|
+
* Returns counts, top/recent exceptions, and per-service summaries
|
|
41
|
+
* in a single round-trip with one SQL GROUP BY for service aggregation.
|
|
42
|
+
*/
|
|
43
|
+
this.router.post(`${(_c = new this.entityType().getCrudApiPath()) === null || _c === void 0 ? void 0 : _c.toString()}/dashboard-summary`, UserMiddleware.getUserMiddleware, async (req, res, next) => {
|
|
44
|
+
try {
|
|
45
|
+
await this.getDashboardSummary(req, res);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
next(err);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
36
51
|
}
|
|
37
52
|
async createAIAgentTask(req, res) {
|
|
38
53
|
const telemetryExceptionIdParam = req.params["telemetryExceptionId"];
|
|
@@ -116,5 +131,26 @@ export default class TelemetryExceptionAPI extends BaseAPI {
|
|
|
116
131
|
},
|
|
117
132
|
});
|
|
118
133
|
}
|
|
134
|
+
async getDashboardSummary(req, res) {
|
|
135
|
+
const props = await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
136
|
+
const summary = await this.service.getDashboardSummary(props);
|
|
137
|
+
const topExceptionsJson = BaseModel.toJSONArray(summary.topExceptions, TelemetryException);
|
|
138
|
+
const recentExceptionsJson = BaseModel.toJSONArray(summary.recentExceptions, TelemetryException);
|
|
139
|
+
const serviceSummariesJson = summary.serviceSummaries.map((entry) => {
|
|
140
|
+
return {
|
|
141
|
+
service: BaseModel.toJSON(entry.service, TelemetryServiceModel),
|
|
142
|
+
unresolvedCount: entry.unresolvedCount,
|
|
143
|
+
totalOccurrences: entry.totalOccurrences,
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
147
|
+
unresolvedCount: summary.unresolvedCount,
|
|
148
|
+
resolvedCount: summary.resolvedCount,
|
|
149
|
+
archivedCount: summary.archivedCount,
|
|
150
|
+
topExceptions: topExceptionsJson,
|
|
151
|
+
recentExceptions: recentExceptionsJson,
|
|
152
|
+
serviceSummaries: serviceSummariesJson,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
119
155
|
}
|
|
120
156
|
//# sourceMappingURL=TelemetryExceptionAPI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TelemetryExceptionAPI.js","sourceRoot":"","sources":["../../../../Server/API/TelemetryExceptionAPI.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,gDAAgD,CAAC;
|
|
1
|
+
{"version":3,"file":"TelemetryExceptionAPI.js","sourceRoot":"","sources":["../../../../Server/API/TelemetryExceptionAPI.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,12 +11,16 @@ import DatabaseService from "./DatabaseService";
|
|
|
11
11
|
import Model from "../../Models/DatabaseModels/TelemetryException";
|
|
12
12
|
import AIAgentTask from "../../Models/DatabaseModels/AIAgentTask";
|
|
13
13
|
import ObjectID from "../../Types/ObjectID";
|
|
14
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
15
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
14
16
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
15
17
|
import AIAgentTaskType from "../../Types/AI/AIAgentTaskType";
|
|
16
18
|
import AIAgentTaskStatus from "../../Types/AI/AIAgentTaskStatus";
|
|
17
19
|
import AIAgentTaskService from "./AIAgentTaskService";
|
|
18
20
|
import AIAgentTaskTelemetryExceptionService from "./AIAgentTaskTelemetryExceptionService";
|
|
21
|
+
import ServiceService from "./ServiceService";
|
|
19
22
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
23
|
+
import ModelPermission from "../Types/Database/Permissions/Index";
|
|
20
24
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
21
25
|
export class Service extends DatabaseService {
|
|
22
26
|
constructor() {
|
|
@@ -105,6 +109,165 @@ export class Service extends DatabaseService {
|
|
|
105
109
|
}
|
|
106
110
|
return createdTask;
|
|
107
111
|
}
|
|
112
|
+
async getDashboardSummary(props) {
|
|
113
|
+
if (!props.tenantId) {
|
|
114
|
+
throw new BadDataException("Project ID is required");
|
|
115
|
+
}
|
|
116
|
+
const projectId = props.tenantId;
|
|
117
|
+
const exceptionSelect = {
|
|
118
|
+
_id: true,
|
|
119
|
+
message: true,
|
|
120
|
+
exceptionType: true,
|
|
121
|
+
fingerprint: true,
|
|
122
|
+
isResolved: true,
|
|
123
|
+
isArchived: true,
|
|
124
|
+
occuranceCount: true,
|
|
125
|
+
lastSeenAt: true,
|
|
126
|
+
firstSeenAt: true,
|
|
127
|
+
environment: true,
|
|
128
|
+
service: {
|
|
129
|
+
_id: true,
|
|
130
|
+
name: true,
|
|
131
|
+
serviceColor: true,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
const [unresolvedCount, resolvedCount, archivedCount, topExceptions, recentExceptions, serviceSummaries,] = await Promise.all([
|
|
135
|
+
this.countBy({
|
|
136
|
+
query: {
|
|
137
|
+
projectId,
|
|
138
|
+
isResolved: false,
|
|
139
|
+
isArchived: false,
|
|
140
|
+
},
|
|
141
|
+
props,
|
|
142
|
+
}),
|
|
143
|
+
this.countBy({
|
|
144
|
+
query: {
|
|
145
|
+
projectId,
|
|
146
|
+
isResolved: true,
|
|
147
|
+
isArchived: false,
|
|
148
|
+
},
|
|
149
|
+
props,
|
|
150
|
+
}),
|
|
151
|
+
this.countBy({
|
|
152
|
+
query: {
|
|
153
|
+
projectId,
|
|
154
|
+
isArchived: true,
|
|
155
|
+
},
|
|
156
|
+
props,
|
|
157
|
+
}),
|
|
158
|
+
this.findBy({
|
|
159
|
+
query: {
|
|
160
|
+
projectId,
|
|
161
|
+
isResolved: false,
|
|
162
|
+
isArchived: false,
|
|
163
|
+
},
|
|
164
|
+
select: exceptionSelect,
|
|
165
|
+
limit: 10,
|
|
166
|
+
skip: 0,
|
|
167
|
+
sort: {
|
|
168
|
+
occuranceCount: SortOrder.Descending,
|
|
169
|
+
},
|
|
170
|
+
props,
|
|
171
|
+
}),
|
|
172
|
+
this.findBy({
|
|
173
|
+
query: {
|
|
174
|
+
projectId,
|
|
175
|
+
isResolved: false,
|
|
176
|
+
isArchived: false,
|
|
177
|
+
},
|
|
178
|
+
select: exceptionSelect,
|
|
179
|
+
limit: 5,
|
|
180
|
+
skip: 0,
|
|
181
|
+
sort: {
|
|
182
|
+
lastSeenAt: SortOrder.Descending,
|
|
183
|
+
},
|
|
184
|
+
props,
|
|
185
|
+
}),
|
|
186
|
+
this.aggregateUnresolvedByService(projectId, props),
|
|
187
|
+
]);
|
|
188
|
+
return {
|
|
189
|
+
unresolvedCount: unresolvedCount.toNumber(),
|
|
190
|
+
resolvedCount: resolvedCount.toNumber(),
|
|
191
|
+
archivedCount: archivedCount.toNumber(),
|
|
192
|
+
topExceptions,
|
|
193
|
+
recentExceptions,
|
|
194
|
+
serviceSummaries,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
async aggregateUnresolvedByService(projectId, props) {
|
|
198
|
+
/*
|
|
199
|
+
* Assert the caller has read permission on TelemetryException. We don't
|
|
200
|
+
* use the returned filtered query — we run a raw GROUP BY below for
|
|
201
|
+
* efficiency — but this throws if the user lacks read access.
|
|
202
|
+
*/
|
|
203
|
+
await ModelPermission.checkReadQueryPermission(Model, {
|
|
204
|
+
projectId,
|
|
205
|
+
isResolved: false,
|
|
206
|
+
isArchived: false,
|
|
207
|
+
}, null, props);
|
|
208
|
+
const rows = (await this.getQueryBuilder("TelemetryException")
|
|
209
|
+
.select(`"TelemetryException"."serviceId"`, "serviceId")
|
|
210
|
+
.addSelect(`COUNT(*)`, "unresolvedCount")
|
|
211
|
+
.addSelect(`COALESCE(SUM("TelemetryException"."occuranceCount"), 0)`, "totalOccurrences")
|
|
212
|
+
.where(`"TelemetryException"."projectId" = :projectId`, {
|
|
213
|
+
projectId: projectId.toString(),
|
|
214
|
+
})
|
|
215
|
+
.andWhere(`"TelemetryException"."isResolved" = false`)
|
|
216
|
+
.andWhere(`"TelemetryException"."isArchived" = false`)
|
|
217
|
+
.andWhere(`"TelemetryException"."deletedAt" IS NULL`)
|
|
218
|
+
.andWhere(`"TelemetryException"."serviceId" IS NOT NULL`)
|
|
219
|
+
.groupBy(`"TelemetryException"."serviceId"`)
|
|
220
|
+
.orderBy(`"unresolvedCount"`, "DESC")
|
|
221
|
+
.getRawMany());
|
|
222
|
+
if (rows.length === 0) {
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
const serviceIds = [];
|
|
226
|
+
for (const row of rows) {
|
|
227
|
+
if (row.serviceId) {
|
|
228
|
+
serviceIds.push(row.serviceId);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (serviceIds.length === 0) {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
const services = await ServiceService.findBy({
|
|
235
|
+
query: {
|
|
236
|
+
projectId,
|
|
237
|
+
_id: QueryHelper.any(serviceIds),
|
|
238
|
+
},
|
|
239
|
+
select: {
|
|
240
|
+
_id: true,
|
|
241
|
+
name: true,
|
|
242
|
+
serviceColor: true,
|
|
243
|
+
},
|
|
244
|
+
limit: new PositiveNumber(serviceIds.length),
|
|
245
|
+
skip: new PositiveNumber(0),
|
|
246
|
+
props,
|
|
247
|
+
});
|
|
248
|
+
const serviceById = new Map();
|
|
249
|
+
for (const service of services) {
|
|
250
|
+
if (service._id) {
|
|
251
|
+
serviceById.set(service._id, service);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const summaries = [];
|
|
255
|
+
for (const row of rows) {
|
|
256
|
+
if (!row.serviceId) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const service = serviceById.get(row.serviceId);
|
|
260
|
+
if (!service) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
summaries.push({
|
|
264
|
+
service,
|
|
265
|
+
unresolvedCount: parseInt(row.unresolvedCount, 10) || 0,
|
|
266
|
+
totalOccurrences: parseInt(row.totalOccurrences || "0", 10) || 0,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return summaries;
|
|
270
|
+
}
|
|
108
271
|
buildFixExceptionMetadata(params) {
|
|
109
272
|
const { telemetryException, telemetryExceptionId } = params;
|
|
110
273
|
const metadata = {
|
|
@@ -141,5 +304,17 @@ __decorate([
|
|
|
141
304
|
__metadata("design:paramtypes", [Object]),
|
|
142
305
|
__metadata("design:returntype", Promise)
|
|
143
306
|
], Service.prototype, "createFixExceptionTask", null);
|
|
307
|
+
__decorate([
|
|
308
|
+
CaptureSpan(),
|
|
309
|
+
__metadata("design:type", Function),
|
|
310
|
+
__metadata("design:paramtypes", [Object]),
|
|
311
|
+
__metadata("design:returntype", Promise)
|
|
312
|
+
], Service.prototype, "getDashboardSummary", null);
|
|
313
|
+
__decorate([
|
|
314
|
+
CaptureSpan(),
|
|
315
|
+
__metadata("design:type", Function),
|
|
316
|
+
__metadata("design:paramtypes", [ObjectID, Object]),
|
|
317
|
+
__metadata("design:returntype", Promise)
|
|
318
|
+
], Service.prototype, "aggregateUnresolvedByService", null);
|
|
144
319
|
export default new Service();
|
|
145
320
|
//# sourceMappingURL=TelemetryExceptionService.js.map
|