ydb-embedded-ui 3.4.5 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +19 -0
- package/dist/components/InfoViewer/formatters/table.ts +6 -0
- package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
- package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
- package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
- package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +1 -0
- package/dist/routes.ts +1 -1
- package/dist/services/api.js +3 -3
- package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +51 -21
- package/dist/store/reducers/executeTopQueries.ts +5 -1
- package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
- package/dist/store/reducers/settings.js +1 -1
- package/dist/store/reducers/storage.js +5 -7
- package/dist/types/api/query.ts +4 -1
- package/dist/types/api/schema.ts +523 -3
- package/dist/types/common.ts +1 -0
- package/dist/types/store/executeQuery.ts +42 -0
- package/dist/types/store/olapStats.ts +14 -0
- package/dist/utils/query.test.ts +42 -29
- package/dist/utils/query.ts +34 -22
- package/dist/utils/timeParsers/formatDuration.ts +30 -12
- package/dist/utils/timeParsers/i18n/en.json +4 -0
- package/dist/utils/timeParsers/i18n/ru.json +4 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.5.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.4.5...v3.5.0) (2023-04-18)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **TableInfo:** extend Table and ColumnTable info ([89e54aa](https://github.com/ydb-platform/ydb-embedded-ui/commit/89e54aa97d7bcbabfd5100daeb1dc0c03608e86e))
|
9
|
+
* **TopQueries:** add columns ([b49b98d](https://github.com/ydb-platform/ydb-embedded-ui/commit/b49b98db2da08c355b23f4a33bf05247530543db))
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* **settings:** use system theme by default ([726c9cb](https://github.com/ydb-platform/ydb-embedded-ui/commit/726c9cb14d7f87cc9248340d1ebebfc8bf0d0384))
|
15
|
+
* **Storage:** fix incorrect usage on zero available space ([2704cd7](https://github.com/ydb-platform/ydb-embedded-ui/commit/2704cd7c696d337cc8e3af68941cf444f8dfae81))
|
16
|
+
* **TableInfo:** add default format for FollowerGroup fields ([961334a](https://github.com/ydb-platform/ydb-embedded-ui/commit/961334aabe89672994f0f3440e20602e180b3394))
|
17
|
+
* **Tablet:** fix dialog type enum ([c477042](https://github.com/ydb-platform/ydb-embedded-ui/commit/c477042cacc2e777cae4bd6981381a8042c603ed))
|
18
|
+
* **TopQueries:** enable go back to TopQueries from Query tab ([bbdfe72](https://github.com/ydb-platform/ydb-embedded-ui/commit/bbdfe726c9081f01422dca787b83399ea44b3956))
|
19
|
+
* **TopShards:** fix table crash on undefined values ([604e99a](https://github.com/ydb-platform/ydb-embedded-ui/commit/604e99a9427021c61ceb8ea366e316e629032b84))
|
20
|
+
* **TruncatedQuery:** wrap message ([f41b7ff](https://github.com/ydb-platform/ydb-embedded-ui/commit/f41b7ff33ac0145446ca89aab031036247f3ddf8))
|
21
|
+
|
3
22
|
## [3.4.5](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.4.4...v3.4.5) (2023-03-30)
|
4
23
|
|
5
24
|
|
@@ -20,6 +20,12 @@ export const formatFollowerGroupItem = createInfoFormatter<TFollowerGroup>({
|
|
20
20
|
values: {
|
21
21
|
FollowerCount: formatNumber,
|
22
22
|
},
|
23
|
+
labels: {
|
24
|
+
// Make it shorter to fit label width
|
25
|
+
FollowerCountPerDataCenter: 'FollowerCountPerDC',
|
26
|
+
},
|
27
|
+
// Most of the FollowerGroup fields are arrays or boolean
|
28
|
+
defaultValueFormatter: (value) => value && String(value),
|
23
29
|
});
|
24
30
|
|
25
31
|
export const formatPartitionConfigItem = createInfoFormatter<TPartitionConfig>({
|
@@ -16,7 +16,7 @@ function TruncatedQuery({value, maxQueryHeight}) {
|
|
16
16
|
return (
|
17
17
|
<React.Fragment>
|
18
18
|
<span className={b()}>{content}</span>
|
19
|
-
<span className={b({color: 'secondary'})}>{message}</span>
|
19
|
+
<span className={b('message', {color: 'secondary'})}>{message}</span>
|
20
20
|
</React.Fragment>
|
21
21
|
);
|
22
22
|
}
|
@@ -5,9 +5,13 @@
|
|
5
5
|
white-space: pre;
|
6
6
|
word-break: break-word;
|
7
7
|
|
8
|
-
&
|
9
|
-
|
10
|
-
|
8
|
+
&__message {
|
9
|
+
white-space: pre-wrap;
|
10
|
+
|
11
|
+
&_color {
|
12
|
+
&_secondary {
|
13
|
+
color: var(--yc-color-text-secondary);
|
14
|
+
}
|
11
15
|
}
|
12
16
|
}
|
13
17
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {ReactNode, useCallback
|
1
|
+
import {ReactNode, useCallback} from 'react';
|
2
2
|
import {shallowEqual, useDispatch, useSelector} from 'react-redux';
|
3
3
|
|
4
4
|
import {Loader} from '../../../../components/Loader';
|
@@ -11,7 +11,7 @@ import {TopicInfo} from './TopicInfo';
|
|
11
11
|
import {ChangefeedInfo} from './ChangefeedInfo';
|
12
12
|
import {TableInfo} from './TableInfo';
|
13
13
|
|
14
|
-
import {EPathType
|
14
|
+
import {EPathType} from '../../../../types/api/schema';
|
15
15
|
import {
|
16
16
|
isEntityWithMergedImplementation,
|
17
17
|
isColumnEntityType,
|
@@ -33,35 +33,6 @@ import {
|
|
33
33
|
} from '../../../../store/reducers/olapStats';
|
34
34
|
import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
|
35
35
|
|
36
|
-
function prepareOlapTableGeneral(item?: TEvDescribeSchemeResult, olapStats?: any[]) {
|
37
|
-
const tableData = item?.PathDescription?.ColumnTableDescription;
|
38
|
-
|
39
|
-
const Bytes = olapStats?.reduce((acc, el) => {
|
40
|
-
acc += parseInt(el.Bytes) || 0;
|
41
|
-
return acc;
|
42
|
-
}, 0);
|
43
|
-
const Rows = olapStats?.reduce((acc, el) => {
|
44
|
-
acc += parseInt(el.Rows) || 0;
|
45
|
-
return acc;
|
46
|
-
}, 0);
|
47
|
-
const tabletIds = olapStats?.reduce((acc, el) => {
|
48
|
-
acc.add(el.TabletId);
|
49
|
-
return acc;
|
50
|
-
}, new Set());
|
51
|
-
|
52
|
-
return {
|
53
|
-
PathDescription: {
|
54
|
-
Self: item?.PathDescription?.Self,
|
55
|
-
TableStats: {
|
56
|
-
ColumnShardCount: tableData?.ColumnShardCount,
|
57
|
-
Bytes: Bytes?.toLocaleString('ru-RU', {useGrouping: true}) ?? 0,
|
58
|
-
Rows: Rows?.toLocaleString('ru-RU', {useGrouping: true}) ?? 0,
|
59
|
-
Parts: tabletIds?.size ?? 0,
|
60
|
-
},
|
61
|
-
},
|
62
|
-
};
|
63
|
-
}
|
64
|
-
|
65
36
|
interface OverviewProps {
|
66
37
|
type?: EPathType;
|
67
38
|
className?: string;
|
@@ -81,7 +52,7 @@ function Overview({type, tenantName, className}: OverviewProps) {
|
|
81
52
|
} = useSelector((state: any) => state.schema);
|
82
53
|
|
83
54
|
const {data: {result: olapStats} = {result: undefined}, loading: olapStatsLoading} =
|
84
|
-
|
55
|
+
useTypedSelector((state) => state.olapStats);
|
85
56
|
|
86
57
|
const loading = schemaLoading || olapStatsLoading;
|
87
58
|
|
@@ -134,13 +105,6 @@ function Overview({type, tenantName, className}: OverviewProps) {
|
|
134
105
|
|
135
106
|
useAutofetcher(fetchData, [fetchData], autorefresh);
|
136
107
|
|
137
|
-
const schemaData = useMemo(() => {
|
138
|
-
return isTableType(type) && isColumnEntityType(type)
|
139
|
-
? // process data for ColumnTable
|
140
|
-
prepareOlapTableGeneral(currentItem, olapStats)
|
141
|
-
: currentItem;
|
142
|
-
}, [type, olapStats, currentItem]);
|
143
|
-
|
144
108
|
const renderContent = () => {
|
145
109
|
// verbose mapping to guarantee a correct render for new path types
|
146
110
|
// TS will error when a new type is added but not mapped here
|
@@ -149,17 +113,21 @@ function Overview({type, tenantName, className}: OverviewProps) {
|
|
149
113
|
[EPathType.EPathTypeDir]: undefined,
|
150
114
|
[EPathType.EPathTypeTable]: undefined,
|
151
115
|
[EPathType.EPathTypeSubDomain]: undefined,
|
152
|
-
[EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={
|
116
|
+
[EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={currentItem} />,
|
153
117
|
[EPathType.EPathTypeExtSubDomain]: undefined,
|
154
118
|
[EPathType.EPathTypeColumnStore]: undefined,
|
155
119
|
[EPathType.EPathTypeColumnTable]: undefined,
|
156
120
|
[EPathType.EPathTypeCdcStream]: () => (
|
157
|
-
<ChangefeedInfo data={
|
121
|
+
<ChangefeedInfo data={currentItem} childrenPaths={mergedChildrenPaths} />
|
158
122
|
),
|
159
|
-
[EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={
|
123
|
+
[EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={currentItem} />,
|
160
124
|
};
|
161
125
|
|
162
|
-
return (
|
126
|
+
return (
|
127
|
+
(type && pathTypeToComponent[type]?.()) || (
|
128
|
+
<TableInfo data={currentItem} type={type} olapStats={olapStats} />
|
129
|
+
)
|
130
|
+
);
|
163
131
|
};
|
164
132
|
|
165
133
|
if ((loading && !wasLoaded) || (isEntityWithMergedImpl && !mergedChildrenPaths)) {
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import {useMemo} from 'react';
|
2
2
|
import cn from 'bem-cn-lite';
|
3
3
|
|
4
|
-
import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
|
5
|
-
|
4
|
+
import type {EPathType, TEvDescribeSchemeResult} from '../../../../../types/api/schema';
|
5
|
+
import type {KeyValueRow} from '../../../../../types/api/query';
|
6
6
|
import {InfoViewer} from '../../../../../components/InfoViewer';
|
7
7
|
|
8
8
|
import {getEntityName} from '../../../utils';
|
@@ -17,27 +17,40 @@ const b = cn('ydb-diagnostics-table-info');
|
|
17
17
|
|
18
18
|
interface TableInfoProps {
|
19
19
|
data?: TEvDescribeSchemeResult;
|
20
|
+
type?: EPathType;
|
21
|
+
olapStats?: KeyValueRow[];
|
20
22
|
}
|
21
23
|
|
22
|
-
export const TableInfo = ({data}: TableInfoProps) => {
|
24
|
+
export const TableInfo = ({data, type, olapStats}: TableInfoProps) => {
|
23
25
|
const entityName = getEntityName(data?.PathDescription);
|
24
26
|
|
25
27
|
const {
|
26
|
-
|
28
|
+
generalInfo = [],
|
27
29
|
tableStatsInfo = [],
|
28
30
|
tabletMetricsInfo = [],
|
29
31
|
partitionConfigInfo = [],
|
30
|
-
} = useMemo(() => prepareTableInfo(data), [data]);
|
32
|
+
} = useMemo(() => prepareTableInfo(data, type, olapStats), [data, type, olapStats]);
|
31
33
|
|
32
34
|
return (
|
33
35
|
<div className={b()}>
|
34
36
|
<InfoViewer
|
35
|
-
info={
|
37
|
+
info={generalInfo}
|
36
38
|
title={entityName}
|
37
39
|
className={b('info-block')}
|
38
40
|
renderEmptyState={() => <div className={b('title')}>{entityName}</div>}
|
39
41
|
/>
|
40
42
|
<div className={b('row')}>
|
43
|
+
<div className={b('col')}>
|
44
|
+
{tableStatsInfo.map((info, index) => (
|
45
|
+
<InfoViewer
|
46
|
+
key={index}
|
47
|
+
info={info}
|
48
|
+
title={index === 0 ? i18n('tableStats') : undefined}
|
49
|
+
className={b('info-block')}
|
50
|
+
renderEmptyState={() => null}
|
51
|
+
/>
|
52
|
+
))}
|
53
|
+
</div>
|
41
54
|
{tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (
|
42
55
|
<div className={b('col')}>
|
43
56
|
<InfoViewer
|
@@ -54,17 +67,6 @@ export const TableInfo = ({data}: TableInfoProps) => {
|
|
54
67
|
/>
|
55
68
|
</div>
|
56
69
|
) : null}
|
57
|
-
<div className={b('col')}>
|
58
|
-
{tableStatsInfo.map((info, index) => (
|
59
|
-
<InfoViewer
|
60
|
-
key={index}
|
61
|
-
info={info}
|
62
|
-
title={index === 0 ? i18n('tableStats') : undefined}
|
63
|
-
className={b('info-block')}
|
64
|
-
renderEmptyState={() => null}
|
65
|
-
/>
|
66
|
-
))}
|
67
|
-
</div>
|
68
70
|
</div>
|
69
71
|
</div>
|
70
72
|
);
|
@@ -1,6 +1,16 @@
|
|
1
|
-
import type {
|
2
|
-
|
3
|
-
|
1
|
+
import type {
|
2
|
+
TColumnDataLifeCycle,
|
3
|
+
TColumnTableDescription,
|
4
|
+
TEvDescribeSchemeResult,
|
5
|
+
TPartitionConfig,
|
6
|
+
TTTLSettings,
|
7
|
+
} from '../../../../../types/api/schema';
|
8
|
+
import type {KeyValueRow} from '../../../../../types/api/query';
|
9
|
+
import {EPathType} from '../../../../../types/api/schema';
|
10
|
+
import {isNumeric} from '../../../../../utils/utils';
|
11
|
+
import {formatBytes, formatNumber} from '../../../../../utils';
|
12
|
+
import {formatDurationToShortTimeFormat} from '../../../../../utils/timeParsers';
|
13
|
+
import {formatObject, InfoViewerItem} from '../../../../../components/InfoViewer';
|
4
14
|
import {
|
5
15
|
formatFollowerGroupItem,
|
6
16
|
formatPartitionConfigItem,
|
@@ -8,7 +18,134 @@ import {
|
|
8
18
|
formatTabletMetricsItem,
|
9
19
|
} from '../../../../../components/InfoViewer/formatters';
|
10
20
|
|
11
|
-
|
21
|
+
const isInStoreColumnTable = (table: TColumnTableDescription) => {
|
22
|
+
// SchemaPresetId could be 0
|
23
|
+
return table.SchemaPresetName && table.SchemaPresetId !== undefined;
|
24
|
+
};
|
25
|
+
|
26
|
+
const prepareOlapStats = (olapStats?: KeyValueRow[]) => {
|
27
|
+
const Bytes = olapStats?.reduce((acc, el) => {
|
28
|
+
const value = isNumeric(el.Bytes) ? Number(el.Bytes) : 0;
|
29
|
+
return acc + value;
|
30
|
+
}, 0);
|
31
|
+
const Rows = olapStats?.reduce((acc, el) => {
|
32
|
+
const value = isNumeric(el.Rows) ? Number(el.Rows) : 0;
|
33
|
+
return acc + value;
|
34
|
+
}, 0);
|
35
|
+
const tabletIds = olapStats?.reduce((acc, el) => {
|
36
|
+
acc.add(el.TabletId);
|
37
|
+
return acc;
|
38
|
+
}, new Set());
|
39
|
+
|
40
|
+
return [
|
41
|
+
{label: 'PartCount', value: tabletIds?.size ?? 0},
|
42
|
+
{label: 'RowCount', value: formatNumber(Rows) ?? 0},
|
43
|
+
{label: 'DataSize', value: formatBytes(Bytes) ?? 0},
|
44
|
+
];
|
45
|
+
};
|
46
|
+
|
47
|
+
const prepareTTL = (ttl: TTTLSettings | TColumnDataLifeCycle) => {
|
48
|
+
// ExpireAfterSeconds could be 0
|
49
|
+
if (ttl.Enabled && ttl.Enabled.ColumnName && ttl.Enabled.ExpireAfterSeconds !== undefined) {
|
50
|
+
const value = `column: '${
|
51
|
+
ttl.Enabled.ColumnName
|
52
|
+
}', expire after: ${formatDurationToShortTimeFormat(
|
53
|
+
ttl.Enabled.ExpireAfterSeconds * 1000,
|
54
|
+
1,
|
55
|
+
)}`;
|
56
|
+
|
57
|
+
return {label: 'TTL for rows', value};
|
58
|
+
}
|
59
|
+
return undefined;
|
60
|
+
};
|
61
|
+
|
62
|
+
function prepareColumnTableGeneralInfo(columnTable: TColumnTableDescription) {
|
63
|
+
const columnTableGeneralInfo: InfoViewerItem[] = [];
|
64
|
+
|
65
|
+
columnTableGeneralInfo.push({
|
66
|
+
label: 'Standalone',
|
67
|
+
value: String(!isInStoreColumnTable(columnTable)),
|
68
|
+
});
|
69
|
+
|
70
|
+
if (columnTable.Sharding && columnTable.Sharding.HashSharding) {
|
71
|
+
columnTableGeneralInfo.push({label: 'Sharding', value: 'hash'});
|
72
|
+
}
|
73
|
+
|
74
|
+
if (columnTable.TtlSettings) {
|
75
|
+
const ttlInfo = prepareTTL(columnTable?.TtlSettings);
|
76
|
+
if (ttlInfo) {
|
77
|
+
columnTableGeneralInfo.push(ttlInfo);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
return columnTableGeneralInfo;
|
82
|
+
}
|
83
|
+
|
84
|
+
const prepareTableGeneralInfo = (PartitionConfig: TPartitionConfig, TTLSettings?: TTTLSettings) => {
|
85
|
+
const {PartitioningPolicy = {}, FollowerGroups, EnableFilterByKey} = PartitionConfig;
|
86
|
+
|
87
|
+
const generalTableInfo: InfoViewerItem[] = [];
|
88
|
+
|
89
|
+
const partitioningBySize = PartitioningPolicy.SizeToSplit
|
90
|
+
? `Enabled, split size: ${formatBytes(PartitioningPolicy.SizeToSplit)}`
|
91
|
+
: 'Disabled';
|
92
|
+
|
93
|
+
const partitioningByLoad = PartitioningPolicy.SplitByLoadSettings?.Enabled
|
94
|
+
? 'Enabled'
|
95
|
+
: 'Disabled';
|
96
|
+
|
97
|
+
generalTableInfo.push(
|
98
|
+
{label: 'Partitioning by size', value: partitioningBySize},
|
99
|
+
{label: 'Partitioning by load', value: partitioningByLoad},
|
100
|
+
{
|
101
|
+
label: 'Min number of partitions',
|
102
|
+
value: PartitioningPolicy.MinPartitionsCount || 0,
|
103
|
+
},
|
104
|
+
);
|
105
|
+
|
106
|
+
if (PartitioningPolicy.MaxPartitionsCount) {
|
107
|
+
generalTableInfo.push({
|
108
|
+
label: 'Max number of partitions',
|
109
|
+
value: PartitioningPolicy.MaxPartitionsCount || 0,
|
110
|
+
});
|
111
|
+
}
|
112
|
+
|
113
|
+
if (FollowerGroups && FollowerGroups.length) {
|
114
|
+
const {RequireAllDataCenters, FollowerCountPerDataCenter, FollowerCount} =
|
115
|
+
FollowerGroups[0];
|
116
|
+
|
117
|
+
let readReplicasConfig: string;
|
118
|
+
|
119
|
+
if (RequireAllDataCenters && FollowerCountPerDataCenter) {
|
120
|
+
readReplicasConfig = `PER_AZ: ${FollowerCount}`;
|
121
|
+
} else {
|
122
|
+
readReplicasConfig = `ANY_AZ: ${FollowerCount}`;
|
123
|
+
}
|
124
|
+
|
125
|
+
generalTableInfo.push({label: 'Read replicas (followers)', value: readReplicasConfig});
|
126
|
+
}
|
127
|
+
|
128
|
+
if (TTLSettings) {
|
129
|
+
const ttlInfo = prepareTTL(TTLSettings);
|
130
|
+
if (ttlInfo) {
|
131
|
+
generalTableInfo.push(ttlInfo);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
generalTableInfo.push({
|
136
|
+
label: 'Bloom filter',
|
137
|
+
value: EnableFilterByKey ? 'Enabled' : 'Disabled',
|
138
|
+
});
|
139
|
+
|
140
|
+
return generalTableInfo;
|
141
|
+
};
|
142
|
+
|
143
|
+
/** Prepares data for Table, ColumnTable and ColumnStore */
|
144
|
+
export const prepareTableInfo = (
|
145
|
+
data?: TEvDescribeSchemeResult,
|
146
|
+
type?: EPathType,
|
147
|
+
olapStats?: KeyValueRow[],
|
148
|
+
) => {
|
12
149
|
if (!data) {
|
13
150
|
return {};
|
14
151
|
}
|
@@ -18,7 +155,8 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
|
|
18
155
|
const {
|
19
156
|
TableStats = {},
|
20
157
|
TabletMetrics = {},
|
21
|
-
Table: {PartitionConfig = {}} = {},
|
158
|
+
Table: {PartitionConfig = {}, TTLSettings} = {},
|
159
|
+
ColumnTableDescription = {},
|
22
160
|
} = PathDescription;
|
23
161
|
|
24
162
|
const {
|
@@ -42,45 +180,62 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
|
|
42
180
|
RowReads,
|
43
181
|
RangeReads,
|
44
182
|
RangeReadRows,
|
45
|
-
|
46
|
-
...restTableStats
|
47
183
|
} = TableStats;
|
48
184
|
|
49
185
|
const {FollowerGroups, FollowerCount, CrossDataCenterFollowerCount} = PartitionConfig;
|
50
186
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
187
|
+
let generalInfo: InfoViewerItem[] = [];
|
188
|
+
|
189
|
+
switch (type) {
|
190
|
+
case EPathType.EPathTypeTable: {
|
191
|
+
generalInfo = prepareTableGeneralInfo(PartitionConfig, TTLSettings);
|
192
|
+
break;
|
193
|
+
}
|
194
|
+
case EPathType.EPathTypeColumnTable: {
|
195
|
+
generalInfo = prepareColumnTableGeneralInfo(ColumnTableDescription);
|
196
|
+
break;
|
197
|
+
}
|
198
|
+
}
|
58
199
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
200
|
+
let tableStatsInfo: InfoViewerItem[][];
|
201
|
+
|
202
|
+
// There is no TableStats and TabletMetrics for ColumnTables inside ColumnStore
|
203
|
+
// Therefore we parse olapStats
|
204
|
+
if (type === EPathType.EPathTypeColumnTable && isInStoreColumnTable(ColumnTableDescription)) {
|
205
|
+
tableStatsInfo = [prepareOlapStats(olapStats)];
|
206
|
+
} else {
|
207
|
+
tableStatsInfo = [
|
208
|
+
formatObject(formatTableStatsItem, {
|
209
|
+
PartCount,
|
210
|
+
RowCount,
|
211
|
+
DataSize,
|
212
|
+
IndexSize,
|
213
|
+
}),
|
214
|
+
formatObject(formatTableStatsItem, {
|
215
|
+
LastAccessTime,
|
216
|
+
LastUpdateTime,
|
217
|
+
}),
|
218
|
+
formatObject(formatTableStatsItem, {
|
219
|
+
ImmediateTxCompleted,
|
220
|
+
PlannedTxCompleted,
|
221
|
+
TxRejectedByOverload,
|
222
|
+
TxRejectedBySpace,
|
223
|
+
TxCompleteLagMsec,
|
224
|
+
InFlightTxCount,
|
225
|
+
}),
|
226
|
+
formatObject(formatTableStatsItem, {
|
227
|
+
RowUpdates,
|
228
|
+
RowDeletes,
|
229
|
+
RowReads,
|
230
|
+
RangeReads,
|
231
|
+
RangeReadRows,
|
232
|
+
}),
|
233
|
+
];
|
234
|
+
}
|
80
235
|
|
81
236
|
const tabletMetricsInfo = formatObject(formatTabletMetricsItem, TabletMetrics);
|
82
237
|
|
83
|
-
let partitionConfigInfo = [];
|
238
|
+
let partitionConfigInfo: InfoViewerItem[] = [];
|
84
239
|
|
85
240
|
if (Array.isArray(FollowerGroups) && FollowerGroups.length > 0) {
|
86
241
|
partitionConfigInfo = formatObject(formatFollowerGroupItem, FollowerGroups[0]);
|
@@ -92,5 +247,5 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
|
|
92
247
|
);
|
93
248
|
}
|
94
249
|
|
95
|
-
return {
|
250
|
+
return {generalInfo, tableStatsInfo, tabletMetricsInfo, partitionConfigInfo};
|
96
251
|
};
|
@@ -25,27 +25,33 @@
|
|
25
25
|
@include search();
|
26
26
|
}
|
27
27
|
|
28
|
-
&
|
28
|
+
&__table {
|
29
29
|
overflow: auto;
|
30
30
|
flex-grow: 1;
|
31
31
|
|
32
32
|
.data-table {
|
33
|
-
&,
|
34
|
-
&__table {
|
35
|
-
width: 100%;
|
36
|
-
}
|
37
|
-
|
38
|
-
&__td {
|
39
|
-
vertical-align: top;
|
40
|
-
white-space: pre;
|
41
|
-
word-break: break-word;
|
42
|
-
}
|
43
|
-
|
44
33
|
&__row {
|
45
|
-
max-height: 80px;
|
46
|
-
|
47
34
|
cursor: pointer;
|
48
35
|
}
|
49
36
|
}
|
50
37
|
}
|
38
|
+
|
39
|
+
&__query {
|
40
|
+
overflow: hidden;
|
41
|
+
|
42
|
+
width: 500px;
|
43
|
+
|
44
|
+
vertical-align: top;
|
45
|
+
white-space: pre-wrap;
|
46
|
+
text-overflow: ellipsis;
|
47
|
+
word-break: break-word;
|
48
|
+
}
|
49
|
+
|
50
|
+
&__user-sid {
|
51
|
+
overflow: hidden;
|
52
|
+
|
53
|
+
max-width: 200px;
|
54
|
+
|
55
|
+
text-overflow: ellipsis;
|
56
|
+
}
|
51
57
|
}
|