ydb-embedded-ui 4.19.3 → 4.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/components/LinkToSchemaObject/LinkToSchemaObject.tsx +20 -0
  3. package/dist/components/QueryExecutionStatus/QueryExecutionStatus.tsx +3 -2
  4. package/dist/components/UsageLabel/UsageLabel.scss +6 -0
  5. package/dist/components/UsageLabel/UsageLabel.tsx +22 -0
  6. package/dist/containers/AsideNavigation/AsideNavigation.tsx +13 -8
  7. package/dist/containers/AsideNavigation/i18n/en.json +13 -0
  8. package/dist/containers/AsideNavigation/i18n/index.ts +11 -0
  9. package/dist/containers/AsideNavigation/i18n/ru.json +13 -0
  10. package/dist/containers/Node/NodeStructure/Pdisk.tsx +74 -68
  11. package/dist/containers/Node/NodeStructure/Vdisk.tsx +9 -33
  12. package/dist/containers/Nodes/Nodes.tsx +10 -2
  13. package/dist/containers/Nodes/getNodesColumns.tsx +206 -122
  14. package/dist/containers/Storage/Storage.tsx +9 -2
  15. package/dist/containers/Storage/utils/index.ts +1 -22
  16. package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +2 -3
  17. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +0 -1
  18. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +4 -2
  19. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +1 -0
  20. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckDetails.tsx +8 -1
  21. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx +11 -1
  22. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/IssuesViewer/IssueTree.tsx +0 -1
  23. package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +3 -0
  24. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TenantCpu.tsx +21 -0
  25. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx +53 -0
  26. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx +53 -0
  27. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx +85 -0
  28. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx +53 -0
  29. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TenantMemory.tsx +9 -0
  30. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx +55 -0
  31. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +40 -0
  32. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +35 -19
  33. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx +53 -0
  34. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx +15 -7
  35. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +3 -3
  36. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +3 -3
  37. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +0 -2
  38. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +13 -61
  39. package/dist/containers/Tenant/Diagnostics/TopQueries/getTopQueriesColumns.tsx +82 -0
  40. package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.tsx +2 -2
  41. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +18 -97
  42. package/dist/containers/Tenant/Diagnostics/TopShards/getTopShardsColumns.tsx +138 -0
  43. package/dist/containers/Tenant/Info/ExternalTable/ExternalTable.tsx +2 -4
  44. package/dist/containers/Tenant/Query/ExecuteResult/{ExecuteResult.js → ExecuteResult.tsx} +51 -31
  45. package/dist/containers/Tenant/Query/Issues/Issues.tsx +4 -6
  46. package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.tsx +1 -1
  47. package/dist/containers/Tenant/utils/paneVisibilityToggleHelpers.tsx +1 -1
  48. package/dist/routes.ts +6 -0
  49. package/dist/store/reducers/{executeTopQueries.ts → executeTopQueries/executeTopQueries.ts} +23 -75
  50. package/dist/{types/store/executeTopQueries.ts → store/reducers/executeTopQueries/types.ts} +3 -7
  51. package/dist/store/reducers/executeTopQueries/utils.ts +36 -0
  52. package/dist/store/reducers/index.ts +12 -2
  53. package/dist/store/reducers/nodes/types.ts +1 -0
  54. package/dist/store/reducers/nodes/utils.ts +16 -6
  55. package/dist/store/reducers/{shardsWorkload.ts → shardsWorkload/shardsWorkload.ts} +5 -11
  56. package/dist/{types/store/shardsWorkload.ts → store/reducers/shardsWorkload/types.ts} +3 -7
  57. package/dist/store/reducers/tenantOverview/topNodesByCpu/topNodesByCpu.ts +87 -0
  58. package/dist/store/reducers/tenantOverview/topNodesByCpu/types.ts +29 -0
  59. package/dist/store/reducers/tenantOverview/topNodesByLoad/topNodesByLoad.ts +87 -0
  60. package/dist/store/reducers/tenantOverview/topNodesByLoad/types.ts +29 -0
  61. package/dist/store/reducers/tenantOverview/topNodesByMemory/topNodesByMemory.ts +87 -0
  62. package/dist/store/reducers/tenantOverview/topNodesByMemory/types.ts +29 -0
  63. package/dist/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts +93 -0
  64. package/dist/store/reducers/tenantOverview/topQueries/types.ts +14 -0
  65. package/dist/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts +103 -0
  66. package/dist/store/reducers/tenantOverview/topShards/types.ts +14 -0
  67. package/dist/store/reducers/tenantOverview/topShards/utils.ts +3 -0
  68. package/dist/styles/mixins.scss +4 -0
  69. package/dist/types/additionalProps.ts +3 -1
  70. package/dist/types/api/compute.ts +1 -1
  71. package/dist/types/react-json-inspector.d.ts +21 -0
  72. package/dist/utils/diagnostics.ts +11 -0
  73. package/dist/utils/generateEvaluator.ts +21 -0
  74. package/package.json +1 -1
