1
1
import cn from 'bem-cn-lite' ;
2
- import { isEmpty } from 'lodash/fp' ;
3
2
4
- import type { DescribeTopicResult } from '../../../../../types/api /topic' ;
3
+ import type { IPreparedTopicStats } from '../../../../../types/store /topic' ;
5
4
6
5
import { Loader } from '../../../../../components/Loader' ;
7
- import { InfoViewerItem , formatObject , InfoViewer } from '../../../../../components/InfoViewer' ;
8
-
9
- import { formatTopicStats } from '../../../../../components/InfoViewer/formatters' ;
6
+ import { InfoViewerItem , InfoViewer } from '../../../../../components/InfoViewer' ;
7
+ import { SpeedMultiMeter } from '../../../../../components/SpeedMultiMeter' ;
8
+ import { LabelWithPopover } from '../../../../../components/LabelWithPopover' ;
9
+ import { LagPopoverContent } from '../../../../../components/LagPopoverContent' ;
10
+ import { ResponseError } from '../../../../../components/Errors/ResponseError' ;
10
11
11
12
import { useTypedSelector } from '../../../../../utils/hooks' ;
12
- import { convertBytesObjectToSpeed } from '../../../../../utils/bytesParsers' ;
13
- import { formatBps } from '../../../../../utils' ;
13
+ import { formatDurationToShortTimeFormat } from '../../../../../utils/timeParsers' ;
14
+ import { formatBps , formatBytes } from '../../../../../utils' ;
15
+
16
+ import { selectPreparedTopicStats } from '../../../../../store/reducers/topic' ;
14
17
15
18
import i18n from './i18n' ;
16
19
17
20
import './TopicStats.scss' ;
18
21
19
22
const b = cn ( 'ydb-overview-topic-stats' ) ;
20
23
21
- const prepareTopicInfo = ( data : DescribeTopicResult ) : Array < InfoViewerItem > => {
24
+ const prepareTopicInfo = ( data : IPreparedTopicStats ) : Array < InfoViewerItem > => {
22
25
return [
23
- ...formatObject ( formatTopicStats , {
24
- ...data . topic_stats ,
25
- } ) ,
26
+ { label : 'Store size' , value : formatBytes ( data . storeSize ) } ,
27
+ {
28
+ label : (
29
+ < LabelWithPopover
30
+ text = { 'Write idle time' }
31
+ popoverContent = {
32
+ < LagPopoverContent text = { i18n ( 'writeIdleTimePopover' ) } type = "write" />
33
+ }
34
+ />
35
+ ) ,
36
+ value : formatDurationToShortTimeFormat ( data . partitionsIdleTime ) ,
37
+ } ,
38
+ {
39
+ label : (
40
+ < LabelWithPopover
41
+ text = { 'Write lag' }
42
+ popoverContent = {
43
+ < LagPopoverContent text = { i18n ( 'writeLagPopover' ) } type = "write" />
44
+ }
45
+ />
46
+ ) ,
47
+ value : formatDurationToShortTimeFormat ( data . partitionsWriteLag ) ,
48
+ } ,
49
+ {
50
+ label : 'Average write speed' ,
51
+ value : < SpeedMultiMeter data = { data . writeSpeed } withValue = { false } /> ,
52
+ } ,
26
53
] ;
27
54
} ;
28
55
29
- const prepareBytesWrittenInfo = ( data : DescribeTopicResult ) : Array < InfoViewerItem > => {
30
- const preparedBytes = convertBytesObjectToSpeed ( data ?. topic_stats ?. bytes_written ) ;
56
+ const prepareBytesWrittenInfo = ( data : IPreparedTopicStats ) : Array < InfoViewerItem > => {
57
+ const writeSpeed = data . writeSpeed ;
31
58
32
59
return [
33
60
{
34
61
label : 'per minute' ,
35
- value : formatBps ( preparedBytes . perMinute ) ,
62
+ value : formatBps ( writeSpeed . perMinute ) ,
36
63
} ,
37
64
{
38
65
label : 'per hour' ,
39
- value : formatBps ( preparedBytes . perHour ) ,
66
+ value : formatBps ( writeSpeed . perHour ) ,
40
67
} ,
41
68
{
42
69
label : 'per day' ,
43
- value : formatBps ( preparedBytes . perDay ) ,
70
+ value : formatBps ( writeSpeed . perDay ) ,
44
71
} ,
45
72
] ;
46
73
} ;
47
74
48
75
export const TopicStats = ( ) => {
49
- const { data, error, loading, wasLoaded} = useTypedSelector ( ( state ) => state . topic ) ;
76
+ const { error, loading, wasLoaded} = useTypedSelector ( ( state ) => state . topic ) ;
77
+
78
+ const data = useTypedSelector ( selectPreparedTopicStats ) ;
50
79
51
80
if ( loading && ! wasLoaded ) {
52
81
return (
@@ -56,24 +85,14 @@ export const TopicStats = () => {
56
85
) ;
57
86
}
58
87
59
- // There are several backed versions with different behaviour
60
- // Possible returns on older versions:
61
- // 1. Error when trying to access endpoint
62
- // 2. No data
63
- // 3. HTML page of Internal Viewer with an error
64
- // 4. Data with no topic stats
65
- // 5. Topic Stats as an empty object
66
- if (
67
- error ||
68
- ! data ||
69
- typeof data !== 'object' ||
70
- ! data . topic_stats ||
71
- isEmpty ( data . topic_stats )
72
- ) {
88
+ // If there is at least some empty data object
89
+ // we initialize its fields with zero values
90
+ // so no data at all is considered to be error as well
91
+ if ( error || ! data ) {
73
92
return (
74
93
< div className = { b ( ) } >
75
94
< div className = { b ( 'title' ) } > Stats</ div >
76
- < div className = " error" > { i18n ( 'notSupportedVersion' ) } </ div >
95
+ < ResponseError error = { error } / >
77
96
</ div >
78
97
) ;
79
98
}
0 commit comments