ydb-embedded-ui 3.2.3 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +20 -0
- package/dist/components/InfoViewer/InfoViewer.scss +10 -0
- package/dist/components/InfoViewer/InfoViewer.tsx +12 -2
- package/dist/components/InfoViewer/formatters/cdcStream.ts +10 -0
- package/dist/components/InfoViewer/formatters/index.ts +3 -0
- package/dist/components/InfoViewer/formatters/pqGroup.ts +51 -0
- package/dist/components/InfoViewer/formatters/schema.ts +1 -29
- package/dist/components/InfoViewer/formatters/topicStats.tsx +50 -0
- package/dist/components/InfoViewer/schemaInfo/index.ts +0 -2
- package/dist/components/InfoViewer/utils.ts +15 -0
- package/dist/components/InternalLink/InternalLink.tsx +17 -0
- package/dist/components/InternalLink/index.ts +1 -0
- package/dist/components/Tablet/Tablet.js +1 -1
- package/dist/components/TabletsStatistic/TabletsStatistic.tsx +1 -1
- package/dist/components/VerticalBars/VerticalBars.scss +15 -0
- package/dist/components/VerticalBars/VerticalBars.tsx +38 -0
- package/dist/components/VerticalBars/index.ts +1 -0
- package/dist/containers/App/App.js +0 -11
- package/dist/containers/App/App.scss +0 -1
- package/dist/containers/Cluster/Cluster.tsx +2 -2
- package/dist/containers/Nodes/Nodes.scss +5 -1
- package/dist/containers/Nodes/Nodes.tsx +196 -0
- package/dist/containers/{App → Nodes}/NodesTable.scss +2 -2
- package/dist/{utils/getNodesColumns.js → containers/Nodes/getNodesColumns.tsx} +60 -35
- package/dist/containers/Nodes/i18n/en.json +3 -0
- package/dist/containers/Nodes/i18n/index.ts +11 -0
- package/dist/containers/Nodes/i18n/ru.json +3 -0
- package/dist/containers/Nodes/index.ts +1 -0
- package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.scss +14 -20
- package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.tsx +32 -16
- package/dist/containers/Storage/DiskStateProgressBar/index.ts +1 -0
- package/dist/containers/Storage/{Pdisk/Pdisk.scss → PDisk/PDisk.scss} +15 -4
- package/dist/containers/Storage/PDisk/PDisk.tsx +145 -0
- package/dist/containers/Storage/PDisk/__tests__/colors.tsx +37 -0
- package/dist/containers/Storage/PDisk/index.ts +1 -0
- package/dist/containers/Storage/PDiskPopup/PDiskPopup.scss +3 -0
- package/dist/containers/Storage/PDiskPopup/PDiskPopup.tsx +82 -0
- package/dist/containers/Storage/PDiskPopup/index.ts +1 -0
- package/dist/containers/Storage/Storage.js +1 -1
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +10 -10
- package/dist/containers/Storage/StorageNodes/StorageNodes.scss +1 -0
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +7 -4
- package/dist/containers/Storage/VDisk/VDisk.scss +7 -0
- package/dist/containers/Storage/VDisk/VDisk.tsx +148 -0
- package/dist/containers/Storage/VDisk/__tests__/colors.tsx +209 -0
- package/dist/containers/Storage/VDisk/index.ts +1 -0
- package/dist/containers/Storage/VDiskPopup/VDiskPopup.scss +14 -0
- package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +134 -0
- package/dist/containers/Storage/VDiskPopup/index.ts +1 -0
- package/dist/containers/Storage/utils/constants.ts +2 -9
- package/dist/containers/TabletsFilters/TabletsFilters.js +10 -6
- package/dist/containers/Tenant/Diagnostics/Diagnostics.scss +2 -2
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -4
- package/dist/containers/Tenant/Diagnostics/OverloadedShards/OverloadedShards.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +69 -0
- package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +18 -16
- package/dist/containers/Tenant/Diagnostics/Overview/TopicInfo/TopicInfo.tsx +37 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TopicInfo/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.scss +30 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +94 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/en.json +3 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/ru.json +3 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/utils/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/utils/prepareTopicSchemaInfo.ts +42 -0
- package/dist/containers/Tenant/utils/schema.ts +19 -0
- package/dist/containers/UserSettings/UserSettings.tsx +18 -10
- package/dist/services/api.d.ts +8 -1
- package/dist/services/api.js +27 -8
- package/dist/store/reducers/index.ts +3 -1
- package/dist/store/reducers/nodes.ts +148 -14
- package/dist/store/reducers/{clusterNodes.js → nodesList.js} +0 -41
- package/dist/store/reducers/settings.js +10 -4
- package/dist/store/reducers/storage.js +24 -13
- package/dist/store/reducers/tenant.js +5 -4
- package/dist/store/reducers/tooltip.ts +1 -1
- package/dist/store/reducers/topic.ts +52 -0
- package/dist/styles/mixins.scss +19 -11
- package/dist/types/api/common.ts +5 -0
- package/dist/types/api/compute.ts +1 -1
- package/dist/types/api/consumer.ts +12 -10
- package/dist/types/api/nodes.ts +2 -0
- package/dist/types/api/pdisk.ts +1 -0
- package/dist/types/api/schema.ts +3 -3
- package/dist/types/api/topic.ts +5 -4
- package/dist/types/api/vdisk.ts +2 -1
- package/dist/types/store/nodes.ts +56 -6
- package/dist/types/store/tooltip.ts +1 -1
- package/dist/types/store/topic.ts +21 -0
- package/dist/utils/constants.ts +5 -1
- package/dist/utils/i18n/i18n.ts +10 -2
- package/dist/utils/index.js +1 -1
- package/dist/utils/timeParsers/__test__/formatDuration.test.ts +50 -0
- package/dist/utils/timeParsers/__test__/protobuf.test.ts +74 -0
- package/dist/utils/timeParsers/formatDuration.ts +46 -0
- package/dist/utils/timeParsers/i18n/en.json +7 -0
- package/dist/utils/timeParsers/i18n/index.ts +11 -0
- package/dist/utils/timeParsers/i18n/ru.json +7 -0
- package/dist/utils/timeParsers/index.ts +2 -0
- package/dist/utils/timeParsers/protobuf.ts +36 -0
- package/package.json +1 -1
- package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +0 -48
- package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +0 -30
- package/dist/components/InternalLink/InternalLink.js +0 -23
- package/dist/containers/Nodes/Nodes.js +0 -214
- package/dist/containers/NodesViewer/NodesViewer.js +0 -163
- package/dist/containers/NodesViewer/NodesViewer.scss +0 -66
- package/dist/containers/Storage/Pdisk/Pdisk.tsx +0 -153
- package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +0 -41
- package/dist/containers/Storage/Vdisk/Vdisk.js +0 -275
- package/dist/containers/Storage/Vdisk/Vdisk.scss +0 -22
- package/dist/containers/Storage/Vdisk/__tests__/colors.tsx +0 -163
- package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +0 -139
- package/dist/containers/Tenant/Diagnostics/Compute/Compute.scss +0 -14
@@ -23,8 +23,7 @@ import Describe from './Describe/Describe';
|
|
23
23
|
import HotKeys from './HotKeys/HotKeys';
|
24
24
|
//@ts-ignore
|
25
25
|
import {Heatmap} from '../../Heatmap';
|
26
|
-
|
27
|
-
import Compute from './Compute/Compute';
|
26
|
+
import {Nodes} from '../../Nodes';
|
28
27
|
//@ts-ignore
|
29
28
|
import {Tablets} from '../../Tablets';
|
30
29
|
import {Consumers} from './Consumers';
|
@@ -130,8 +129,8 @@ function Diagnostics(props: DiagnosticsProps) {
|
|
130
129
|
}
|
131
130
|
case GeneralPagesIds.nodes: {
|
132
131
|
return (
|
133
|
-
<
|
134
|
-
|
132
|
+
<Nodes
|
133
|
+
tenantPath={tenantNameString}
|
135
134
|
additionalNodesInfo={props.additionalNodesInfo}
|
136
135
|
/>
|
137
136
|
);
|
@@ -6,7 +6,7 @@ import DataTable, {Column, Settings, SortOrder} from '@yandex-cloud/react-data-t
|
|
6
6
|
import {Loader} from '@gravity-ui/uikit';
|
7
7
|
|
8
8
|
import {DateRange, DateRangeValues} from '../../../../components/DateRange';
|
9
|
-
import InternalLink from '../../../../components/InternalLink
|
9
|
+
import {InternalLink} from '../../../../components/InternalLink';
|
10
10
|
|
11
11
|
import HistoryContext from '../../../../contexts/HistoryContext';
|
12
12
|
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
|
2
|
+
|
3
|
+
import {formatObject, InfoViewer, InfoViewerItem} from '../../../../../components/InfoViewer';
|
4
|
+
import {
|
5
|
+
formatCdcStreamItem,
|
6
|
+
formatCommonItem,
|
7
|
+
} from '../../../../../components/InfoViewer/formatters';
|
8
|
+
|
9
|
+
import {useTypedSelector} from '../../../../../utils/hooks';
|
10
|
+
import {selectSchemaData} from '../../../../../store/reducers/schema';
|
11
|
+
|
12
|
+
import {getEntityName} from '../../../utils';
|
13
|
+
|
14
|
+
import {TopicStats} from '../TopicStats';
|
15
|
+
|
16
|
+
import {prepareTopicSchemaInfo} from '../utils';
|
17
|
+
|
18
|
+
const prepareChangefeedInfo = (
|
19
|
+
changefeedData?: TEvDescribeSchemeResult,
|
20
|
+
topicData?: TEvDescribeSchemeResult,
|
21
|
+
): Array<InfoViewerItem> => {
|
22
|
+
if (!changefeedData && !topicData) {
|
23
|
+
return [];
|
24
|
+
}
|
25
|
+
|
26
|
+
const streamDescription = changefeedData?.PathDescription?.CdcStreamDescription;
|
27
|
+
|
28
|
+
const {Mode, Format} = streamDescription || {};
|
29
|
+
|
30
|
+
const created = formatCommonItem(
|
31
|
+
'CreateStep',
|
32
|
+
changefeedData?.PathDescription?.Self?.CreateStep,
|
33
|
+
);
|
34
|
+
const changefeedInfo = formatObject(formatCdcStreamItem, {
|
35
|
+
Mode,
|
36
|
+
Format,
|
37
|
+
});
|
38
|
+
const topicInfo = prepareTopicSchemaInfo(topicData);
|
39
|
+
|
40
|
+
return [created, ...changefeedInfo, ...topicInfo];
|
41
|
+
};
|
42
|
+
|
43
|
+
interface ChangefeedProps {
|
44
|
+
data?: TEvDescribeSchemeResult;
|
45
|
+
childrenPaths?: string[];
|
46
|
+
}
|
47
|
+
|
48
|
+
/** Displays overview for CDCStream EPathType */
|
49
|
+
export const ChangefeedInfo = ({data, childrenPaths}: ChangefeedProps) => {
|
50
|
+
const entityName = getEntityName(data?.PathDescription);
|
51
|
+
|
52
|
+
const {error: schemaError} = useTypedSelector((state) => state.schema);
|
53
|
+
const pqGroupData = useTypedSelector((state) => selectSchemaData(state, childrenPaths?.[0]));
|
54
|
+
|
55
|
+
if (schemaError) {
|
56
|
+
return <div className="error">{schemaError.statusText}</div>;
|
57
|
+
}
|
58
|
+
|
59
|
+
if (!data || !pqGroupData) {
|
60
|
+
return <div className="error">No {entityName} data</div>;
|
61
|
+
}
|
62
|
+
|
63
|
+
return (
|
64
|
+
<div>
|
65
|
+
<InfoViewer title={entityName} info={prepareChangefeedInfo(data, pqGroupData)} />
|
66
|
+
<TopicStats />
|
67
|
+
</div>
|
68
|
+
);
|
69
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './ChangefeedInfo';
|
@@ -6,20 +6,17 @@ import {Loader} from '@gravity-ui/uikit';
|
|
6
6
|
|
7
7
|
//@ts-ignore
|
8
8
|
import SchemaInfoViewer from '../../Schema/SchemaInfoViewer/SchemaInfoViewer';
|
9
|
-
import {
|
10
|
-
CDCStreamInfo,
|
11
|
-
TableIndexInfo,
|
12
|
-
PersQueueGroupInfo,
|
13
|
-
} from '../../../../components/InfoViewer/schemaInfo';
|
9
|
+
import {TableIndexInfo} from '../../../../components/InfoViewer/schemaInfo';
|
14
10
|
|
15
|
-
import {
|
16
|
-
|
17
|
-
|
18
|
-
} from '../../../../types/api/schema';
|
11
|
+
import {TopicInfo} from './TopicInfo';
|
12
|
+
import {ChangefeedInfo} from './ChangefeedInfo';
|
13
|
+
|
14
|
+
import {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
|
19
15
|
import {
|
20
16
|
isEntityWithMergedImplementation,
|
21
17
|
isColumnEntityType,
|
22
18
|
isTableType,
|
19
|
+
isPathTypeWithTopic,
|
23
20
|
} from '../../utils/schema';
|
24
21
|
//@ts-ignore
|
25
22
|
import {
|
@@ -28,6 +25,7 @@ import {
|
|
28
25
|
resetLoadingState,
|
29
26
|
selectSchemaMergedChildrenPaths,
|
30
27
|
} from '../../../../store/reducers/schema';
|
28
|
+
import {getTopic} from '../../../../store/reducers/topic';
|
31
29
|
//@ts-ignore
|
32
30
|
import {
|
33
31
|
getOlapStats,
|
@@ -122,6 +120,10 @@ function Overview({type, tenantName, className}: OverviewProps) {
|
|
122
120
|
}
|
123
121
|
dispatch(getOlapStats({path: schemaPath}));
|
124
122
|
}
|
123
|
+
|
124
|
+
if (isPathTypeWithTopic(type)) {
|
125
|
+
dispatch(getTopic(currentSchemaPath));
|
126
|
+
}
|
125
127
|
},
|
126
128
|
[
|
127
129
|
tenantName,
|
@@ -163,9 +165,9 @@ function Overview({type, tenantName, className}: OverviewProps) {
|
|
163
165
|
[EPathType.EPathTypeColumnStore]: undefined,
|
164
166
|
[EPathType.EPathTypeColumnTable]: undefined,
|
165
167
|
[EPathType.EPathTypeCdcStream]: () => (
|
166
|
-
<
|
168
|
+
<ChangefeedInfo data={schemaData} childrenPaths={mergedChildrenPaths} />
|
167
169
|
),
|
168
|
-
[EPathType.EPathTypePersQueueGroup]: () => <
|
170
|
+
[EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={schemaData} />,
|
169
171
|
};
|
170
172
|
|
171
173
|
return (
|
@@ -175,11 +177,11 @@ function Overview({type, tenantName, className}: OverviewProps) {
|
|
175
177
|
);
|
176
178
|
};
|
177
179
|
|
178
|
-
|
179
|
-
renderLoader()
|
180
|
-
|
181
|
-
|
182
|
-
)
|
180
|
+
if ((loading && !wasLoaded) || (isEntityWithMergedImpl && !mergedChildrenPaths)) {
|
181
|
+
return renderLoader();
|
182
|
+
}
|
183
|
+
|
184
|
+
return <div className={className}>{renderContent()}</div>;
|
183
185
|
}
|
184
186
|
|
185
187
|
export default Overview;
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
|
2
|
+
|
3
|
+
import {InfoViewer} from '../../../../../components/InfoViewer';
|
4
|
+
|
5
|
+
import {useTypedSelector} from '../../../../../utils/hooks';
|
6
|
+
|
7
|
+
import {getEntityName} from '../../../utils';
|
8
|
+
|
9
|
+
import {prepareTopicSchemaInfo} from '../utils';
|
10
|
+
|
11
|
+
import {TopicStats} from '../TopicStats';
|
12
|
+
|
13
|
+
interface TopicInfoProps {
|
14
|
+
data?: TEvDescribeSchemeResult;
|
15
|
+
}
|
16
|
+
|
17
|
+
/** Displays overview for PersQueueGroup EPathType */
|
18
|
+
export const TopicInfo = ({data}: TopicInfoProps) => {
|
19
|
+
const entityName = getEntityName(data?.PathDescription);
|
20
|
+
|
21
|
+
const {error: schemaError} = useTypedSelector((state) => state.schema);
|
22
|
+
|
23
|
+
if (schemaError) {
|
24
|
+
return <div className="error">{schemaError.statusText}</div>;
|
25
|
+
}
|
26
|
+
|
27
|
+
if (!data) {
|
28
|
+
return <div className="error">No {entityName} data</div>;
|
29
|
+
}
|
30
|
+
|
31
|
+
return (
|
32
|
+
<div>
|
33
|
+
<InfoViewer title={entityName} info={prepareTopicSchemaInfo(data)} />
|
34
|
+
<TopicStats />
|
35
|
+
</div>
|
36
|
+
);
|
37
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './TopicInfo';
|
@@ -0,0 +1,30 @@
|
|
1
|
+
@import '../../../../../styles/mixins.scss';
|
2
|
+
|
3
|
+
.ydb-overview-topic-stats {
|
4
|
+
&__title {
|
5
|
+
@include info-viewer-title();
|
6
|
+
}
|
7
|
+
|
8
|
+
.ydb-loader {
|
9
|
+
margin-top: 50px;
|
10
|
+
}
|
11
|
+
|
12
|
+
.ydb-bars {
|
13
|
+
margin-top: -5px;
|
14
|
+
}
|
15
|
+
|
16
|
+
&__info {
|
17
|
+
.info-viewer__label-text_multiline {
|
18
|
+
max-width: 150px;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
&__bytes-written {
|
23
|
+
margin-top: 7px;
|
24
|
+
padding-left: 20px;
|
25
|
+
|
26
|
+
.info-viewer__label {
|
27
|
+
min-width: 180px;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
import {isEmpty} from 'lodash/fp';
|
3
|
+
|
4
|
+
import type {DescribeTopicResult} from '../../../../../types/api/topic';
|
5
|
+
|
6
|
+
import {Loader} from '../../../../../components/Loader';
|
7
|
+
import {InfoViewerItem, formatObject, InfoViewer} from '../../../../../components/InfoViewer';
|
8
|
+
|
9
|
+
import {
|
10
|
+
prepareBytesWritten,
|
11
|
+
formatTopicStats,
|
12
|
+
} from '../../../../../components/InfoViewer/formatters';
|
13
|
+
|
14
|
+
import {useTypedSelector} from '../../../../../utils/hooks';
|
15
|
+
import {formatBps} from '../../../../../utils';
|
16
|
+
|
17
|
+
import i18n from './i18n';
|
18
|
+
|
19
|
+
import './TopicStats.scss';
|
20
|
+
|
21
|
+
const b = cn('ydb-overview-topic-stats');
|
22
|
+
|
23
|
+
const prepareTopicInfo = (data: DescribeTopicResult): Array<InfoViewerItem> => {
|
24
|
+
return [
|
25
|
+
...formatObject(formatTopicStats, {
|
26
|
+
...data.topic_stats,
|
27
|
+
}),
|
28
|
+
];
|
29
|
+
};
|
30
|
+
|
31
|
+
const prepareBytesWrittenInfo = (data: DescribeTopicResult): Array<InfoViewerItem> => {
|
32
|
+
const preparedBytes = prepareBytesWritten(data?.topic_stats?.bytes_written);
|
33
|
+
|
34
|
+
return [
|
35
|
+
{
|
36
|
+
label: 'per minute',
|
37
|
+
value: formatBps(preparedBytes.per_minute),
|
38
|
+
},
|
39
|
+
{
|
40
|
+
label: 'per hour',
|
41
|
+
value: formatBps(preparedBytes.per_hour),
|
42
|
+
},
|
43
|
+
{
|
44
|
+
label: 'per day',
|
45
|
+
value: formatBps(preparedBytes.per_day),
|
46
|
+
},
|
47
|
+
];
|
48
|
+
};
|
49
|
+
|
50
|
+
export const TopicStats = () => {
|
51
|
+
const {data, error, loading, wasLoaded} = useTypedSelector((state) => state.topic);
|
52
|
+
|
53
|
+
if (loading && !wasLoaded) {
|
54
|
+
return (
|
55
|
+
<div className={b()}>
|
56
|
+
<Loader size="s" />
|
57
|
+
</div>
|
58
|
+
);
|
59
|
+
}
|
60
|
+
|
61
|
+
// There are several backed versions with different behaviour
|
62
|
+
// Possible returns on older versions:
|
63
|
+
// 1. Error when trying to access endpoint
|
64
|
+
// 2. No data
|
65
|
+
// 3. HTML page of Internal Viewer with an error
|
66
|
+
// 4. Data with no topic stats
|
67
|
+
// 5. Topic Stats as an empty object
|
68
|
+
if (
|
69
|
+
error ||
|
70
|
+
!data ||
|
71
|
+
typeof data !== 'object' ||
|
72
|
+
!data.topic_stats ||
|
73
|
+
isEmpty(data.topic_stats)
|
74
|
+
) {
|
75
|
+
return (
|
76
|
+
<div className={b()}>
|
77
|
+
<div className={b('title')}>Stats</div>
|
78
|
+
<div className="error">{i18n('notSupportedVersion')}</div>
|
79
|
+
</div>
|
80
|
+
);
|
81
|
+
}
|
82
|
+
|
83
|
+
return (
|
84
|
+
<div className={b()}>
|
85
|
+
<div className={b('title')}>Stats</div>
|
86
|
+
<div className={b('info')}>
|
87
|
+
<InfoViewer info={prepareTopicInfo(data)} multilineLabels />
|
88
|
+
</div>
|
89
|
+
<div className={b('bytes-written')}>
|
90
|
+
<InfoViewer info={prepareBytesWrittenInfo(data)} />
|
91
|
+
</div>
|
92
|
+
</div>
|
93
|
+
);
|
94
|
+
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import {i18n, Lang} from '../../../../../../utils/i18n';
|
2
|
+
|
3
|
+
import en from './en.json';
|
4
|
+
import ru from './ru.json';
|
5
|
+
|
6
|
+
const COMPONENT = 'ydb-diagnostics-overview-topic-stats';
|
7
|
+
|
8
|
+
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
9
|
+
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
10
|
+
|
11
|
+
export default i18n.keyset(COMPONENT);
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './TopicStats';
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './prepareTopicSchemaInfo';
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import type {
|
2
|
+
TEvDescribeSchemeResult,
|
3
|
+
TPersQueueGroupDescription,
|
4
|
+
TPQTabletConfig,
|
5
|
+
TPQPartitionConfig,
|
6
|
+
} from '../../../../../types/api/schema';
|
7
|
+
|
8
|
+
import {formatObject, InfoViewerItem} from '../../../../../components/InfoViewer';
|
9
|
+
import {
|
10
|
+
formatPQGroupItem,
|
11
|
+
formatPQPartitionConfig,
|
12
|
+
formatPQTabletConfig,
|
13
|
+
} from '../../../../../components/InfoViewer/formatters';
|
14
|
+
|
15
|
+
export const prepareTopicSchemaInfo = (data?: TEvDescribeSchemeResult): Array<InfoViewerItem> => {
|
16
|
+
const pqGroupData = data?.PathDescription?.PersQueueGroup;
|
17
|
+
|
18
|
+
if (!pqGroupData) {
|
19
|
+
return [];
|
20
|
+
}
|
21
|
+
|
22
|
+
const {Partitions = [], PQTabletConfig = {PartitionConfig: {LifetimeSeconds: 0}}} = pqGroupData;
|
23
|
+
|
24
|
+
const {Codecs, MeteringMode} = pqGroupData?.PQTabletConfig;
|
25
|
+
const {WriteSpeedInBytesPerSecond, StorageLimitBytes} =
|
26
|
+
pqGroupData?.PQTabletConfig?.PartitionConfig;
|
27
|
+
|
28
|
+
const pqGeneralInfo = formatObject<TPersQueueGroupDescription>(formatPQGroupItem, {
|
29
|
+
Partitions,
|
30
|
+
PQTabletConfig,
|
31
|
+
});
|
32
|
+
const pqPartitionInfo = formatObject<TPQPartitionConfig>(formatPQPartitionConfig, {
|
33
|
+
StorageLimitBytes,
|
34
|
+
WriteSpeedInBytesPerSecond,
|
35
|
+
});
|
36
|
+
const pqTabletInfo = formatObject<TPQTabletConfig>(formatPQTabletConfig, {
|
37
|
+
Codecs,
|
38
|
+
MeteringMode,
|
39
|
+
});
|
40
|
+
|
41
|
+
return [...pqGeneralInfo, ...pqPartitionInfo, ...pqTabletInfo];
|
42
|
+
};
|
@@ -217,3 +217,22 @@ const pathTypeToChildless: Record<EPathType, boolean> = {
|
|
217
217
|
|
218
218
|
export const isChildlessPathType = (type?: EPathType, subType?: EPathSubType) =>
|
219
219
|
((subType && pathSubTypeToChildless[subType]) || (type && pathTypeToChildless[type])) ?? false;
|
220
|
+
|
221
|
+
// ====================
|
222
|
+
|
223
|
+
const mapPathTypeToIsWithTopic: Record<EPathType, boolean> = {
|
224
|
+
[EPathType.EPathTypeCdcStream]: true,
|
225
|
+
[EPathType.EPathTypePersQueueGroup]: true,
|
226
|
+
|
227
|
+
[EPathType.EPathTypeInvalid]: false,
|
228
|
+
[EPathType.EPathTypeColumnStore]: false,
|
229
|
+
[EPathType.EPathTypeColumnTable]: false,
|
230
|
+
[EPathType.EPathTypeDir]: false,
|
231
|
+
[EPathType.EPathTypeTable]: false,
|
232
|
+
[EPathType.EPathTypeSubDomain]: false,
|
233
|
+
[EPathType.EPathTypeTableIndex]: false,
|
234
|
+
[EPathType.EPathTypeExtSubDomain]: false,
|
235
|
+
};
|
236
|
+
|
237
|
+
export const isPathTypeWithTopic = (type?: EPathType) =>
|
238
|
+
(type && mapPathTypeToIsWithTopic[type]) ?? false;
|
@@ -6,7 +6,11 @@ import {Settings} from '@gravity-ui/navigation';
|
|
6
6
|
import favoriteFilledIcon from '../../assets/icons/star.svg';
|
7
7
|
import flaskIcon from '../../assets/icons/flask.svg';
|
8
8
|
|
9
|
-
import {
|
9
|
+
import {
|
10
|
+
INVERTED_DISKS_KEY,
|
11
|
+
THEME_KEY,
|
12
|
+
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
13
|
+
} from '../../utils/constants';
|
10
14
|
|
11
15
|
import {setSettingValue} from '../../store/reducers/settings';
|
12
16
|
|
@@ -25,6 +29,10 @@ function UserSettings(props: any) {
|
|
25
29
|
props.setSettingValue(INVERTED_DISKS_KEY, String(value));
|
26
30
|
};
|
27
31
|
|
32
|
+
const _onNodesEndpointChangeHandler = (value: boolean) => {
|
33
|
+
props.setSettingValue(USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, String(value));
|
34
|
+
};
|
35
|
+
|
28
36
|
return (
|
29
37
|
<Settings>
|
30
38
|
<Settings.Page
|
@@ -42,11 +50,7 @@ function UserSettings(props: any) {
|
|
42
50
|
</Settings.Item>
|
43
51
|
</Settings.Section>
|
44
52
|
</Settings.Page>
|
45
|
-
<Settings.Page
|
46
|
-
id="experiments"
|
47
|
-
title="Experiments"
|
48
|
-
icon={{data: flaskIcon}}
|
49
|
-
>
|
53
|
+
<Settings.Page id="experiments" title="Experiments" icon={{data: flaskIcon}}>
|
50
54
|
<Settings.Section title="Experiments">
|
51
55
|
<Settings.Item title="Inverted disks space indicators">
|
52
56
|
<Switch
|
@@ -54,6 +58,12 @@ function UserSettings(props: any) {
|
|
54
58
|
onUpdate={_onInvertedDisksChangeHandler}
|
55
59
|
/>
|
56
60
|
</Settings.Item>
|
61
|
+
<Settings.Item title="Use /viewer/json/nodes for Nodes Tab in diagnostics">
|
62
|
+
<Switch
|
63
|
+
checked={props.useNodesEndpointInDiagnostics}
|
64
|
+
onUpdate={_onNodesEndpointChangeHandler}
|
65
|
+
/>
|
66
|
+
</Settings.Item>
|
57
67
|
</Settings.Section>
|
58
68
|
</Settings.Page>
|
59
69
|
</Settings>
|
@@ -61,14 +71,12 @@ function UserSettings(props: any) {
|
|
61
71
|
}
|
62
72
|
|
63
73
|
const mapStateToProps = (state: any) => {
|
64
|
-
const {
|
65
|
-
theme,
|
66
|
-
invertedDisks,
|
67
|
-
} = state.settings.userSettings;
|
74
|
+
const {theme, invertedDisks, useNodesEndpointInDiagnostics} = state.settings.userSettings;
|
68
75
|
|
69
76
|
return {
|
70
77
|
theme,
|
71
78
|
invertedDisks: JSON.parse(invertedDisks),
|
79
|
+
useNodesEndpointInDiagnostics: JSON.parse(useNodesEndpointInDiagnostics),
|
72
80
|
};
|
73
81
|
};
|
74
82
|
|
package/dist/services/api.d.ts
CHANGED
@@ -17,10 +17,14 @@ interface Window {
|
|
17
17
|
tenant: string;
|
18
18
|
filter: string;
|
19
19
|
nodeId: string;
|
20
|
-
type: 'Groups' | 'Nodes';
|
21
20
|
},
|
22
21
|
axiosOptions?: AxiosOptions,
|
23
22
|
) => Promise<import('../types/api/storage').TStorageInfo>;
|
23
|
+
getNodes: (
|
24
|
+
params: import('../types/store/nodes').INodesApiRequestParams,
|
25
|
+
axiosOptions?: AxiosOptions,
|
26
|
+
) => Promise<import('../types/api/nodes').TNodesInfo>;
|
27
|
+
getCompute: (path: string) => Promise<import('../types/api/compute').TComputeInfo>;
|
24
28
|
sendQuery: <
|
25
29
|
Action extends import('../types/api/query').Actions,
|
26
30
|
Schema extends import('../types/api/query').Schemas = undefined,
|
@@ -55,6 +59,9 @@ interface Window {
|
|
55
59
|
getHeatmapData: (params: {
|
56
60
|
path: string;
|
57
61
|
}) => Promise<import('../types/api/schema').TEvDescribeSchemeResult>;
|
62
|
+
getTopic: (params: {
|
63
|
+
path?: string;
|
64
|
+
}) => Promise<import('../types/api/topic').DescribeTopicResult>;
|
58
65
|
[method: string]: Function;
|
59
66
|
};
|
60
67
|
}
|
package/dist/services/api.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import AxiosWrapper from '@gravity-ui/axios-wrapper';
|
2
2
|
|
3
3
|
import {backend as BACKEND} from '../store';
|
4
|
-
import {StorageTypes} from '../store/reducers/storage';
|
5
4
|
|
6
5
|
const config = {withCredentials: !window.custom_backend};
|
7
6
|
|
@@ -14,9 +13,6 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
14
13
|
getClusterInfo() {
|
15
14
|
return this.get(this.getPath('/viewer/json/cluster'), {tablets: true});
|
16
15
|
}
|
17
|
-
getNodes(path) {
|
18
|
-
return this.get(this.getPath('/viewer/json/compute?enums=true'), {path});
|
19
|
-
}
|
20
16
|
getNodeInfo(id) {
|
21
17
|
return this.get(this.getPath('/viewer/json/sysinfo?enums=true'), {
|
22
18
|
node_id: id,
|
@@ -35,11 +31,27 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
35
31
|
storage: true,
|
36
32
|
});
|
37
33
|
}
|
38
|
-
|
34
|
+
getNodes({tenant, filter, storage, type = 'any', tablets = true}, {concurrentId} = {}) {
|
35
|
+
return this.get(
|
36
|
+
this.getPath('/viewer/json/nodes?enums=true'),
|
37
|
+
{
|
38
|
+
tenant,
|
39
|
+
with: filter,
|
40
|
+
storage,
|
41
|
+
type,
|
42
|
+
tablets,
|
43
|
+
},
|
44
|
+
{
|
45
|
+
concurrentId,
|
46
|
+
},
|
47
|
+
);
|
48
|
+
}
|
49
|
+
getCompute(path) {
|
50
|
+
return this.get(this.getPath('/viewer/json/compute?enums=true'), {path});
|
51
|
+
}
|
52
|
+
getStorageInfo({tenant, filter, nodeId}, {concurrentId} = {}) {
|
39
53
|
return this.get(
|
40
|
-
this.getPath(
|
41
|
-
`/viewer/json/${type === StorageTypes.nodes ? 'nodes' : 'storage'}?enums=true`,
|
42
|
-
),
|
54
|
+
this.getPath(`/viewer/json/storage?enums=true`),
|
43
55
|
{
|
44
56
|
tenant,
|
45
57
|
node_id: nodeId,
|
@@ -129,6 +141,13 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
129
141
|
path,
|
130
142
|
});
|
131
143
|
}
|
144
|
+
getTopic({path}) {
|
145
|
+
return this.get(this.getPath('/viewer/json/describe_topic'), {
|
146
|
+
enums: true,
|
147
|
+
include_stats: true,
|
148
|
+
path,
|
149
|
+
});
|
150
|
+
}
|
132
151
|
getPoolInfo(poolName) {
|
133
152
|
return this.get(this.getPath('/viewer/json/storage'), {
|
134
153
|
pool: poolName,
|
@@ -17,12 +17,13 @@ import network from './network';
|
|
17
17
|
import pool from './pool';
|
18
18
|
import tenants from './tenants';
|
19
19
|
import tablet from './tablet';
|
20
|
+
import topic from './topic';
|
20
21
|
import executeQuery from './executeQuery';
|
21
22
|
import explainQuery from './explainQuery';
|
22
23
|
import tabletsFilters from './tabletsFilters';
|
23
24
|
import settings from './settings';
|
24
25
|
import preview from './preview';
|
25
|
-
import nodesList from './
|
26
|
+
import nodesList from './nodesList';
|
26
27
|
import describe from './describe';
|
27
28
|
import schemaAcl from './schemaAcl';
|
28
29
|
import executeTopQueries from './executeTopQueries';
|
@@ -55,6 +56,7 @@ export const rootReducer = {
|
|
55
56
|
pool,
|
56
57
|
tenants,
|
57
58
|
tablet,
|
59
|
+
topic,
|
58
60
|
executeQuery,
|
59
61
|
explainQuery,
|
60
62
|
tabletsFilters,
|