@@ -1,91 +1,44 @@
1
1
  import {useCallback, useEffect, useRef, useState} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import {useHistory, useLocation} from 'react-router';
4
- import qs from 'qs';
5
4
  import cn from 'bem-cn-lite';
6
5
 
7
- import DataTable, {Column} from '@gravity-ui/react-data-table';
6
+ import DataTable from '@gravity-ui/react-data-table';
8
7
  import {Loader} from '@gravity-ui/uikit';
9
8
 
10
9
  import {DateRange, DateRangeValues} from '../../../../components/DateRange';
11
10
  import {Search} from '../../../../components/Search';
12
- import {TruncatedQuery} from '../../../../components/TruncatedQuery/TruncatedQuery';
13
11
 
14
12
  import {changeUserInput} from '../../../../store/reducers/executeQuery';
15
- import {
16
- fetchTopQueries,
17
- setTopQueriesFilters,
18
- setTopQueriesState,
19
- } from '../../../../store/reducers/executeTopQueries';
20
13
 
21
- import type {KeyValueRow} from '../../../../types/api/query';
22
14
  import type {EPathType} from '../../../../types/api/schema';
23
- import type {ITopQueriesFilters} from '../../../../types/store/executeTopQueries';
24
15
  import type {IQueryResult} from '../../../../types/store/query';
16
+ import type {ITopQueriesFilters} from '../../../../store/reducers/executeTopQueries/types';
25
17
 
26
18
  import {
27
19
  TENANT_PAGE,
28
20
  TENANT_PAGES_IDS,
29
21
  TENANT_QUERY_TABS_ID,
30
22
  } from '../../../../store/reducers/tenant/constants';
31
- import {formatDateTime, formatNumber} from '../../../../utils/dataFormatters/dataFormatters';
23
+ import {
24
+ setTopQueriesFilters,
25
+ setTopQueriesState,
26
+ fetchTopQueries,
27
+ } from '../../../../store/reducers/executeTopQueries/executeTopQueries';
32
28
  import {HOUR_IN_SECONDS} from '../../../../utils/constants';
33
29
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
34
30
  import {prepareQueryError} from '../../../../utils/query';
35
-
36
- import {MAX_QUERY_HEIGHT, QUERY_TABLE_SETTINGS} from '../../utils/constants';
31
+ import {parseQuery} from '../../../../routes';
32
+ import {QUERY_TABLE_SETTINGS} from '../../utils/constants';
37
33
  import {isColumnEntityType} from '../../utils/schema';
38
34
  import {TenantTabsGroups, getTenantPath} from '../../TenantPages';
35
+ import {getTopQueriesColumns} from './getTopQueriesColumns';
39
36
 
40
37
  import i18n from './i18n';
41
38
  import './TopQueries.scss';
42
39
 
43
40
  const b = cn('kv-top-queries');
44
41
 
