-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathTopicStats.tsx
More file actions
122 lines (110 loc) · 4.27 KB
/
Copy pathTopicStats.tsx
File metadata and controls
122 lines (110 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import React from 'react';
import {ResponseError} from '../../../../../components/Errors/ResponseError';
import type {InfoViewerItem} from '../../../../../components/InfoViewer';
import {InfoViewer} from '../../../../../components/InfoViewer';
import {LabelWithPopover} from '../../../../../components/LabelWithPopover';
import {LagPopoverContent} from '../../../../../components/LagPopoverContent';
import {Loader} from '../../../../../components/Loader';
import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
import {useClusterWithProxy} from '../../../../../store/reducers/cluster/cluster';
import {selectPreparedTopicStats, topicApi} from '../../../../../store/reducers/topic/topic';
import type {IPreparedTopicStats} from '../../../../../types/store/topic';
import {cn} from '../../../../../utils/cn';
import {formatBps, formatBytes} from '../../../../../utils/dataFormatters/dataFormatters';
import {useAutoRefreshInterval, useTypedSelector} from '../../../../../utils/hooks';
import {formatDurationToShortTimeFormat} from '../../../../../utils/timeParsers';
import i18n from './i18n';
import './TopicStats.scss';
const b = cn('ydb-overview-topic-stats');
const prepareTopicInfo = (data: IPreparedTopicStats): Array<InfoViewerItem> => {
return [
{label: 'Store size', value: formatBytes(data.storeSize)},
{
label: (
<LabelWithPopover
text={'Write idle time'}
popoverContent={
<LagPopoverContent text={i18n('writeIdleTimePopover')} type="write" />
}
/>
),
value: formatDurationToShortTimeFormat(data.partitionsIdleTime),
},
{
label: (
<LabelWithPopover
text={'Write lag'}
popoverContent={
<LagPopoverContent text={i18n('writeLagPopover')} type="write" />
}
/>
),
value: formatDurationToShortTimeFormat(data.partitionsWriteLag),
},
{
label: 'Average write speed',
value: <SpeedMultiMeter data={data.writeSpeed} withValue={false} />,
},
];
};
const prepareBytesWrittenInfo = (data: IPreparedTopicStats): Array<InfoViewerItem> => {
const writeSpeed = data.writeSpeed;
return [
{
label: 'per minute',
value: formatBps(writeSpeed.perMinute),
},
{
label: 'per hour',
value: formatBps(writeSpeed.perHour),
},
{
label: 'per day',
value: formatBps(writeSpeed.perDay),
},
];
};
interface TopicStatsProps {
path: string;
database: string;
databaseFullPath: string;
}
export const TopicStats = ({path, database, databaseFullPath}: TopicStatsProps) => {
const useMetaProxy = useClusterWithProxy();
const [autoRefreshInterval] = useAutoRefreshInterval();
const {currentData, isFetching, error} = topicApi.useGetTopicQuery(
{path, database, databaseFullPath, useMetaProxy},
{pollingInterval: autoRefreshInterval},
);
const loading = isFetching && currentData === undefined;
const data = useTypedSelector((state) =>
selectPreparedTopicStats(state, path, database, databaseFullPath, useMetaProxy),
);
if (loading) {
return (
<div className={b()}>
<Loader size="s" />
</div>
);
}
// If there is at least some empty data object
// we initialize its fields with zero values
// so no data at all is considered to be error as well
const errorContent = error || !data ? <ResponseError error={error} /> : null;
return (
<div className={b()}>
<div className={b('title')}>Stats</div>
{errorContent}
{data ? (
<React.Fragment>
<div className={b('info')}>
<InfoViewer info={prepareTopicInfo(data)} multilineLabels />
</div>
<div className={b('bytes-written')}>
<InfoViewer info={prepareBytesWrittenInfo(data)} />
</div>
</React.Fragment>
) : null}
</div>
);
};