Skip to content

Commit

Permalink
feat(ClusterInfo): display groups stats
Browse files Browse the repository at this point in the history
  • Loading branch information
artemmufazalov committed Nov 30, 2023
1 parent c99b7e2 commit 79e5347
Show file tree
Hide file tree
Showing 13 changed files with 445 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/components/ProgressViewer/ProgressViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Props description:
interface ProgressViewerProps {
value?: number | string;
capacity?: number | string;
formatValues?: (value?: number, capacity?: number) => (string | undefined)[];
formatValues?: (value?: number, capacity?: number) => (string | number | undefined)[];
percents?: boolean;
className?: string;
size?: ProgressViewerSize;
Expand Down
2 changes: 2 additions & 0 deletions src/containers/Cluster/Cluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function Cluster({
loading: clusterLoading,
wasLoaded: clusterWasLoaded,
error: clusterError,
groupsStats,
} = useTypedSelector((state) => state.cluster);
const {
nodes,
Expand Down Expand Up @@ -135,6 +136,7 @@ function Cluster({
<div className={b()} ref={container}>
<ClusterInfo
cluster={cluster}
groupsStats={groupsStats}
versionsValues={versionsValues}
loading={infoLoading}
error={clusterError}
Expand Down
19 changes: 14 additions & 5 deletions src/containers/Cluster/ClusterInfo/ClusterInfo.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@
}
}

&__metric-field {
margin-top: -8px;
}

&__system-tablets {
display: flex;
flex-wrap: wrap;
Expand Down Expand Up @@ -83,14 +79,27 @@
margin-left: 15px;
padding: 0 !important;
}

&__links {
display: flex;
flex-flow: row wrap;

gap: 12px;
}

&__storage-groups-stats {
display: flex;
flex-direction: column;
gap: 11px;
}

&__groups-stats-bar {
cursor: pointer;
}

&__groups-stats-popup-content {
padding: 12px;
}

&__clipboard-button {
display: flex;
align-items: center;
Expand Down
121 changes: 97 additions & 24 deletions src/containers/Cluster/ClusterInfo/ClusterInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {Tablet} from '../../../components/Tablet';
import {ResponseError} from '../../../components/Errors/ResponseError';
import {ExternalLinkWithIcon} from '../../../components/ExternalLinkWithIcon/ExternalLinkWithIcon';
import {IconWrapper as Icon} from '../../../components/Icon/Icon';
import {ContentWithPopup} from '../../../components/ContentWithPopup/ContentWithPopup';

import type {IResponseError} from '../../../types/api/error';
import type {AdditionalClusterProps, ClusterLink} from '../../../types/additionalProps';
Expand All @@ -18,39 +19,115 @@ import type {TClusterInfo} from '../../../types/api/cluster';
import {backend, customBackend} from '../../../store';
import {formatStorageValues} from '../../../utils/dataFormatters/dataFormatters';
import {useSetting, useTypedSelector} from '../../../utils/hooks';
import {formatBytes, getSizeWithSignificantDigits} from '../../../utils/bytesParsers';
import {
CLUSTER_DEFAULT_TITLE,
CLUSTER_INFO_HIDDEN_KEY,
DEVELOPER_UI_TITLE,
} from '../../../utils/constants';
import type {
ClusterGroupsStats,
DiskErasureGroupsStats,
} from '../../../store/reducers/cluster/types';

import {VersionsBar} from '../VersionsBar/VersionsBar';
import {ClusterInfoSkeleton} from '../ClusterInfoSkeleton/ClusterInfoSkeleton';
import i18n from '../i18n';

import {compareTablets} from './utils';

import './ClusterInfo.scss';

const b = block('cluster-info');

interface GroupsStatsPopupContentProps {
stats: DiskErasureGroupsStats;
}

const GroupsStatsPopupContent = ({stats}: GroupsStatsPopupContentProps) => {
const {diskType, erasure, allocatedSize, availableSize} = stats;

const sizeToConvert = getSizeWithSignificantDigits(Math.max(allocatedSize, availableSize), 2);

const convertedAllocatedSize = formatBytes({value: allocatedSize, size: sizeToConvert});
const convertedAvailableSize = formatBytes({value: availableSize, size: sizeToConvert});

const usage = Math.round((allocatedSize / (allocatedSize + availableSize)) * 100);

const info = [
{
label: i18n('disk-type'),
value: diskType,
},
{
label: i18n('erasure'),
value: erasure,
},
{
label: i18n('allocated'),
value: convertedAllocatedSize,
},
{
label: i18n('available'),
value: convertedAvailableSize,
},
{
label: i18n('usage'),
value: usage + '%',
},
];

return (
<InfoViewer dots={true} info={info} className={b('groups-stats-popup-content')} size="s" />
);
};

const getGroupsStatsFields = (groupsStats: ClusterGroupsStats) => {
return Object.keys(groupsStats).map((diskType) => {
return {
label: i18n('storage-groups', {diskType}),
value: (
<div className={b('storage-groups-stats')}>
{Object.values(groupsStats[diskType]).map((erasureStats) => {
return (
<ContentWithPopup
placement={['right']}
key={erasureStats.erasure}
content={<GroupsStatsPopupContent stats={erasureStats} />}
>
<ProgressViewer
className={b('groups-stats-bar')}
value={erasureStats.createdGroups}
capacity={erasureStats.totalGroups}
/>
</ContentWithPopup>
);
})}
</div>
),
};
});
};

const getInfo = (
cluster: TClusterInfo,
versionsValues: VersionValue[],
groupsStats: ClusterGroupsStats,
additionalInfo: InfoViewerItem[],
links: ClusterLink[],
) => {
const info: InfoViewerItem[] = [];

if (cluster.DataCenters) {
info.push({
label: 'DC',
label: i18n('dc'),
value: <Tags tags={cluster.DataCenters} />,
});
}

if (cluster.SystemTablets) {
info.push({
label: 'Tablets',
label: i18n('tablets'),
value: (
<div className={b('system-tablets')}>
{cluster.SystemTablets.sort(compareTablets).map((tablet, tabletIndex) => (
Expand All @@ -63,46 +140,40 @@ const getInfo = (

if (cluster.Tenants) {
info.push({
label: 'Databases',
label: i18n('databases'),
value: cluster.Tenants,
});
}

info.push(
{
label: 'Nodes',
value: (
<ProgressViewer
className={b('metric-field')}
value={cluster?.NodesAlive}
capacity={cluster?.NodesTotal}
/>
),
label: i18n('nodes'),
value: <ProgressViewer value={cluster?.NodesAlive} capacity={cluster?.NodesTotal} />,
},
{
label: 'Load',
value: (
<ProgressViewer
className={b('metric-field')}
value={cluster?.LoadAverage}
capacity={cluster?.NumberOfCpus}
/>
),
label: i18n('load'),
value: <ProgressViewer value={cluster?.LoadAverage} capacity={cluster?.NumberOfCpus} />,
},
{
label: 'Storage',
label: i18n('storage-size'),
value: (
<ProgressViewer
className={b('metric-field')}
value={cluster?.StorageUsed}
capacity={cluster?.StorageTotal}
formatValues={formatStorageValues}
/>
),
},
);

if (Object.keys(groupsStats).length) {
info.push(...getGroupsStatsFields(groupsStats));
}

info.push(
...additionalInfo,
{
label: 'Links',
label: i18n('links'),
value: (
<div className={b('links')}>
{links.map(({title, url}) => (
Expand All @@ -112,7 +183,7 @@ const getInfo = (
),
},
{
label: 'Versions',
label: i18n('versions'),
value: <VersionsBar versionsValues={versionsValues} />,
},
);
Expand All @@ -123,6 +194,7 @@ const getInfo = (
interface ClusterInfoProps {
cluster?: TClusterInfo;
versionsValues?: VersionValue[];
groupsStats?: ClusterGroupsStats;
loading?: boolean;
error?: IResponseError;
additionalClusterProps?: AdditionalClusterProps;
Expand All @@ -131,6 +203,7 @@ interface ClusterInfoProps {
export const ClusterInfo = ({
cluster = {},
versionsValues = [],
groupsStats = {},
loading,
error,
additionalClusterProps = {},
Expand All @@ -151,7 +224,7 @@ export const ClusterInfo = ({

const {info = [], links = []} = additionalClusterProps;

const clusterInfo = getInfo(cluster, versionsValues, info, [
const clusterInfo = getInfo(cluster, versionsValues, groupsStats, info, [
{title: DEVELOPER_UI_TITLE, url: internalLink},
...links,
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface ClusterInfoSkeletonProps {
rows?: number;
}

export const ClusterInfoSkeleton = ({rows = 7, className}: ClusterInfoSkeletonProps) => (
export const ClusterInfoSkeleton = ({rows = 8, className}: ClusterInfoSkeletonProps) => (
<div className={b(null, className)}>
{[...new Array(rows)].map((_, index) => (
<div className={b('row')} key={`skeleton-row-${index}`}>
Expand Down
16 changes: 16 additions & 0 deletions src/containers/Cluster/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"disk-type": "Disk Type",
"erasure": "Erasure",
"allocated": "Allocated",
"available": "Available",
"usage": "Usage",
"dc": "DC",
"tablets": "Tablets",
"databases": "Databases",
"nodes": "Nodes",
"load": "Load",
"storage-size": "Storage size",
"storage-groups": "Storage groups, {{diskType}}",
"links": "Links",
"versions": "Versions"
}
11 changes: 11 additions & 0 deletions src/containers/Cluster/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {i18n, Lang} from '../../../utils/i18n';

import en from './en.json';
import ru from './ru.json';

const COMPONENT = 'ydb-cluster';

i18n.registerKeyset(Lang.En, COMPONENT, en);
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);

export default i18n.keyset(COMPONENT);
16 changes: 16 additions & 0 deletions src/containers/Cluster/i18n/ru.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"disk-type": "Тип диска",
"erasure": "Режим",
"allocated": "Использовано",
"available": "Доступно",
"usage": "Потребление",
"dc": "ДЦ",
"tablets": "Таблетки",
"databases": "Базы данных",
"nodes": "Узлы",
"load": "Нагрузка",
"storage-size": "Размер хранилища",
"storage-groups": "Группы хранения, {{diskType}}",
"links": "Ссылки",
"versions": "Версии"
}
Loading

0 comments on commit 79e5347

Please sign in to comment.