ydb-embedded-ui 4.16.2 → 4.18.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +30 -0
- package/dist/components/CircularProgressBar/CircularProgressBar.scss +42 -0
- package/dist/components/CircularProgressBar/CircularProgressBar.tsx +59 -0
- package/dist/components/DiagnosticCard/DiagnosticCard.scss +20 -3
- package/dist/components/DiagnosticCard/DiagnosticCard.tsx +5 -6
- package/dist/components/FullNodeViewer/FullNodeViewer.tsx +2 -2
- package/dist/components/InfoViewer/formatters/common.ts +1 -1
- package/dist/components/InfoViewer/formatters/pqGroup.ts +1 -1
- package/dist/components/InfoViewer/formatters/table.ts +6 -1
- package/dist/components/ProgressViewer/ProgressViewer.tsx +99 -0
- package/dist/components/TooltipsContent/TabletTooltipContent/TabletTooltipContent.tsx +1 -1
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +3 -1
- package/dist/containers/Authentication/Authentication.tsx +14 -4
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +2 -2
- package/dist/containers/Heatmap/Heatmap.tsx +1 -1
- package/dist/containers/Heatmap/Histogram/Histogram.js +1 -1
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +2 -2
- package/dist/containers/Node/NodeStructure/Vdisk.tsx +5 -2
- package/dist/containers/Nodes/getNodesColumns.tsx +2 -2
- package/dist/containers/Storage/PDisk/PDisk.tsx +1 -1
- package/dist/containers/Storage/PDiskPopup/PDiskPopup.tsx +1 -1
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +1 -1
- package/dist/containers/Storage/VDisk/VDisk.tsx +1 -1
- package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +1 -1
- package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +1 -1
- package/dist/containers/Tablet/TabletTable/TabletTable.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/ConsumersTopicStats.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +1 -5
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +40 -17
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Details/Details.tsx +3 -3
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Healthcheck.scss +27 -14
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Healthcheck.tsx +6 -6
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Preview/Preview.tsx +15 -16
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/Healthcheck.scss +108 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckDetails.tsx +45 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx +83 -0
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTree.scss +1 -3
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTree.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/IssueTreeItem.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/en.json +2 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/index.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/ru.json +2 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricCard/MetricCard.scss +52 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricCard/MetricCard.tsx +48 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.scss +12 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +134 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/OldTenantOverview.tsx +155 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +3 -5
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +76 -86
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +3 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +3 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/useHealthcheck.ts +53 -0
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +1 -1
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +1 -1
- package/dist/containers/Tenant/TenantPages.tsx +1 -0
- package/dist/containers/Tenants/Tenants.tsx +5 -1
- package/dist/containers/UserSettings/i18n/en.json +4 -1
- package/dist/containers/UserSettings/i18n/ru.json +4 -1
- package/dist/containers/UserSettings/settings.ts +7 -0
- package/dist/containers/Versions/NodesTable/NodesTable.tsx +2 -2
- package/dist/services/api.ts +6 -4
- package/dist/store/reducers/clusterNodes/clusterNodes.tsx +1 -1
- package/dist/store/reducers/healthcheckInfo.ts +20 -12
- package/dist/store/reducers/node/selectors.ts +1 -1
- package/dist/store/reducers/nodes/selectors.ts +1 -1
- package/dist/store/reducers/nodes/types.ts +1 -1
- package/dist/store/reducers/nodes/utils.ts +1 -1
- package/dist/store/reducers/settings/settings.ts +6 -1
- package/dist/store/reducers/storage/types.ts +1 -1
- package/dist/store/reducers/storage/utils.ts +1 -1
- package/dist/store/reducers/tenant/constants.ts +7 -0
- package/dist/store/reducers/tenant/tenant.ts +15 -0
- package/dist/store/reducers/tenant/types.ts +5 -0
- package/dist/store/reducers/tenants/contants.ts +6 -0
- package/dist/store/reducers/tenants/types.ts +4 -0
- package/dist/store/reducers/tenants/utils.ts +114 -7
- package/dist/store/state-url-mapping.js +3 -0
- package/dist/styles/constants.scss +2 -0
- package/dist/types/api/tenant.ts +3 -0
- package/dist/types/api/vdisk.ts +1 -1
- package/dist/utils/bytesParsers/formatBytes.ts +1 -1
- package/dist/utils/constants.ts +2 -0
- package/dist/utils/dataFormatters/dataFormatters.ts +128 -0
- package/dist/utils/dataFormatters/i18n/en.json +3 -0
- package/dist/utils/dataFormatters/i18n/index.ts +11 -0
- package/dist/utils/dataFormatters/i18n/ru.json +3 -0
- package/dist/utils/index.js +0 -102
- package/package.json +1 -1
- package/dist/components/ProgressViewer/ProgressViewer.js +0 -92
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Details/index.ts +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Preview/index.ts +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/index.ts +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/IssueTreeItem.scss +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/index.ts +0 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
import {useCallback} from 'react';
|
2
|
+
import {useDispatch} from 'react-redux';
|
3
|
+
|
4
|
+
import {
|
5
|
+
getHealthcheckInfo,
|
6
|
+
selectIssuesStatistics,
|
7
|
+
selectIssuesTrees,
|
8
|
+
setDataWasNotLoaded,
|
9
|
+
} from '../../../../store/reducers/healthcheckInfo';
|
10
|
+
import type {IIssuesTree} from '../../../../types/store/healthcheck';
|
11
|
+
import {type StatusFlag, SelfCheckResult} from '../../../../types/api/healthcheck';
|
12
|
+
import type {IResponseError} from '../../../../types/api/error';
|
13
|
+
import {useTypedSelector} from '../../../../utils/hooks/useTypedSelector';
|
14
|
+
|
15
|
+
interface HealthcheckParams {
|
16
|
+
issueTrees: IIssuesTree[];
|
17
|
+
issuesStatistics: [StatusFlag, number][];
|
18
|
+
fetchHealthcheck: (isBackground?: boolean) => void;
|
19
|
+
loading: boolean;
|
20
|
+
wasLoaded: boolean;
|
21
|
+
error?: IResponseError;
|
22
|
+
selfCheckResult: SelfCheckResult;
|
23
|
+
}
|
24
|
+
|
25
|
+
export const useHealthcheck = (tenantName: string): HealthcheckParams => {
|
26
|
+
const dispatch = useDispatch();
|
27
|
+
|
28
|
+
const {data, loading, wasLoaded, error} = useTypedSelector((state) => state.healthcheckInfo);
|
29
|
+
const selfCheckResult = data?.self_check_result || SelfCheckResult.UNSPECIFIED;
|
30
|
+
const issuesStatistics = useTypedSelector(selectIssuesStatistics);
|
31
|
+
const issueTrees = useTypedSelector(selectIssuesTrees);
|
32
|
+
|
33
|
+
const fetchHealthcheck = useCallback(
|
34
|
+
(isBackground = true) => {
|
35
|
+
if (!isBackground) {
|
36
|
+
dispatch(setDataWasNotLoaded());
|
37
|
+
}
|
38
|
+
|
39
|
+
dispatch(getHealthcheckInfo(tenantName));
|
40
|
+
},
|
41
|
+
[dispatch, tenantName],
|
42
|
+
);
|
43
|
+
|
44
|
+
return {
|
45
|
+
issueTrees,
|
46
|
+
issuesStatistics,
|
47
|
+
fetchHealthcheck,
|
48
|
+
loading,
|
49
|
+
wasLoaded,
|
50
|
+
error,
|
51
|
+
selfCheckResult,
|
52
|
+
};
|
53
|
+
};
|
@@ -28,7 +28,7 @@ import {
|
|
28
28
|
TENANT_PAGES_IDS,
|
29
29
|
TENANT_QUERY_TABS_ID,
|
30
30
|
} from '../../../../store/reducers/tenant/constants';
|
31
|
-
import {formatDateTime, formatNumber} from '../../../../utils';
|
31
|
+
import {formatDateTime, formatNumber} from '../../../../utils/dataFormatters/dataFormatters';
|
32
32
|
import {HOUR_IN_SECONDS} from '../../../../utils/constants';
|
33
33
|
import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
|
34
34
|
import {prepareQueryError} from '../../../../utils/query';
|
@@ -22,7 +22,7 @@ import {EShardsWorkloadMode, IShardsWorkloadFilters} from '../../../../types/sto
|
|
22
22
|
import type {EPathType} from '../../../../types/api/schema';
|
23
23
|
import type {CellValue, KeyValueRow} from '../../../../types/api/query';
|
24
24
|
|
25
|
-
import {formatDateTime, formatNumber} from '../../../../utils';
|
25
|
+
import {formatDateTime, formatNumber} from '../../../../utils/dataFormatters/dataFormatters';
|
26
26
|
import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
|
27
27
|
import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
|
28
28
|
import {prepareQueryError} from '../../../../utils/query';
|
@@ -24,7 +24,7 @@ import {
|
|
24
24
|
TColumnTableDescription,
|
25
25
|
} from '../../../types/api/schema';
|
26
26
|
import routes, {createHref} from '../../../routes';
|
27
|
-
import {formatDateTime} from '../../../utils';
|
27
|
+
import {formatDateTime} from '../../../utils/dataFormatters/dataFormatters';
|
28
28
|
import {useTypedSelector} from '../../../utils/hooks';
|
29
29
|
import {
|
30
30
|
DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED,
|
@@ -26,7 +26,11 @@ import {
|
|
26
26
|
ProblemFilterValues,
|
27
27
|
selectProblemFilter,
|
28
28
|
} from '../../store/reducers/settings/settings';
|
29
|
-
import {
|
29
|
+
import {
|
30
|
+
formatBytesToGigabyte,
|
31
|
+
formatCPU,
|
32
|
+
formatNumber,
|
33
|
+
} from '../../utils/dataFormatters/dataFormatters';
|
30
34
|
import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
|
31
35
|
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
|
32
36
|
import {clusterName} from '../../store';
|
@@ -23,5 +23,8 @@
|
|
23
23
|
"settings.useBackendParamsForTables.popover": "Filter and sort Nodes and Storage tables with request params. May increase performance, but could causes additional fetches and longer loading time on older versions",
|
24
24
|
|
25
25
|
"settings.enableAdditionalQueryModes.title": "Enable additional query modes",
|
26
|
-
"settings.enableAdditionalQueryModes.popover": "Adds 'Data', 'YQL - QueryService' and 'PostgreSQL' modes. May not work on some versions"
|
26
|
+
"settings.enableAdditionalQueryModes.popover": "Adds 'Data', 'YQL - QueryService' and 'PostgreSQL' modes. May not work on some versions",
|
27
|
+
|
28
|
+
"settings.tenantDiagnostics.title": "Display metrics cards for database diagnostics",
|
29
|
+
"settings.tenantDiagnostics.popover": "Adds indicators of database resources usage. Incomplete data may be displayed for some databases"
|
27
30
|
}
|
@@ -23,5 +23,8 @@
|
|
23
23
|
"settings.useBackendParamsForTables.popover": "Добавляет фильтрацию и сортировку таблиц Nodes и Storage с использованием параметров запроса. Может улушить производительность, но на старых версиях может привести к дополнительным запросам и большему времени ожидания загрузки",
|
24
24
|
|
25
25
|
"settings.enableAdditionalQueryModes.title": "Включить дополнительные режимы выполнения запросов",
|
26
|
-
"settings.enableAdditionalQueryModes.popover": "Добавляет режимы 'Data', 'YQL - QueryService' и 'PostgreSQL'. Может работать некорректно на некоторых версиях"
|
26
|
+
"settings.enableAdditionalQueryModes.popover": "Добавляет режимы 'Data', 'YQL - QueryService' и 'PostgreSQL'. Может работать некорректно на некоторых версиях",
|
27
|
+
|
28
|
+
"settings.tenantDiagnostics.title": "Показывать карточки с метриками в диагностике базы данных",
|
29
|
+
"settings.tenantDiagnostics.popover": "Добавляет индикаторы использования ресурсов базы данных. Для некоторых баз могут отображаться неполные данные"
|
27
30
|
}
|
@@ -5,6 +5,7 @@ import flaskIcon from '../../assets/icons/flask.svg';
|
|
5
5
|
|
6
6
|
import {
|
7
7
|
ENABLE_ADDITIONAL_QUERY_MODES,
|
8
|
+
DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
8
9
|
INVERTED_DISKS_KEY,
|
9
10
|
LANGUAGE_KEY,
|
10
11
|
THEME_KEY,
|
@@ -94,6 +95,11 @@ export const enableQueryModesForExplainSetting: SettingProps = {
|
|
94
95
|
title: i18n('settings.enableAdditionalQueryModes.title'),
|
95
96
|
helpPopoverContent: i18n('settings.enableAdditionalQueryModes.popover'),
|
96
97
|
};
|
98
|
+
export const enableNewTenantDiagnosticsDesign: SettingProps = {
|
99
|
+
settingKey: DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
100
|
+
title: i18n('settings.tenantDiagnostics.title'),
|
101
|
+
helpPopoverContent: i18n('settings.tenantDiagnostics.popover'),
|
102
|
+
};
|
97
103
|
|
98
104
|
export const generalSection: SettingsSection = {
|
99
105
|
id: 'generalSection',
|
@@ -108,6 +114,7 @@ export const experimentsSection: SettingsSection = {
|
|
108
114
|
useNodesEndpointSetting,
|
109
115
|
useBackendParamsForTables,
|
110
116
|
enableQueryModesForExplainSetting,
|
117
|
+
enableNewTenantDiagnosticsDesign,
|
111
118
|
],
|
112
119
|
};
|
113
120
|
|
@@ -3,10 +3,10 @@ import DataTable, {Column} from '@gravity-ui/react-data-table';
|
|
3
3
|
import type {PreparedClusterNode} from '../../../store/reducers/clusterNodes/types';
|
4
4
|
import {isUnavailableNode} from '../../../utils/nodes';
|
5
5
|
import {DEFAULT_TABLE_SETTINGS} from '../../../utils/constants';
|
6
|
-
import {formatBytes} from '../../../utils';
|
6
|
+
import {formatBytes} from '../../../utils/dataFormatters/dataFormatters';
|
7
7
|
import {getDefaultNodePath} from '../../Node/NodePages';
|
8
8
|
|
9
|
-
import ProgressViewer from '../../../components/ProgressViewer/ProgressViewer';
|
9
|
+
import {ProgressViewer} from '../../../components/ProgressViewer/ProgressViewer';
|
10
10
|
import {PoolsGraph} from '../../../components/PoolsGraph/PoolsGraph';
|
11
11
|
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
12
12
|
|
package/dist/services/api.ts
CHANGED
@@ -350,10 +350,12 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
350
350
|
enable_sampling: enableSampling,
|
351
351
|
});
|
352
352
|
}
|
353
|
-
getHealthcheckInfo(database: string) {
|
354
|
-
return this.get<HealthCheckAPIResponse>(
|
355
|
-
|
356
|
-
|
353
|
+
getHealthcheckInfo(database: string, {concurrentId}: AxiosOptions = {}) {
|
354
|
+
return this.get<HealthCheckAPIResponse>(
|
355
|
+
this.getPath('/viewer/json/healthcheck?merge_records=true'),
|
356
|
+
{tenant: database},
|
357
|
+
{concurrentId},
|
358
|
+
);
|
357
359
|
}
|
358
360
|
killTablet(id?: string) {
|
359
361
|
return this.get<string>(this.getPath(`/tablets?KillTabletID=${id}`), {});
|
@@ -5,7 +5,7 @@ import {createRequestActionTypes, createApiRequest} from '../../utils';
|
|
5
5
|
import type {ClusterNodesAction, ClusterNodesState, PreparedClusterNode} from './types';
|
6
6
|
|
7
7
|
import '../../../services/api';
|
8
|
-
import {calcUptime} from '../../../utils';
|
8
|
+
import {calcUptime} from '../../../utils/dataFormatters/dataFormatters';
|
9
9
|
|
10
10
|
export const FETCH_CLUSTER_NODES = createRequestActionTypes('cluster', 'FETCH_CLUSTER_NODES');
|
11
11
|
|
@@ -44,6 +44,10 @@ const healthcheckInfo: Reducer<IHealthcheckInfoState, IHealthCheckInfoAction> =
|
|
44
44
|
};
|
45
45
|
}
|
46
46
|
case FETCH_HEALTHCHECK.FAILURE: {
|
47
|
+
if (action.error?.isCancelled) {
|
48
|
+
return state;
|
49
|
+
}
|
50
|
+
|
47
51
|
return {
|
48
52
|
...state,
|
49
53
|
error: action.error,
|
@@ -72,21 +76,25 @@ const mapStatusToPriority: Partial<Record<StatusFlag, number>> = {
|
|
72
76
|
GREEN: 4,
|
73
77
|
};
|
74
78
|
|
75
|
-
const
|
76
|
-
return data.
|
77
|
-
|
79
|
+
const sortIssues = (data: IssueLog[]): IssueLog[] => {
|
80
|
+
return data.sort((a, b) => {
|
81
|
+
const aPriority = mapStatusToPriority[a.status] || 0;
|
82
|
+
const bPriority = mapStatusToPriority[b.status] || 0;
|
78
83
|
|
79
|
-
|
80
|
-
let roots = data.filter((item) => {
|
81
|
-
return !data.find((issue) => issue.reason && issue.reason.indexOf(item.id) !== -1);
|
84
|
+
return aPriority - bPriority;
|
82
85
|
});
|
86
|
+
};
|
83
87
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
])(roots);
|
88
|
+
const getReasonsForIssue = ({issue, data}: {issue: IssueLog; data: IssueLog[]}) => {
|
89
|
+
return sortIssues(data.filter((item) => issue.reason && issue.reason.indexOf(item.id) !== -1));
|
90
|
+
};
|
88
91
|
|
89
|
-
|
92
|
+
const getRoots = (data: IssueLog[]): IssueLog[] => {
|
93
|
+
return sortIssues(
|
94
|
+
data.filter((item) => {
|
95
|
+
return !data.find((issue) => issue.reason && issue.reason.indexOf(item.id) !== -1);
|
96
|
+
}),
|
97
|
+
);
|
90
98
|
};
|
91
99
|
|
92
100
|
const getInvertedConsequencesTree = ({
|
@@ -147,7 +155,7 @@ export const selectIssuesStatistics: Selector<
|
|
147
155
|
|
148
156
|
export function getHealthcheckInfo(database: string) {
|
149
157
|
return createApiRequest({
|
150
|
-
request: window.api.getHealthcheckInfo(database),
|
158
|
+
request: window.api.getHealthcheckInfo(database, {concurrentId: 'getHealthcheckInfo'}),
|
151
159
|
actions: FETCH_HEALTHCHECK,
|
152
160
|
});
|
153
161
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import {Selector, createSelector} from 'reselect';
|
2
2
|
|
3
3
|
import {EFlag} from '../../../types/api/enums';
|
4
|
-
import {calcUptimeInSeconds} from '../../../utils';
|
4
|
+
import {calcUptimeInSeconds} from '../../../utils/dataFormatters/dataFormatters';
|
5
5
|
import {HOUR_IN_SECONDS} from '../../../utils/constants';
|
6
6
|
import {NodesUptimeFilterValues} from '../../../utils/nodes';
|
7
7
|
import {prepareSearchValue} from '../../../utils/filters';
|
@@ -64,7 +64,7 @@ export interface NodesGeneralRequestParams extends NodesSortParams {
|
|
64
64
|
uptime?: number; // return nodes with less uptime in seconds
|
65
65
|
problems_only?: boolean; // return nodes with SystemState !== EFlag.Green
|
66
66
|
|
67
|
-
|
67
|
+
offset?: number;
|
68
68
|
limit?: number;
|
69
69
|
}
|
70
70
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import type {TComputeInfo, TComputeNodeInfo} from '../../../types/api/compute';
|
2
2
|
import type {TNodesInfo} from '../../../types/api/nodes';
|
3
|
-
import {calcUptime} from '../../../utils';
|
3
|
+
import {calcUptime} from '../../../utils/dataFormatters/dataFormatters';
|
4
4
|
|
5
5
|
import type {NodesHandledResponse, NodesPreparedEntity} from './types';
|
6
6
|
|
@@ -15,6 +15,7 @@ import {
|
|
15
15
|
LAST_USED_QUERY_ACTION_KEY,
|
16
16
|
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
17
17
|
LANGUAGE_KEY,
|
18
|
+
DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
18
19
|
} from '../../../utils/constants';
|
19
20
|
import '../../../services/api';
|
20
21
|
import {parseJson} from '../../../utils/utils';
|
@@ -49,12 +50,16 @@ export const initialState = {
|
|
49
50
|
[INVERTED_DISKS_KEY]: readSavedSettingsValue(INVERTED_DISKS_KEY, 'false'),
|
50
51
|
[USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY]: readSavedSettingsValue(
|
51
52
|
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
52
|
-
'
|
53
|
+
'true',
|
53
54
|
),
|
54
55
|
[ENABLE_ADDITIONAL_QUERY_MODES]: readSavedSettingsValue(
|
55
56
|
ENABLE_ADDITIONAL_QUERY_MODES,
|
56
57
|
'false',
|
57
58
|
),
|
59
|
+
[DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS]: readSavedSettingsValue(
|
60
|
+
DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
61
|
+
'false',
|
62
|
+
),
|
58
63
|
[SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
|
59
64
|
[TENANT_INITIAL_PAGE_KEY]: readSavedSettingsValue(
|
60
65
|
TENANT_INITIAL_PAGE_KEY,
|
@@ -9,7 +9,7 @@ import {TPDiskState} from '../../../types/api/pdisk';
|
|
9
9
|
import {EFlag} from '../../../types/api/enums';
|
10
10
|
import {getPDiskType} from '../../../utils/pdisk';
|
11
11
|
import {getUsage} from '../../../utils/storage';
|
12
|
-
import {calcUptime} from '../../../utils';
|
12
|
+
import {calcUptime} from '../../../utils/dataFormatters/dataFormatters';
|
13
13
|
|
14
14
|
import type {PreparedStorageGroup, PreparedStorageNode, PreparedStorageResponse} from './types';
|
15
15
|
|
@@ -4,6 +4,7 @@ import type {TTenant} from '../../../types/api/tenant';
|
|
4
4
|
import type {
|
5
5
|
TenantAction,
|
6
6
|
TenantDiagnosticsTab,
|
7
|
+
TenantMetricsTab,
|
7
8
|
TenantPage,
|
8
9
|
TenantQueryTab,
|
9
10
|
TenantState,
|
@@ -19,6 +20,7 @@ const SET_TOP_LEVEL_TAB = 'tenant/SET_TOP_LEVEL_TAB';
|
|
19
20
|
const SET_QUERY_TAB = 'tenant/SET_QUERY_TAB';
|
20
21
|
const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
|
21
22
|
const SET_SUMMARY_TAB = 'tenant/SET_SUMMARY_TAB';
|
23
|
+
const SET_METRICS_TAB = 'tenant/SET_METRICS_TAB';
|
22
24
|
const CLEAR_TENANT = 'tenant/CLEAR_TENANT';
|
23
25
|
const SET_DATA_WAS_NOT_LOADED = 'tenant/SET_DATA_WAS_NOT_LOADED';
|
24
26
|
|
@@ -88,6 +90,12 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
|
|
88
90
|
summaryTab: action.data,
|
89
91
|
};
|
90
92
|
}
|
93
|
+
case SET_METRICS_TAB: {
|
94
|
+
return {
|
95
|
+
...state,
|
96
|
+
metricsTab: action.data,
|
97
|
+
};
|
98
|
+
}
|
91
99
|
|
92
100
|
case SET_DATA_WAS_NOT_LOADED: {
|
93
101
|
return {
|
@@ -143,6 +151,13 @@ export function setSummaryTab(tab: TenantSummaryTab) {
|
|
143
151
|
} as const;
|
144
152
|
}
|
145
153
|
|
154
|
+
export function setMetricsTab(tab: TenantMetricsTab) {
|
155
|
+
return {
|
156
|
+
type: SET_METRICS_TAB,
|
157
|
+
data: tab,
|
158
|
+
} as const;
|
159
|
+
}
|
160
|
+
|
146
161
|
export const setDataWasNotLoaded = () => {
|
147
162
|
return {
|
148
163
|
type: SET_DATA_WAS_NOT_LOADED,
|
@@ -8,6 +8,7 @@ import {
|
|
8
8
|
TENANT_DIAGNOSTICS_TABS_IDS,
|
9
9
|
TENANT_PAGES_IDS,
|
10
10
|
TENANT_SUMMARY_TABS_IDS,
|
11
|
+
TENANT_METRICS_TABS_IDS,
|
11
12
|
} from './constants';
|
12
13
|
import {
|
13
14
|
FETCH_TENANT,
|
@@ -15,6 +16,7 @@ import {
|
|
15
16
|
setDiagnosticsTab,
|
16
17
|
setQueryTab,
|
17
18
|
setSummaryTab,
|
19
|
+
setMetricsTab,
|
18
20
|
setTenantPage,
|
19
21
|
setDataWasNotLoaded,
|
20
22
|
} from './tenant';
|
@@ -24,6 +26,7 @@ export type TenantPage = ValueOf<typeof TENANT_PAGES_IDS>;
|
|
24
26
|
export type TenantQueryTab = ValueOf<typeof TENANT_QUERY_TABS_ID>;
|
25
27
|
export type TenantDiagnosticsTab = ValueOf<typeof TENANT_DIAGNOSTICS_TABS_IDS>;
|
26
28
|
export type TenantSummaryTab = ValueOf<typeof TENANT_SUMMARY_TABS_IDS>;
|
29
|
+
export type TenantMetricsTab = ValueOf<typeof TENANT_METRICS_TABS_IDS>;
|
27
30
|
|
28
31
|
export interface TenantState {
|
29
32
|
loading: boolean;
|
@@ -32,6 +35,7 @@ export interface TenantState {
|
|
32
35
|
queryTab?: TenantQueryTab;
|
33
36
|
diagnosticsTab?: TenantDiagnosticsTab;
|
34
37
|
summaryTab?: TenantSummaryTab;
|
38
|
+
metricsTab?: TenantMetricsTab;
|
35
39
|
tenant?: TTenant;
|
36
40
|
error?: IResponseError;
|
37
41
|
}
|
@@ -43,4 +47,5 @@ export type TenantAction =
|
|
43
47
|
| ReturnType<typeof setQueryTab>
|
44
48
|
| ReturnType<typeof setDiagnosticsTab>
|
45
49
|
| ReturnType<typeof setSummaryTab>
|
50
|
+
| ReturnType<typeof setMetricsTab>
|
46
51
|
| ReturnType<typeof setDataWasNotLoaded>;
|
@@ -1,8 +1,10 @@
|
|
1
1
|
import {FETCH_TENANTS, setSearchValue} from './tenants';
|
2
2
|
|
3
|
+
import {ValueOf} from '../../../types/common';
|
3
4
|
import type {TTenant} from '../../../types/api/tenant';
|
4
5
|
import type {IResponseError} from '../../../types/api/error';
|
5
6
|
import type {ApiRequestAction} from '../../utils';
|
7
|
+
import {METRIC_STATUS} from './contants';
|
6
8
|
|
7
9
|
export interface PreparedTenant extends TTenant {
|
8
10
|
backend: string | undefined;
|
@@ -30,3 +32,5 @@ export type TenantsAction =
|
|
30
32
|
export interface TenantsStateSlice {
|
31
33
|
tenants: TenantsState;
|
32
34
|
}
|
35
|
+
|
36
|
+
export type MetricStatus = ValueOf<typeof METRIC_STATUS>;
|
@@ -1,5 +1,8 @@
|
|
1
1
|
import type {TTenant} from '../../../types/api/tenant';
|
2
|
+
import {formatBytes} from '../../../utils/bytesParsers';
|
3
|
+
import {formatCPUWithLabel} from '../../../utils/dataFormatters/dataFormatters';
|
2
4
|
import {isNumeric} from '../../../utils/utils';
|
5
|
+
import {METRIC_STATUS} from './contants';
|
3
6
|
|
4
7
|
const getControlPlaneValue = (tenant: TTenant) => {
|
5
8
|
const parts = tenant.Name?.split('/');
|
@@ -18,21 +21,40 @@ const getTenantBackend = (tenant: TTenant) => {
|
|
18
21
|
return node.Host ? `${node.Host}${address ? address : ''}` : undefined;
|
19
22
|
};
|
20
23
|
|
21
|
-
const calculateTenantMetrics = (tenant
|
22
|
-
const {
|
24
|
+
export const calculateTenantMetrics = (tenant?: TTenant) => {
|
25
|
+
const {
|
26
|
+
CoresUsed,
|
27
|
+
MemoryUsed,
|
28
|
+
StorageAllocatedSize,
|
29
|
+
CoresLimit,
|
30
|
+
MemoryLimit,
|
31
|
+
StorageLimit,
|
32
|
+
Metrics = {},
|
33
|
+
} = tenant || {};
|
23
34
|
|
24
35
|
const cpuFromCores = isNumeric(CoresUsed) ? Number(CoresUsed) * 1_000_000 : undefined;
|
25
36
|
const cpuFromMetrics = isNumeric(Metrics.CPU) ? Number(Metrics.CPU) : undefined;
|
26
37
|
|
27
|
-
const cpu = cpuFromCores ?? cpuFromMetrics ??
|
38
|
+
const cpu = cpuFromCores ?? cpuFromMetrics ?? undefined;
|
28
39
|
|
29
40
|
const rawMemory = MemoryUsed ?? Metrics.Memory;
|
30
|
-
const rawStorage = StorageAllocatedSize ?? Metrics.Storage;
|
31
41
|
|
32
|
-
const memory = isNumeric(rawMemory) ? Number(rawMemory) :
|
33
|
-
const storage = isNumeric(rawStorage) ? Number(rawStorage) : 0;
|
42
|
+
const memory = isNumeric(rawMemory) ? Number(rawMemory) : undefined;
|
34
43
|
|
35
|
-
|
44
|
+
// Blob storage - actual database size
|
45
|
+
const storage = isNumeric(StorageAllocatedSize) ? Number(StorageAllocatedSize) : undefined;
|
46
|
+
const cpuLimit = isNumeric(CoresLimit) ? Number(CoresLimit) : undefined;
|
47
|
+
const memoryLimit = isNumeric(MemoryLimit) ? Number(MemoryLimit) : undefined;
|
48
|
+
const storageLimit = isNumeric(StorageLimit) ? Number(StorageLimit) : undefined;
|
49
|
+
|
50
|
+
return {
|
51
|
+
cpu,
|
52
|
+
memory,
|
53
|
+
storage,
|
54
|
+
cpuLimit,
|
55
|
+
memoryLimit,
|
56
|
+
storageLimit,
|
57
|
+
};
|
36
58
|
};
|
37
59
|
|
38
60
|
const calculateTenantEntities = (tenant: TTenant) => {
|
@@ -66,3 +88,88 @@ export const prepareTenants = (tenants: TTenant[], useNodeAsBackend: boolean) =>
|
|
66
88
|
};
|
67
89
|
});
|
68
90
|
};
|
91
|
+
|
92
|
+
export const calculateUsage = (valueUsed?: number, valueLimit?: number): number | undefined => {
|
93
|
+
if (valueUsed && valueLimit) {
|
94
|
+
return (valueUsed * 100) / valueLimit;
|
95
|
+
}
|
96
|
+
|
97
|
+
return undefined;
|
98
|
+
};
|
99
|
+
|
100
|
+
export const formatUsage = (usage?: number) => {
|
101
|
+
if (usage) {
|
102
|
+
return `${usage.toFixed()}%`;
|
103
|
+
}
|
104
|
+
|
105
|
+
return undefined;
|
106
|
+
};
|
107
|
+
|
108
|
+
export const cpuUsageToStatus = (usage?: number) => {
|
109
|
+
if (!usage) {
|
110
|
+
return METRIC_STATUS.Unspecified;
|
111
|
+
}
|
112
|
+
|
113
|
+
if (usage > 70) {
|
114
|
+
return METRIC_STATUS.Danger;
|
115
|
+
}
|
116
|
+
if (usage > 60) {
|
117
|
+
return METRIC_STATUS.Warning;
|
118
|
+
}
|
119
|
+
|
120
|
+
return METRIC_STATUS.Good;
|
121
|
+
};
|
122
|
+
export const storageUsageToStatus = (usage?: number) => {
|
123
|
+
if (!usage) {
|
124
|
+
return METRIC_STATUS.Unspecified;
|
125
|
+
}
|
126
|
+
|
127
|
+
if (usage > 85) {
|
128
|
+
return METRIC_STATUS.Danger;
|
129
|
+
}
|
130
|
+
if (usage > 75) {
|
131
|
+
return METRIC_STATUS.Warning;
|
132
|
+
}
|
133
|
+
|
134
|
+
return METRIC_STATUS.Good;
|
135
|
+
};
|
136
|
+
|
137
|
+
export const memoryUsageToStatus = (usage?: number) => {
|
138
|
+
if (!usage) {
|
139
|
+
return METRIC_STATUS.Unspecified;
|
140
|
+
}
|
141
|
+
|
142
|
+
if (usage > 70) {
|
143
|
+
return METRIC_STATUS.Danger;
|
144
|
+
}
|
145
|
+
if (usage > 60) {
|
146
|
+
return METRIC_STATUS.Warning;
|
147
|
+
}
|
148
|
+
|
149
|
+
return METRIC_STATUS.Good;
|
150
|
+
};
|
151
|
+
|
152
|
+
export const formatTenantMetrics = ({
|
153
|
+
cpu,
|
154
|
+
storage,
|
155
|
+
memory,
|
156
|
+
}: {
|
157
|
+
cpu?: number;
|
158
|
+
storage?: number;
|
159
|
+
memory?: number;
|
160
|
+
}) => ({
|
161
|
+
cpu: formatCPUWithLabel(cpu),
|
162
|
+
storage: formatBytes({value: storage, significantDigits: 2}) || undefined,
|
163
|
+
memory: formatBytes({value: memory, significantDigits: 2}) || undefined,
|
164
|
+
});
|
165
|
+
|
166
|
+
export const normalizeProgress = (progress: number) => {
|
167
|
+
if (progress >= 100) {
|
168
|
+
return 100;
|
169
|
+
}
|
170
|
+
if (progress <= 0) {
|
171
|
+
return 0;
|
172
|
+
}
|
173
|
+
|
174
|
+
return progress;
|
175
|
+
};
|
package/dist/types/api/tenant.ts
CHANGED
@@ -57,6 +57,9 @@ export interface TTenant {
|
|
57
57
|
|
58
58
|
MonitoringEndpoint?: string; // additional
|
59
59
|
ControlPlane?: ControlPlane; // additional
|
60
|
+
|
61
|
+
CoresLimit?: string; // TODO: check correctness in backend protos when fully supported
|
62
|
+
StorageLimit?: string; // TODO: check correctness in backend protos when fully supported
|
60
63
|
}
|
61
64
|
|
62
65
|
interface THiveDomainStatsStateCount {
|
package/dist/types/api/vdisk.ts
CHANGED