ydb-embedded-ui 3.3.3 → 3.4.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 +28 -0
- package/dist/components/Errors/ResponseError/ResponseError.tsx +2 -2
- package/dist/components/InfoViewer/formatters/topicStats.tsx +8 -29
- package/dist/components/LabelWithPopover/LabelWithPopover.tsx +20 -0
- package/dist/components/LabelWithPopover/index.ts +1 -0
- package/dist/components/LagImages/LagImages.tsx +205 -0
- package/dist/components/LagImages/index.ts +1 -0
- package/dist/components/SpeedMultiMeter/SpeedMultiMeter.scss +92 -0
- package/dist/components/SpeedMultiMeter/SpeedMultiMeter.tsx +120 -0
- package/dist/components/SpeedMultiMeter/i18n/en.json +6 -0
- package/dist/components/SpeedMultiMeter/i18n/index.ts +13 -0
- package/dist/components/SpeedMultiMeter/i18n/ru.json +6 -0
- package/dist/components/SpeedMultiMeter/index.ts +1 -0
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +26 -14
- package/dist/containers/Storage/VDisk/VDisk.tsx +20 -5
- package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +34 -5
- package/dist/containers/Storage/utils/types.ts +5 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.scss +32 -3
- package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.tsx +62 -69
- package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.scss +13 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.tsx +27 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/Headers/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/ConsumersTopicStats.scss +32 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/ConsumersTopicStats.tsx +43 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/Columns.scss +5 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +66 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/i18n/en.json +4 -3
- package/dist/containers/Tenant/Diagnostics/Consumers/i18n/ru.json +4 -3
- package/dist/containers/Tenant/Diagnostics/Consumers/utils/constants.ts +23 -0
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +7 -3
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +15 -9
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.scss +9 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +6 -8
- package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.scss +33 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.tsx +76 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/Headers/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.scss +45 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +254 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsWrapper.tsx +79 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/Columns.scss +13 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx +246 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/i18n/en.json +13 -0
- package/dist/containers/Tenant/Diagnostics/{OverloadedShards → Partitions}/i18n/index.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/i18n/ru.json +13 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/utils/constants.ts +74 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/utils/types.ts +6 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.scss +8 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.tsx +56 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/Filters/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/{OverloadedShards/OverloadedShards.scss → TopShards/TopShards.scss} +2 -10
- package/dist/containers/Tenant/Diagnostics/{OverloadedShards/OverloadedShards.tsx → TopShards/TopShards.tsx} +61 -31
- package/dist/containers/Tenant/Diagnostics/TopShards/i18n/en.json +6 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/i18n/ru.json +6 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/index.ts +1 -0
- package/dist/containers/Tenant/utils/schema.ts +1 -16
- package/dist/services/api.d.ts +4 -0
- package/dist/services/api.js +22 -6
- package/dist/store/reducers/authentication.js +0 -15
- package/dist/store/reducers/consumer.ts +160 -0
- package/dist/store/reducers/index.ts +2 -0
- package/dist/store/reducers/settings.js +2 -0
- package/dist/store/reducers/shardsWorkload.ts +28 -2
- package/dist/store/reducers/topic.ts +82 -2
- package/dist/store/state-url-mapping.js +3 -0
- package/dist/types/store/consumer.ts +55 -0
- package/dist/types/store/shardsWorkload.ts +6 -0
- package/dist/types/store/topic.ts +23 -6
- package/dist/utils/bytesParsers/convertBytesObjectToSpeed.ts +24 -0
- package/dist/utils/bytesParsers/formatBytesCustom.ts +57 -0
- package/dist/utils/bytesParsers/i18n/en.json +7 -0
- package/dist/utils/bytesParsers/i18n/index.ts +11 -0
- package/dist/utils/bytesParsers/i18n/ru.json +7 -0
- package/dist/utils/bytesParsers/index.ts +2 -0
- package/dist/utils/constants.ts +3 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/storage.ts +2 -2
- package/dist/utils/timeParsers/index.ts +2 -1
- package/dist/utils/timeParsers/parsers.ts +18 -0
- package/dist/utils/timeParsers/{protobuf.ts → protobufParsers.ts} +0 -0
- package/dist/utils/typecheckers.ts +5 -0
- package/dist/utils/utils.js +3 -3
- package/package.json +2 -2
- package/dist/containers/Tenant/Diagnostics/OverloadedShards/i18n/en.json +0 -4
- package/dist/containers/Tenant/Diagnostics/OverloadedShards/i18n/ru.json +0 -4
- package/dist/containers/Tenant/Diagnostics/OverloadedShards/index.ts +0 -1
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import DataTable, {Column} from '@gravity-ui/react-data-table';
|
|
2
|
+
import block from 'bem-cn-lite';
|
|
3
|
+
|
|
4
|
+
import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
|
|
5
|
+
import EntityStatus from '../../../../../components/EntityStatus/EntityStatus';
|
|
6
|
+
import {getDefaultNodePath} from '../../../../Node/NodePages';
|
|
7
|
+
import {formatBytes, formatMsToUptime} from '../../../../../utils';
|
|
8
|
+
import {isNumeric} from '../../../../../utils/utils';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
PARTITIONS_COLUMNS_IDS,
|
|
12
|
+
PARTITIONS_COLUMNS_TITILES,
|
|
13
|
+
PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS,
|
|
14
|
+
PARTITIONS_READ_LAGS_SUB_COLUMNS_TITLES,
|
|
15
|
+
PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS,
|
|
16
|
+
PARTITIONS_WRITE_LAGS_SUB_COLUMNS_TITLES,
|
|
17
|
+
} from '../utils/constants';
|
|
18
|
+
import type {IPreparedPartitionDataWithHosts} from '../utils/types';
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
MultilineHeader,
|
|
22
|
+
ReadLagsHeader,
|
|
23
|
+
ReadSessionHeader,
|
|
24
|
+
UncommitedMessagesHeader,
|
|
25
|
+
UnreadMessagesHeader,
|
|
26
|
+
WriteLagsHeader,
|
|
27
|
+
} from '../Headers';
|
|
28
|
+
|
|
29
|
+
import './Columns.scss';
|
|
30
|
+
|
|
31
|
+
const b = block('ydb-diagnostics-partitions-columns');
|
|
32
|
+
|
|
33
|
+
export const columns: Column<IPreparedPartitionDataWithHosts>[] = [
|
|
34
|
+
{
|
|
35
|
+
name: PARTITIONS_COLUMNS_IDS.PARTITION_ID,
|
|
36
|
+
header: (
|
|
37
|
+
<MultilineHeader
|
|
38
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.PARTITION_ID]}
|
|
39
|
+
/>
|
|
40
|
+
),
|
|
41
|
+
sortAccessor: (row) => isNumeric(row.partitionId) && Number(row.partitionId),
|
|
42
|
+
align: DataTable.LEFT,
|
|
43
|
+
render: ({row}) => row.partitionId,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: PARTITIONS_COLUMNS_IDS.STORE_SIZE,
|
|
47
|
+
header: (
|
|
48
|
+
<MultilineHeader
|
|
49
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.STORE_SIZE]}
|
|
50
|
+
/>
|
|
51
|
+
),
|
|
52
|
+
align: DataTable.RIGHT,
|
|
53
|
+
render: ({row}) => formatBytes(row.storeSize),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: PARTITIONS_COLUMNS_IDS.WRITE_SPEED,
|
|
57
|
+
header: PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.WRITE_SPEED],
|
|
58
|
+
align: DataTable.LEFT,
|
|
59
|
+
sortAccessor: (row) => row.writeSpeed.perMinute,
|
|
60
|
+
render: ({row}) => <SpeedMultiMeter data={row.writeSpeed} />,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: PARTITIONS_COLUMNS_IDS.READ_SPEED,
|
|
64
|
+
header: PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.READ_SPEED],
|
|
65
|
+
align: DataTable.LEFT,
|
|
66
|
+
sortAccessor: (row) => row.readSpeed.perMinute,
|
|
67
|
+
render: ({row}) => <SpeedMultiMeter data={row.readSpeed} />,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: PARTITIONS_COLUMNS_IDS.WRITE_LAGS,
|
|
71
|
+
header: <WriteLagsHeader />,
|
|
72
|
+
className: b('lags-header'),
|
|
73
|
+
sub: [
|
|
74
|
+
{
|
|
75
|
+
name: PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS.PARTITION_WRITE_LAG,
|
|
76
|
+
header: PARTITIONS_WRITE_LAGS_SUB_COLUMNS_TITLES[
|
|
77
|
+
PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS.PARTITION_WRITE_LAG
|
|
78
|
+
],
|
|
79
|
+
align: DataTable.RIGHT,
|
|
80
|
+
render: ({row}) => formatMsToUptime(row.partitionWriteLag),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS.PARTITION_WRITE_IDLE_TIME,
|
|
84
|
+
header: PARTITIONS_WRITE_LAGS_SUB_COLUMNS_TITLES[
|
|
85
|
+
PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS.PARTITION_WRITE_IDLE_TIME
|
|
86
|
+
],
|
|
87
|
+
align: DataTable.RIGHT,
|
|
88
|
+
render: ({row}) => formatMsToUptime(row.partitionWriteIdleTime),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: PARTITIONS_COLUMNS_IDS.READ_LAGS,
|
|
94
|
+
header: <ReadLagsHeader />,
|
|
95
|
+
className: b('lags-header'),
|
|
96
|
+
sub: [
|
|
97
|
+
{
|
|
98
|
+
name: PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_WRITE_LAG,
|
|
99
|
+
header: PARTITIONS_READ_LAGS_SUB_COLUMNS_TITLES[
|
|
100
|
+
PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_WRITE_LAG
|
|
101
|
+
],
|
|
102
|
+
align: DataTable.RIGHT,
|
|
103
|
+
render: ({row}) => formatMsToUptime(row.consumerWriteLag),
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_READ_LAG,
|
|
107
|
+
header: PARTITIONS_READ_LAGS_SUB_COLUMNS_TITLES[
|
|
108
|
+
PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_READ_LAG
|
|
109
|
+
],
|
|
110
|
+
align: DataTable.RIGHT,
|
|
111
|
+
render: ({row}) => formatMsToUptime(row.consumerReadLag),
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_READ_IDLE_TIME,
|
|
115
|
+
header: PARTITIONS_READ_LAGS_SUB_COLUMNS_TITLES[
|
|
116
|
+
PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_READ_IDLE_TIME
|
|
117
|
+
],
|
|
118
|
+
align: DataTable.RIGHT,
|
|
119
|
+
render: ({row}) => formatMsToUptime(row.consumerReadIdleTime),
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: PARTITIONS_COLUMNS_IDS.UNCOMMITED_MESSAGES,
|
|
125
|
+
header: <UncommitedMessagesHeader />,
|
|
126
|
+
align: DataTable.RIGHT,
|
|
127
|
+
render: ({row}) => row.uncommitedMessages,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: PARTITIONS_COLUMNS_IDS.UNREAD_MESSAGES,
|
|
131
|
+
header: <UnreadMessagesHeader />,
|
|
132
|
+
align: DataTable.RIGHT,
|
|
133
|
+
render: ({row}) => row.unreadMessages,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: PARTITIONS_COLUMNS_IDS.START_OFFSET,
|
|
137
|
+
header: (
|
|
138
|
+
<MultilineHeader
|
|
139
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.START_OFFSET]}
|
|
140
|
+
/>
|
|
141
|
+
),
|
|
142
|
+
sortAccessor: (row) => isNumeric(row.startOffset) && Number(row.startOffset),
|
|
143
|
+
align: DataTable.RIGHT,
|
|
144
|
+
render: ({row}) => row.startOffset,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: PARTITIONS_COLUMNS_IDS.END_OFFSET,
|
|
148
|
+
header: (
|
|
149
|
+
<MultilineHeader
|
|
150
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.END_OFFSET]}
|
|
151
|
+
/>
|
|
152
|
+
),
|
|
153
|
+
sortAccessor: (row) => isNumeric(row.endOffset) && Number(row.endOffset),
|
|
154
|
+
align: DataTable.RIGHT,
|
|
155
|
+
render: ({row}) => row.endOffset,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: PARTITIONS_COLUMNS_IDS.COMMITED_OFFSET,
|
|
159
|
+
header: (
|
|
160
|
+
<MultilineHeader
|
|
161
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.COMMITED_OFFSET]}
|
|
162
|
+
/>
|
|
163
|
+
),
|
|
164
|
+
sortAccessor: (row) => isNumeric(row.commitedOffset) && Number(row.commitedOffset),
|
|
165
|
+
align: DataTable.RIGHT,
|
|
166
|
+
render: ({row}) => row.commitedOffset,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: PARTITIONS_COLUMNS_IDS.READ_SESSION_ID,
|
|
170
|
+
header: <ReadSessionHeader />,
|
|
171
|
+
align: DataTable.LEFT,
|
|
172
|
+
render: ({row}) =>
|
|
173
|
+
row.readSessionId ? (
|
|
174
|
+
<EntityStatus
|
|
175
|
+
name={row.readSessionId}
|
|
176
|
+
showStatus={false}
|
|
177
|
+
hasClipboardButton
|
|
178
|
+
className={b('string-with-copy')}
|
|
179
|
+
/>
|
|
180
|
+
) : (
|
|
181
|
+
'–'
|
|
182
|
+
),
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: PARTITIONS_COLUMNS_IDS.READER_NAME,
|
|
186
|
+
header: (
|
|
187
|
+
<MultilineHeader
|
|
188
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.READER_NAME]}
|
|
189
|
+
/>
|
|
190
|
+
),
|
|
191
|
+
align: DataTable.LEFT,
|
|
192
|
+
render: ({row}) =>
|
|
193
|
+
row.readerName ? (
|
|
194
|
+
<EntityStatus
|
|
195
|
+
name={row.readerName}
|
|
196
|
+
showStatus={false}
|
|
197
|
+
hasClipboardButton
|
|
198
|
+
className={b('string-with-copy')}
|
|
199
|
+
/>
|
|
200
|
+
) : (
|
|
201
|
+
'–'
|
|
202
|
+
),
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: PARTITIONS_COLUMNS_IDS.PARTITION_HOST,
|
|
206
|
+
header: (
|
|
207
|
+
<MultilineHeader
|
|
208
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.PARTITION_HOST]}
|
|
209
|
+
/>
|
|
210
|
+
),
|
|
211
|
+
align: DataTable.LEFT,
|
|
212
|
+
render: ({row}) =>
|
|
213
|
+
row.partitionHost ? (
|
|
214
|
+
<EntityStatus
|
|
215
|
+
name={row.partitionHost}
|
|
216
|
+
path={getDefaultNodePath(row.partitionHost)}
|
|
217
|
+
showStatus={false}
|
|
218
|
+
hasClipboardButton
|
|
219
|
+
className={b('string-with-copy')}
|
|
220
|
+
/>
|
|
221
|
+
) : (
|
|
222
|
+
'–'
|
|
223
|
+
),
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: PARTITIONS_COLUMNS_IDS.CONNECTION_HOST,
|
|
227
|
+
header: (
|
|
228
|
+
<MultilineHeader
|
|
229
|
+
title={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.CONNECTION_HOST]}
|
|
230
|
+
/>
|
|
231
|
+
),
|
|
232
|
+
align: DataTable.LEFT,
|
|
233
|
+
render: ({row}) =>
|
|
234
|
+
row.connectionHost ? (
|
|
235
|
+
<EntityStatus
|
|
236
|
+
name={row.connectionHost}
|
|
237
|
+
path={getDefaultNodePath(row.connectionNodeId)}
|
|
238
|
+
showStatus={false}
|
|
239
|
+
hasClipboardButton
|
|
240
|
+
className={b('string-with-copy')}
|
|
241
|
+
/>
|
|
242
|
+
) : (
|
|
243
|
+
'–'
|
|
244
|
+
),
|
|
245
|
+
},
|
|
246
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './columns';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lagsPopover.writeLags": "Write lags statistics (time format dd hh:mm:ss)",
|
|
3
|
+
"lagsPopover.readLags": "Read lags statistics (time format dd hh:mm:ss)",
|
|
4
|
+
"headers.unread": "End offset - Last read offset",
|
|
5
|
+
"headers.uncommited": "End offset - Committed offset",
|
|
6
|
+
"controls.consumerSelector": "Consumer:",
|
|
7
|
+
"controls.consumerSelector.placeholder": "Consumer",
|
|
8
|
+
"controls.partitionSearch": "Partition ID",
|
|
9
|
+
"controls.generalSearch": "Host, Host ID, Reader, Read Session ID",
|
|
10
|
+
"table.emptyDataMessage": "No partitions match the current search",
|
|
11
|
+
"noConsumersMessage.topic": "This topic has no consumers",
|
|
12
|
+
"noConsumersMessage.stream": "This changefeed has no consumers"
|
|
13
|
+
}
|
|
@@ -3,7 +3,7 @@ import {i18n, Lang} from '../../../../../utils/i18n';
|
|
|
3
3
|
import en from './en.json';
|
|
4
4
|
import ru from './ru.json';
|
|
5
5
|
|
|
6
|
-
const COMPONENT = 'ydb-diagnostics-
|
|
6
|
+
const COMPONENT = 'ydb-diagnostics-partitions';
|
|
7
7
|
|
|
8
8
|
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
|
9
9
|
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lagsPopover.writeLags": "Статистика лагов записи (формат времени дд чч:мм:сс)",
|
|
3
|
+
"lagsPopover.readLags": "Статистика лагов чтения (формат времени дд чч:мм:сс)",
|
|
4
|
+
"headers.unread": "End offset - Last read offset",
|
|
5
|
+
"headers.uncommited": "End offset - Committed offset",
|
|
6
|
+
"controls.consumerSelector": "Читатель:",
|
|
7
|
+
"controls.consumerSelector.placeholder": "Читатель",
|
|
8
|
+
"controls.partitionSearch": "Partition ID",
|
|
9
|
+
"controls.generalSearch": "Host, Host ID, Reader, Read Session ID",
|
|
10
|
+
"table.emptyDataMessage": "По заданному поиску нет партиций",
|
|
11
|
+
"noConsumersMessage.topic": "У этого топика нет читателей",
|
|
12
|
+
"noConsumersMessage.stream": "У этого стрима нет читателей"
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PartitionsWrapper';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export const PARTITIONS_COLUMNS_IDS = {
|
|
2
|
+
PARTITION_ID: 'partitionId',
|
|
3
|
+
|
|
4
|
+
STORE_SIZE: 'storeSize',
|
|
5
|
+
|
|
6
|
+
WRITE_SPEED: 'writeSpeed',
|
|
7
|
+
READ_SPEED: 'readSpeed',
|
|
8
|
+
|
|
9
|
+
WRITE_LAGS: 'writeLags',
|
|
10
|
+
READ_LAGS: 'readLags',
|
|
11
|
+
|
|
12
|
+
UNCOMMITED_MESSAGES: 'uncommitedMessages',
|
|
13
|
+
UNREAD_MESSAGES: 'unreadMessages',
|
|
14
|
+
|
|
15
|
+
START_OFFSET: 'startOffset',
|
|
16
|
+
END_OFFSET: 'endOffset',
|
|
17
|
+
COMMITED_OFFSET: 'commitedOffset',
|
|
18
|
+
|
|
19
|
+
READ_SESSION_ID: 'readSessionId',
|
|
20
|
+
READER_NAME: 'readerName',
|
|
21
|
+
|
|
22
|
+
PARTITION_HOST: 'partitionHost',
|
|
23
|
+
CONNECTION_HOST: 'connectionHost',
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
export const PARTITIONS_COLUMNS_TITILES = {
|
|
27
|
+
[PARTITIONS_COLUMNS_IDS.PARTITION_ID]: 'Partition ID',
|
|
28
|
+
|
|
29
|
+
[PARTITIONS_COLUMNS_IDS.STORE_SIZE]: 'Store size',
|
|
30
|
+
|
|
31
|
+
[PARTITIONS_COLUMNS_IDS.WRITE_SPEED]: 'Write speed',
|
|
32
|
+
[PARTITIONS_COLUMNS_IDS.READ_SPEED]: 'Read speed',
|
|
33
|
+
|
|
34
|
+
[PARTITIONS_COLUMNS_IDS.WRITE_LAGS]: 'Write lags, duration',
|
|
35
|
+
|
|
36
|
+
[PARTITIONS_COLUMNS_IDS.READ_LAGS]: 'Read lags, duration',
|
|
37
|
+
|
|
38
|
+
[PARTITIONS_COLUMNS_IDS.UNCOMMITED_MESSAGES]: 'Uncommited messages',
|
|
39
|
+
[PARTITIONS_COLUMNS_IDS.UNREAD_MESSAGES]: 'Unread messages',
|
|
40
|
+
|
|
41
|
+
[PARTITIONS_COLUMNS_IDS.START_OFFSET]: 'Start offset',
|
|
42
|
+
[PARTITIONS_COLUMNS_IDS.END_OFFSET]: 'End offset',
|
|
43
|
+
[PARTITIONS_COLUMNS_IDS.COMMITED_OFFSET]: 'Commited offset',
|
|
44
|
+
|
|
45
|
+
[PARTITIONS_COLUMNS_IDS.READ_SESSION_ID]: 'Read session ID',
|
|
46
|
+
[PARTITIONS_COLUMNS_IDS.READER_NAME]: 'Reader name',
|
|
47
|
+
|
|
48
|
+
[PARTITIONS_COLUMNS_IDS.PARTITION_HOST]: 'Partition host',
|
|
49
|
+
[PARTITIONS_COLUMNS_IDS.CONNECTION_HOST]: 'Connection host',
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
export const PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS = {
|
|
53
|
+
PARTITION_WRITE_LAG: 'partitionWriteLag',
|
|
54
|
+
PARTITION_WRITE_IDLE_TIME: 'partitionWriteIdleTime',
|
|
55
|
+
} as const;
|
|
56
|
+
|
|
57
|
+
export const PARTITIONS_WRITE_LAGS_SUB_COLUMNS_TITLES = {
|
|
58
|
+
[PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS.PARTITION_WRITE_LAG]: 'write lag',
|
|
59
|
+
[PARTITIONS_WRITE_LAGS_SUB_COLUMNS_IDS.PARTITION_WRITE_IDLE_TIME]: 'write idle time',
|
|
60
|
+
} as const;
|
|
61
|
+
|
|
62
|
+
export const PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS = {
|
|
63
|
+
CONSUMER_WRITE_LAG: 'consumerWriteLag',
|
|
64
|
+
CONSUMER_READ_LAG: 'consumerReadLag',
|
|
65
|
+
CONSUMER_READ_IDLE_TIME: 'consumerReadIdleTime',
|
|
66
|
+
} as const;
|
|
67
|
+
|
|
68
|
+
export const PARTITIONS_READ_LAGS_SUB_COLUMNS_TITLES = {
|
|
69
|
+
[PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_WRITE_LAG]: 'write lag',
|
|
70
|
+
[PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_READ_LAG]: 'read lag',
|
|
71
|
+
[PARTITIONS_READ_LAGS_SUB_COLUMNS_IDS.CONSUMER_READ_IDLE_TIME]: 'read idle time',
|
|
72
|
+
} as const;
|
|
73
|
+
|
|
74
|
+
export const PARTITIONS_DEFAULT_SELECTED_COLUMNS = Object.values(PARTITIONS_COLUMNS_IDS);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {RadioButton} from '@gravity-ui/uikit';
|
|
2
|
+
|
|
3
|
+
import {DateRange, DateRangeValues} from '../../../../../components/DateRange';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
EShardsWorkloadMode,
|
|
7
|
+
IShardsWorkloadFilters,
|
|
8
|
+
} from '../../../../../types/store/shardsWorkload';
|
|
9
|
+
|
|
10
|
+
import {isEnumMember} from '../../../../../utils/typecheckers';
|
|
11
|
+
|
|
12
|
+
import i18n from '../i18n';
|
|
13
|
+
import {b} from '../TopShards';
|
|
14
|
+
|
|
15
|
+
import './Filters.scss';
|
|
16
|
+
|
|
17
|
+
interface FiltersProps {
|
|
18
|
+
value: IShardsWorkloadFilters;
|
|
19
|
+
onChange: (value: Partial<IShardsWorkloadFilters>) => void;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const Filters = ({value, onChange, className}: FiltersProps) => {
|
|
24
|
+
const handleModeChange = (mode: string) => {
|
|
25
|
+
if (!isEnumMember(EShardsWorkloadMode, mode)) {
|
|
26
|
+
const values = Object.values(EShardsWorkloadMode).join(', ');
|
|
27
|
+
throw new Error(`Unexpected TopShards mode "${mode}". Should be one of: ${values}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onChange({mode});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleDateRangeChange = (dateRange: DateRangeValues) => {
|
|
34
|
+
onChange({
|
|
35
|
+
mode: EShardsWorkloadMode.History,
|
|
36
|
+
...dateRange,
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const from = value.mode === EShardsWorkloadMode.Immediate ? undefined : value.from;
|
|
41
|
+
const to = value.mode === EShardsWorkloadMode.Immediate ? undefined : value.to;
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className={b('filters', className)}>
|
|
45
|
+
<RadioButton value={value.mode} onUpdate={handleModeChange}>
|
|
46
|
+
<RadioButton.Option value={EShardsWorkloadMode.Immediate}>
|
|
47
|
+
{i18n('filters.mode.immediate')}
|
|
48
|
+
</RadioButton.Option>
|
|
49
|
+
<RadioButton.Option value={EShardsWorkloadMode.History}>
|
|
50
|
+
{i18n('filters.mode.history')}
|
|
51
|
+
</RadioButton.Option>
|
|
52
|
+
</RadioButton>
|
|
53
|
+
<DateRange from={from} to={to} onChange={handleDateRangeChange} />
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Filters';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
.
|
|
1
|
+
.top-shards {
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
|
+
gap: 10px;
|
|
4
5
|
|
|
5
6
|
height: 100%;
|
|
6
7
|
|
|
@@ -11,15 +12,6 @@
|
|
|
11
12
|
justify-content: center;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
&__controls {
|
|
15
|
-
display: flex;
|
|
16
|
-
flex-wrap: wrap;
|
|
17
|
-
align-items: baseline;
|
|
18
|
-
gap: 16px;
|
|
19
|
-
|
|
20
|
-
margin-bottom: 10px;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
15
|
&__table {
|
|
24
16
|
overflow: auto;
|
|
25
17
|
flex-grow: 1;
|
|
@@ -5,7 +5,6 @@ import cn from 'bem-cn-lite';
|
|
|
5
5
|
import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
|
|
6
6
|
import {Loader} from '@gravity-ui/uikit';
|
|
7
7
|
|
|
8
|
-
import {DateRange, DateRangeValues} from '../../../../components/DateRange';
|
|
9
8
|
import {InternalLink} from '../../../../components/InternalLink';
|
|
10
9
|
|
|
11
10
|
import HistoryContext from '../../../../contexts/HistoryContext';
|
|
@@ -18,7 +17,7 @@ import {
|
|
|
18
17
|
setShardsQueryFilters,
|
|
19
18
|
} from '../../../../store/reducers/shardsWorkload';
|
|
20
19
|
import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema';
|
|
21
|
-
import
|
|
20
|
+
import {EShardsWorkloadMode, IShardsWorkloadFilters} from '../../../../types/store/shardsWorkload';
|
|
22
21
|
|
|
23
22
|
import type {EPathType} from '../../../../types/api/schema';
|
|
24
23
|
|
|
@@ -31,10 +30,12 @@ import {getDefaultNodePath} from '../../../Node/NodePages';
|
|
|
31
30
|
|
|
32
31
|
import {isColumnEntityType} from '../../utils/schema';
|
|
33
32
|
|
|
33
|
+
import {Filters} from './Filters';
|
|
34
|
+
|
|
34
35
|
import i18n from './i18n';
|
|
35
|
-
import './
|
|
36
|
+
import './TopShards.scss';
|
|
36
37
|
|
|
37
|
-
const b = cn('
|
|
38
|
+
export const b = cn('top-shards');
|
|
38
39
|
const bLink = cn('yc-link');
|
|
39
40
|
|
|
40
41
|
const TABLE_SETTINGS: Settings = {
|
|
@@ -83,12 +84,18 @@ function dataTableToStringSortOrder(value: SortOrder | SortOrder[] = []) {
|
|
|
83
84
|
return sortOrders.map(({columnId}) => columnId).join(',');
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
function fillDateRangeFor(value: IShardsWorkloadFilters) {
|
|
88
|
+
value.to = Date.now();
|
|
89
|
+
value.from = value.to - HOUR_IN_SECONDS * 1000;
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface TopShardsProps {
|
|
87
94
|
tenantPath: string;
|
|
88
95
|
type?: EPathType;
|
|
89
96
|
}
|
|
90
97
|
|
|
91
|
-
export const
|
|
98
|
+
export const TopShards = ({tenantPath, type}: TopShardsProps) => {
|
|
92
99
|
const dispatch = useDispatch();
|
|
93
100
|
|
|
94
101
|
const {autorefresh, currentSchemaPath} = useTypedSelector((state) => state.schema);
|
|
@@ -101,17 +108,20 @@ export const OverloadedShards = ({tenantPath, type}: OverloadedShardsProps) => {
|
|
|
101
108
|
wasLoaded,
|
|
102
109
|
} = useTypedSelector((state) => state.shardsWorkload);
|
|
103
110
|
|
|
104
|
-
// default
|
|
111
|
+
// default filters shouldn't propagate into URL until user interacts with the control
|
|
105
112
|
// redux initial value can't be used, as it synchronizes with URL
|
|
106
113
|
const [filters, setFilters] = useState<IShardsWorkloadFilters>(() => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
const defaultValue = {...storeFilters};
|
|
115
|
+
|
|
116
|
+
if (!defaultValue.mode) {
|
|
117
|
+
defaultValue.mode = EShardsWorkloadMode.Immediate;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!defaultValue.from && !defaultValue.to) {
|
|
121
|
+
fillDateRangeFor(defaultValue);
|
|
112
122
|
}
|
|
113
123
|
|
|
114
|
-
return
|
|
124
|
+
return defaultValue;
|
|
115
125
|
});
|
|
116
126
|
|
|
117
127
|
const [sortOrder, setSortOrder] = useState(tableColumnsNames.CPUCores);
|
|
@@ -144,18 +154,34 @@ export const OverloadedShards = ({tenantPath, type}: OverloadedShardsProps) => {
|
|
|
144
154
|
const history = useContext(HistoryContext);
|
|
145
155
|
|
|
146
156
|
const onSort = (newSortOrder?: SortOrder | SortOrder[]) => {
|
|
147
|
-
// omit information about sort order to disable ASC order, only DESC makes sense for
|
|
157
|
+
// omit information about sort order to disable ASC order, only DESC makes sense for top shards
|
|
148
158
|
// use a string (and not the DataTable default format) to prevent reference change,
|
|
149
159
|
// which would cause an excess state change, to avoid repeating requests
|
|
150
160
|
setSortOrder(dataTableToStringSortOrder(newSortOrder));
|
|
151
161
|
};
|
|
152
162
|
|
|
153
|
-
const
|
|
163
|
+
const handleFiltersChange = (value: Partial<IShardsWorkloadFilters>) => {
|
|
164
|
+
const newStateValue = {...value};
|
|
165
|
+
const isDateRangePristine =
|
|
166
|
+
!storeFilters.from && !storeFilters.to && !value.from && !value.to;
|
|
167
|
+
|
|
168
|
+
if (isDateRangePristine) {
|
|
169
|
+
switch (value.mode) {
|
|
170
|
+
case EShardsWorkloadMode.Immediate:
|
|
171
|
+
newStateValue.from = newStateValue.to = undefined;
|
|
172
|
+
break;
|
|
173
|
+
case EShardsWorkloadMode.History:
|
|
174
|
+
// should default to the current datetime every time history mode activates
|
|
175
|
+
fillDateRangeFor(newStateValue);
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
154
180
|
dispatch(setShardsQueryFilters(value));
|
|
155
|
-
setFilters(
|
|
181
|
+
setFilters((state) => ({...state, ...newStateValue}));
|
|
156
182
|
};
|
|
157
183
|
|
|
158
|
-
const tableColumns
|
|
184
|
+
const tableColumns = useMemo(() => {
|
|
159
185
|
const onSchemaClick = (schemaPath: string) => {
|
|
160
186
|
return () => {
|
|
161
187
|
dispatch(setCurrentSchemaPath(schemaPath));
|
|
@@ -164,7 +190,7 @@ export const OverloadedShards = ({tenantPath, type}: OverloadedShardsProps) => {
|
|
|
164
190
|
};
|
|
165
191
|
};
|
|
166
192
|
|
|
167
|
-
|
|
193
|
+
const columns: Column<any>[] = [
|
|
168
194
|
{
|
|
169
195
|
name: tableColumnsNames.Path,
|
|
170
196
|
render: ({value: relativeNodePath}) => {
|
|
@@ -217,23 +243,29 @@ export const OverloadedShards = ({tenantPath, type}: OverloadedShardsProps) => {
|
|
|
217
243
|
align: DataTable.RIGHT,
|
|
218
244
|
sortable: false,
|
|
219
245
|
},
|
|
220
|
-
{
|
|
221
|
-
name: tableColumnsNames.PeakTime,
|
|
222
|
-
render: ({value}) => formatDateTime(new Date(value as string).valueOf()),
|
|
223
|
-
sortable: false,
|
|
224
|
-
},
|
|
225
246
|
{
|
|
226
247
|
name: tableColumnsNames.InFlightTxCount,
|
|
227
248
|
render: ({value}) => formatNumber(value as number),
|
|
228
249
|
align: DataTable.RIGHT,
|
|
229
250
|
sortable: false,
|
|
230
251
|
},
|
|
231
|
-
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
if (filters.mode === EShardsWorkloadMode.History) {
|
|
255
|
+
// after NodeId
|
|
256
|
+
columns.splice(5, 0, {
|
|
257
|
+
name: tableColumnsNames.PeakTime,
|
|
258
|
+
render: ({value}) => formatDateTime(new Date(value as string).valueOf()),
|
|
259
|
+
sortable: false,
|
|
260
|
+
});
|
|
261
|
+
columns.push({
|
|
232
262
|
name: tableColumnsNames.IntervalEnd,
|
|
233
263
|
render: ({value}) => formatDateTime(new Date(value as string).getTime()),
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return columns;
|
|
268
|
+
}, [dispatch, filters.mode, history, tenantPath]);
|
|
237
269
|
|
|
238
270
|
const renderLoader = () => {
|
|
239
271
|
return (
|
|
@@ -272,10 +304,8 @@ export const OverloadedShards = ({tenantPath, type}: OverloadedShardsProps) => {
|
|
|
272
304
|
|
|
273
305
|
return (
|
|
274
306
|
<div className={b()}>
|
|
275
|
-
<
|
|
276
|
-
|
|
277
|
-
<DateRange from={filters.from} to={filters.to} onChange={handleDateRangeChange} />
|
|
278
|
-
</div>
|
|
307
|
+
<Filters value={filters} onChange={handleFiltersChange} />
|
|
308
|
+
{filters.mode === EShardsWorkloadMode.History && <div>{i18n('description')}</div>}
|
|
279
309
|
{renderContent()}
|
|
280
310
|
</div>
|
|
281
311
|
);
|
|
@@ -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-top-shards';
|
|
7
|
+
|
|
8
|
+
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
|
9
|
+
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
|
10
|
+
|
|
11
|
+
export default i18n.keyset(COMPONENT);
|