45
- const COLUMNS: Column<KeyValueRow>[] = [
46
- {
47
- name: 'CPUTimeUs',
48
- sortAccessor: (row) => Number(row.CPUTimeUs),
49
- align: DataTable.RIGHT,
50
- },
51
- {
52
- name: 'QueryText',
53
- width: 500,
54
- sortable: false,
55
- render: ({row}) => (
56
- <div className={b('query')}>
57
- <TruncatedQuery
58
- value={row.QueryText?.toString()}
59
- maxQueryHeight={MAX_QUERY_HEIGHT}
60
- />
61
- </div>
62
- ),
63
- },
64
- {
65
- name: 'EndTime',
66
- render: ({row}) => formatDateTime(new Date(row.EndTime as string).getTime()),
67
- align: DataTable.RIGHT,
68
- },
69
- {
70
- name: 'ReadRows',
71
- render: ({row}) => formatNumber(row.ReadRows),
72
- sortAccessor: (row) => Number(row.ReadRows),
73
- align: DataTable.RIGHT,
74
- },
75
- {
76
- name: 'ReadBytes',
77
- render: ({row}) => formatNumber(row.ReadBytes),
78
- sortAccessor: (row) => Number(row.ReadBytes),
79
- align: DataTable.RIGHT,
80
- },
81
- {
82
- name: 'UserSID',
83
- render: ({row}) => <div className={b('user-sid')}>{row.UserSID || '–'}</div>,
84
- sortAccessor: (row) => String(row.UserSID),
85
- align: DataTable.LEFT,
86
- },
87
- ];
88
-
89
42
  interface TopQueriesProps {
90
43
  path: string;
91
44
  type?: EPathType;
@@ -105,6 +58,7 @@ export const TopQueries = ({path, type}: TopQueriesProps) => {
105
58
  data: {result: data = undefined} = {},
106
59
  filters: storeFilters,
107
60
  } = useTypedSelector((state) => state.executeTopQueries);
61
+ const columns = getTopQueriesColumns();
108
62
 
109
63
  const preventFetch = useRef(false);
110
64
 
@@ -173,9 +127,7 @@ export const TopQueries = ({path, type}: TopQueriesProps) => {
173
127
 
174
128
  dispatch(changeUserInput({input}));
175
129
 
176
- const queryParams = qs.parse(location.search, {
177
- ignoreQueryPrefix: true,
178
- });
130
+ const queryParams = parseQuery(location);
179
131
 
180
132
  const queryPath = getTenantPath({
181
133
  ...queryParams,
@@ -220,7 +172,7 @@ export const TopQueries = ({path, type}: TopQueriesProps) => {
220
172
  return (
221
173
  <div className={b('table')}>
222
174
  <DataTable
223
- columns={COLUMNS}
175
+ columns={columns}
224
176
  data={data}
225
177
  settings={QUERY_TABLE_SETTINGS}
226
178
  onRowClick={handleRowClick}
@@ -0,0 +1,82 @@
1
+ import cn from 'bem-cn-lite';
2
+
3
+ import DataTable, {type Column} from '@gravity-ui/react-data-table';
4
+
5
+ import type {KeyValueRow} from '../../../../types/api/query';
6
+ import {formatDateTime, formatNumber} from '../../../../utils/dataFormatters/dataFormatters';
7
+ import {TruncatedQuery} from '../../../../components/TruncatedQuery/TruncatedQuery';
8
+ import {MAX_QUERY_HEIGHT} from '../../utils/constants';
9
+
10
+ import './TopQueries.scss';
11
+
12
+ const b = cn('kv-top-queries');
13
+
14
+ const TOP_QUERIES_COLUMNS_IDS = {
15
+ CPUTimeUs: 'CPUTimeUs',
16
+ QueryText: 'QueryText',
17
+ EndTime: 'EndTime',
18
+ ReadRows: 'ReadRows',
19
+ ReadBytes: 'ReadBytes',
20
+ UserSID: 'UserSID',
21
+ };
22
+
23
+ const cpuTimeUsColumn: Column<KeyValueRow> = {
24
+ name: TOP_QUERIES_COLUMNS_IDS.CPUTimeUs,
25
+ sortAccessor: (row) => Number(row.CPUTimeUs),
26
+ width: 120,
27
+ align: DataTable.RIGHT,
28
+ sortable: false,
29
+ };
30
+
31
+ const queryTextColumn: Column<KeyValueRow> = {
32
+ name: TOP_QUERIES_COLUMNS_IDS.QueryText,
33
+ sortAccessor: (row) => Number(row.CPUTimeUs),
34
+ render: ({row}) => (
35
+ <div className={b('query')}>
36
+ <TruncatedQuery value={row.QueryText?.toString()} maxQueryHeight={MAX_QUERY_HEIGHT} />
37
+ </div>
38
+ ),
39
+ sortable: false,
40
+ };
41
+
42
+ const endTimeColumn: Column<KeyValueRow> = {
43
+ name: TOP_QUERIES_COLUMNS_IDS.EndTime,
44
+ render: ({row}) => formatDateTime(new Date(row.EndTime as string).getTime()),
45
+ align: DataTable.RIGHT,
46
+ };
47
+
48
+ const readRowsColumn: Column<KeyValueRow> = {
49
+ name: TOP_QUERIES_COLUMNS_IDS.ReadRows,
50
+ render: ({row}) => formatNumber(row.ReadRows),
51
+ sortAccessor: (row) => Number(row.ReadRows),
52
+ align: DataTable.RIGHT,
53
+ };
54
+
55
+ const readBytesColumn: Column<KeyValueRow> = {
56
+ name: TOP_QUERIES_COLUMNS_IDS.ReadBytes,
57
+ render: ({row}) => formatNumber(row.ReadBytes),
58
+ sortAccessor: (row) => Number(row.ReadBytes),
59
+ align: DataTable.RIGHT,
60
+ };
61
+
62
+ const userSIDColumn: Column<KeyValueRow> = {
63
+ name: TOP_QUERIES_COLUMNS_IDS.UserSID,
64
+ render: ({row}) => <div className={b('user-sid')}>{row.UserSID || '–'}</div>,
65
+ sortAccessor: (row) => String(row.UserSID),
66
+ align: DataTable.LEFT,
67
+ };
68
+
69
+ export const getTopQueriesColumns = (): Column<KeyValueRow>[] => {
70
+ return [
71
+ cpuTimeUsColumn,
72
+ queryTextColumn,
73
+ endTimeColumn,
74
+ readRowsColumn,
75
+ readBytesColumn,
76
+ userSIDColumn,
77
+ ];
78
+ };
79
+
80
+ export const getTenantOverviewTopQueriesColumns = (): Column<KeyValueRow>[] => {
81
+ return [queryTextColumn, cpuTimeUsColumn];
82
+ };
@@ -4,8 +4,8 @@ import {DateRange, DateRangeValues} from '../../../../../components/DateRange';
4
4
 
5
5
  import {
6
6
  EShardsWorkloadMode,
7
- IShardsWorkloadFilters,
8
- } from '../../../../../types/store/shardsWorkload';
7
+ type IShardsWorkloadFilters,
8
+ } from '../../../../../store/reducers/shardsWorkload/types';
9
9
 
10
10
  import {isEnumMember} from '../../../../../utils/typecheckers';
11
11
 
@@ -1,43 +1,38 @@
1
- import {useState, useContext, useEffect, useMemo} from 'react';
1
+ import {useState, useEffect, useMemo} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
+ import {useLocation} from 'react-router';
4
5
 
5
6
  import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
6
7
  import {Loader} from '@gravity-ui/uikit';
7
8
 
8
- import {InternalLink} from '../../../../components/InternalLink';
9
-
10
- import HistoryContext from '../../../../contexts/HistoryContext';
11
-
12
- import routes, {createHref} from '../../../../routes';
13
-
14
9
  import {
15
10
  sendShardQuery,
16
11
  setShardsState,
17
12
  setShardsQueryFilters,
18
- } from '../../../../store/reducers/shardsWorkload';
19
- import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema/schema';
20
- import {EShardsWorkloadMode, IShardsWorkloadFilters} from '../../../../types/store/shardsWorkload';
13
+ } from '../../../../store/reducers/shardsWorkload/shardsWorkload';
14
+ import {
15
+ EShardsWorkloadMode,
16
+ type IShardsWorkloadFilters,
17
+ } from '../../../../store/reducers/shardsWorkload/types';
21
18
 
22
19
  import type {EPathType} from '../../../../types/api/schema';
23
20
  import type {CellValue, KeyValueRow} from '../../../../types/api/query';
24
21
 
25
- import {formatDateTime, formatNumber} from '../../../../utils/dataFormatters/dataFormatters';
22
+ import {formatDateTime} from '../../../../utils/dataFormatters/dataFormatters';
26
23
  import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
27
24
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
28
25
  import {prepareQueryError} from '../../../../utils/query';
29
-
30
- import {getDefaultNodePath} from '../../../Node/NodePages';
31
-
26
+ import {isSortableTopShardsProperty} from '../../../../utils/diagnostics';
32
27
  import {isColumnEntityType} from '../../utils/schema';
33
28
 
34
29
  import {Filters} from './Filters';
30
+ import {getShardsWorkloadColumns} from './getTopShardsColumns';
35
31
 
36
32
  import i18n from './i18n';
37
33
  import './TopShards.scss';
38
34
 
39
35
  export const b = cn('top-shards');
40
- const bLink = cn('yc-link');
41
36
 
42
37
  const TABLE_SETTINGS: Settings = {
43
38
  ...DEFAULT_TABLE_SETTINGS,
@@ -58,10 +53,6 @@ const tableColumnsNames = {
58
53
  IntervalEnd: 'IntervalEnd',
59
54
  };
60
55
 
61
- function prepareCPUWorkloadValue(value: string | number) {
62
- return `${(Number(value) * 100).toFixed(2)}%`;
63
- }
64
-
65
56
  function prepareDateTimeValue(value: CellValue) {
66
57
  if (!value) {
67
58
  return '–';
@@ -105,6 +96,7 @@ interface TopShardsProps {
105
96
 
106
97
  export const TopShards = ({tenantPath, type}: TopShardsProps) => {
107
98
  const dispatch = useDispatch();
99
+ const location = useLocation();
108
100
 
109
101
  const {autorefresh, currentSchemaPath} = useTypedSelector((state) => state.schema);
110
102
 
@@ -159,8 +151,6 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
159
151
  );
160
152
  }, [dispatch, currentSchemaPath, tenantPath, filters]);
161
153
 
162
- const history = useContext(HistoryContext);
163
-
164
154
  const onSort = (newSortOrder?: SortOrder | SortOrder[]) => {
165
155
  // omit information about sort order to disable ASC order, only DESC makes sense for top shards
166
156
  // use a string (and not the DataTable default format) to prevent reference change,
@@ -190,81 +180,12 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
190
180
  };
191
181
 
192
182
  const tableColumns = useMemo(() => {
193
- const onSchemaClick = (schemaPath: string) => {
194
- return () => {
195
- dispatch(setCurrentSchemaPath(schemaPath));
196
- dispatch(getSchema({path: schemaPath}));
197
- history.go(0);
198
- };
199
- };
200
-
201
- const columns: Column<KeyValueRow>[] = [
202
- {
203
- name: tableColumnsNames.Path,
204
- render: ({row}) => {
205
- // row.Path - relative schema path
206
- return (
207
- <span
208
- onClick={onSchemaClick(tenantPath + row.Path)}
209
- className={bLink({view: 'normal'})}
210
- >
211
- {row.Path}
212
- </span>
213
- );
214
- },
215
- sortable: false,
216
- },
217
- {
218
- name: tableColumnsNames.CPUCores,
219
- render: ({row}) => {
220
- return prepareCPUWorkloadValue(row.CPUCores || 0);
221
- },
222
- align: DataTable.RIGHT,
223
- },
224
- {
225
- name: tableColumnsNames.DataSize,
226
- header: 'DataSize (B)',
227
- render: ({row}) => {
228
- return formatNumber(row.DataSize);
229
- },
230
- align: DataTable.RIGHT,
231
- },
232
- {
233
- name: tableColumnsNames.TabletId,
234
- render: ({row}) => {
235
- if (!row.TabletId) {
236
- return '–';
237
- }
238
- return (
239
- <InternalLink to={createHref(routes.tablet, {id: row.TabletId})}>
240
- {row.TabletId}
241
- </InternalLink>
242
- );
243
- },
244
- sortable: false,
245
- },
246
- {
247
- name: tableColumnsNames.NodeId,
248
- render: ({row}) => {
249
- if (!row.NodeId) {
250
- return '–';
251
- }
252
- return (
253
- <InternalLink to={getDefaultNodePath(row.NodeId)}>
254
- {row.NodeId}
255
- </InternalLink>
256
- );
257
- },
258
- align: DataTable.RIGHT,
259
- sortable: false,
260
- },
261
- {
262
- name: tableColumnsNames.InFlightTxCount,
263
- render: ({row}) => formatNumber(row.InFlightTxCount),
264
- align: DataTable.RIGHT,
265
- sortable: false,
266
- },
267
- ];
183
+ const rawColumns: Column<KeyValueRow>[] = getShardsWorkloadColumns(tenantPath, location);
184
+
185
+ const columns: Column<KeyValueRow>[] = rawColumns.map((column) => ({
186
+ ...column,
187
+ sortable: isSortableTopShardsProperty(column.name),
188
+ }));
268
189
 
269
190
  if (filters.mode === EShardsWorkloadMode.History) {
270
191
  // after NodeId
@@ -284,7 +205,7 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
284
205
  }
285
206
 
286
207
  return columns;
287
- }, [dispatch, filters.mode, history, tenantPath]);
208
+ }, [filters.mode, tenantPath, location]);
288
209
 
289
210
  const renderLoader = () => {
290
211
  return (
@@ -0,0 +1,138 @@
1
+ import type {Location} from 'history';
2
+
3
+ import DataTable, {type Column} from '@gravity-ui/react-data-table';
4
+
5
+ import type {KeyValueRow} from '../../../../types/api/query';
6
+ import type {ValueOf} from '../../../../types/common';
7
+ import {formatNumber, roundToPrecision} from '../../../../utils/dataFormatters/dataFormatters';
8
+ import {getLoadSeverityForShard} from '../../../../store/reducers/tenantOverview/topShards/utils';
9
+ import {InternalLink} from '../../../../components/InternalLink';
10
+ import routes, {createHref} from '../../../../routes';
11
+ import {getDefaultNodePath} from '../../../Node/NodePages';
12
+ import {UsageLabel} from '../../../../components/UsageLabel/UsageLabel';
13
+ import {LinkToSchemaObject} from '../../../../components/LinkToSchemaObject/LinkToSchemaObject';
14
+
15
+ const TOP_SHARDS_COLUMNS_IDS = {
16
+ TabletId: 'TabletId',
17
+ CPUCores: 'CPUCores',
18
+ DataSize: 'DataSize',
19
+ Path: 'Path',
20
+ NodeId: 'NodeId',
21
+ PeakTime: 'PeakTime',
22
+ InFlightTxCount: 'InFlightTxCount',
23
+ IntervalEnd: 'IntervalEnd',
24
+ } as const;
25
+
26
+ type TopShardsColumns = ValueOf<typeof TOP_SHARDS_COLUMNS_IDS>;
27
+
28
+ const tableColumnsNames: Record<TopShardsColumns, string> = {
29
+ TabletId: 'TabletId',
30
+ CPUCores: 'CPUCores',
31
+ DataSize: 'DataSize (B)',
32
+ Path: 'Path',
33
+ NodeId: 'NodeId',
34
+ PeakTime: 'PeakTime',
35
+ InFlightTxCount: 'InFlightTxCount',
36
+ IntervalEnd: 'IntervalEnd',
37
+ };
38
+
39
+ function prepareCPUWorkloadValue(value: string | number) {
40
+ return `${roundToPrecision(Number(value) * 100, 2)}%`;
41
+ }
42
+
43
+ const getPathColumn = (schemaPath: string, location: Location): Column<KeyValueRow> => ({
44
+ name: TOP_SHARDS_COLUMNS_IDS.Path,
45
+ header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.Path],
46
+ render: ({row}) => {
47
+ // row.Path - relative schema path
48
+ return (
49
+ <LinkToSchemaObject path={schemaPath + row.Path} location={location}>
50
+ {row.Path}
51
+ </LinkToSchemaObject>
52
+ );
53
+ },
54
+ sortable: false,
55
+ });
56
+
57
+ const cpuCoresColumn: Column<KeyValueRow> = {
58
+ name: TOP_SHARDS_COLUMNS_IDS.CPUCores,
59
+ header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.CPUCores],
60
+ render: ({row}) => {
61
+ return prepareCPUWorkloadValue(row.CPUCores || 0);
62
+ },
63
+ align: DataTable.RIGHT,
64
+ };
65
+
66
+ const dataSizeColumn: Column<KeyValueRow> = {
67
+ name: TOP_SHARDS_COLUMNS_IDS.DataSize,
68
+ header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.DataSize],
69
+ render: ({row}) => {
70
+ return formatNumber(row.DataSize);
71
+ },
72
+ align: DataTable.RIGHT,
73
+ };
74
+
75
+ const tabletIdColumn: Column<KeyValueRow> = {
76
+ name: TOP_SHARDS_COLUMNS_IDS.TabletId,
77
+ header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.TabletId],
78
+ render: ({row}) => {
79
+ if (!row.TabletId) {
80
+ return '–';
81
+ }
82
+ return (
83
+ <InternalLink to={createHref(routes.tablet, {id: row.TabletId})}>
84
+ {row.TabletId}
85
+ </InternalLink>
86
+ );
87
+ },
88
+ sortable: false,
89
+ };
90
+
91
+ const nodeIdColumn: Column<KeyValueRow> = {
92
+ name: TOP_SHARDS_COLUMNS_IDS.NodeId,
93
+ header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.NodeId],
94
+ render: ({row}) => {
95
+ if (!row.NodeId) {
96
+ return '–';
97
+ }
98
+ return <InternalLink to={getDefaultNodePath(row.NodeId)}>{row.NodeId}</InternalLink>;
99
+ },
100
+ align: DataTable.RIGHT,
101
+ };
102
+
103
+ const topShardsCpuCoresColumn: Column<KeyValueRow> = {
104
+ name: TOP_SHARDS_COLUMNS_IDS.CPUCores,
105
+ header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.CPUCores],
106
+ render: ({row}) => {
107
+ return (
108
+ <UsageLabel
109
+ value={roundToPrecision(Number(row.CPUCores) * 100, 2)}
110
+ theme={getLoadSeverityForShard(Number(row.CPUCores) * 100)}
111
+ />
112
+ );
113
+ },
114
+ align: DataTable.RIGHT,
115
+ sortable: false,
116
+ };
117
+
118
+ const inFlightTxCountColumn: Column<KeyValueRow> = {
119
+ name: TOP_SHARDS_COLUMNS_IDS.InFlightTxCount,
120
+ header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.InFlightTxCount],
121
+ render: ({row}) => formatNumber(row.InFlightTxCount),
122
+ align: DataTable.RIGHT,
123
+ };
124
+
125
+ export const getShardsWorkloadColumns = (schemaPath: string, location: Location) => {
126
+ return [
127
+ getPathColumn(schemaPath, location),
128
+ cpuCoresColumn,
129
+ dataSizeColumn,
130
+ tabletIdColumn,
131
+ nodeIdColumn,
132
+ inFlightTxCountColumn,
133
+ ];
134
+ };
135
+
136
+ export const getTopShardsColumns = (schemaPath: string, location: Location) => {
137
+ return [tabletIdColumn, getPathColumn(schemaPath, location), topShardsCpuCoresColumn];
138
+ };
@@ -3,7 +3,7 @@ import block from 'bem-cn-lite';
3
3
 
4
4
  import type {TEvDescribeSchemeResult} from '../../../../types/api/schema';
5
5
  import {useTypedSelector} from '../../../../utils/hooks';
6
- import {createHref, parseQuery} from '../../../../routes';
6
+ import {createExternalUILink, parseQuery} from '../../../../routes';
7
7
  import {formatCommonItem} from '../../../../components/InfoViewer/formatters';
8
8
  import {InfoViewer, InfoViewerItem} from '../../../../components/InfoViewer';
9
9
  import {ExternalLinkWithIcon} from '../../../../components/ExternalLinkWithIcon/ExternalLinkWithIcon';
@@ -72,9 +72,7 @@ const ExternalTable = ({data, prepareData}: ExternalTableProps) => {
72
72
  const location = useLocation();
73
73
  const query = parseQuery(location);
74
74
 
75
- // embedded version could be located in some folder (e.g. host/some_folder/app_router_path)
76
- // window.location has the full pathname, while location from router ignores path to project
77
- const pathToDataSource = createHref(window.location.pathname, undefined, {
75
+ const pathToDataSource = createExternalUILink({
78
76
  ...query,
79
77
  schema: data?.PathDescription?.ExternalTableDescription?.DataSourcePath,
80
78
  });