ydb-embedded-ui 3.4.5 → 3.5.0
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/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
|
}
|