ydb-embedded-ui 3.3.4 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/components/Errors/ResponseError/ResponseError.tsx +2 -2
  3. package/dist/components/InfoViewer/formatters/topicStats.tsx +8 -29
  4. package/dist/components/LabelWithPopover/LabelWithPopover.tsx +20 -0
  5. package/dist/components/LabelWithPopover/index.ts +1 -0
  6. package/dist/components/LagImages/LagImages.tsx +205 -0
  7. package/dist/components/LagImages/index.ts +1 -0
  8. package/dist/components/SpeedMultiMeter/SpeedMultiMeter.scss +92 -0
  9. package/dist/components/SpeedMultiMeter/SpeedMultiMeter.tsx +120 -0
  10. package/dist/components/SpeedMultiMeter/i18n/en.json +6 -0
  11. package/dist/components/SpeedMultiMeter/i18n/index.ts +13 -0
  12. package/dist/components/SpeedMultiMeter/i18n/ru.json +6 -0
  13. package/dist/components/SpeedMultiMeter/index.ts +1 -0
  14. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +18 -14
  15. package/dist/containers/Storage/VDisk/VDisk.tsx +20 -5
  16. package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +34 -5
  17. package/dist/containers/Storage/utils/types.ts +5 -0
  18. package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.scss +32 -3
  19. package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.tsx +62 -69
  20. package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.scss +13 -0
  21. package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.tsx +27 -0
  22. package/dist/containers/Tenant/Diagnostics/Consumers/Headers/index.ts +1 -0
  23. package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/ConsumersTopicStats.scss +32 -0
  24. package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/ConsumersTopicStats.tsx +43 -0
  25. package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/index.ts +1 -0
  26. package/dist/containers/Tenant/Diagnostics/Consumers/columns/Columns.scss +5 -0
  27. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +66 -0
  28. package/dist/containers/Tenant/Diagnostics/Consumers/columns/index.ts +1 -0
  29. package/dist/containers/Tenant/Diagnostics/Consumers/i18n/en.json +4 -3
  30. package/dist/containers/Tenant/Diagnostics/Consumers/i18n/ru.json +4 -3
  31. package/dist/containers/Tenant/Diagnostics/Consumers/utils/constants.ts +23 -0
  32. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -0
  33. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +8 -2
  34. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.scss +9 -1
  35. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +6 -8
  36. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.scss +33 -0
  37. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.tsx +76 -0
  38. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/index.ts +1 -0
  39. package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.scss +45 -0
  40. package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +254 -0
  41. package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsWrapper.tsx +79 -0
  42. package/dist/containers/Tenant/Diagnostics/Partitions/columns/Columns.scss +13 -0
  43. package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx +246 -0
  44. package/dist/containers/Tenant/Diagnostics/Partitions/columns/index.ts +1 -0
  45. package/dist/containers/Tenant/Diagnostics/Partitions/i18n/en.json +13 -0
  46. package/dist/containers/Tenant/Diagnostics/Partitions/i18n/index.ts +11 -0
  47. package/dist/containers/Tenant/Diagnostics/Partitions/i18n/ru.json +13 -0
  48. package/dist/containers/Tenant/Diagnostics/Partitions/index.ts +1 -0
  49. package/dist/containers/Tenant/Diagnostics/Partitions/utils/constants.ts +74 -0
  50. package/dist/containers/Tenant/Diagnostics/Partitions/utils/types.ts +6 -0
  51. package/dist/containers/Tenant/utils/schema.ts +1 -16
  52. package/dist/services/api.d.ts +4 -0
  53. package/dist/services/api.js +22 -6
  54. package/dist/store/reducers/consumer.ts +160 -0
  55. package/dist/store/reducers/index.ts +2 -0
  56. package/dist/store/reducers/settings.js +2 -0
  57. package/dist/store/reducers/topic.ts +82 -2
  58. package/dist/types/store/consumer.ts +55 -0
  59. package/dist/types/store/topic.ts +23 -6
  60. package/dist/utils/bytesParsers/convertBytesObjectToSpeed.ts +24 -0
  61. package/dist/utils/bytesParsers/formatBytesCustom.ts +57 -0
  62. package/dist/utils/bytesParsers/i18n/en.json +7 -0
  63. package/dist/utils/bytesParsers/i18n/index.ts +11 -0
  64. package/dist/utils/bytesParsers/i18n/ru.json +7 -0
  65. package/dist/utils/bytesParsers/index.ts +2 -0
  66. package/dist/utils/constants.ts +3 -0
  67. package/dist/utils/index.js +6 -0
  68. package/dist/utils/storage.ts +2 -2
  69. package/dist/utils/timeParsers/index.ts +2 -1
  70. package/dist/utils/timeParsers/parsers.ts +18 -0
  71. package/dist/utils/timeParsers/{protobuf.ts → protobufParsers.ts} +0 -0
  72. package/dist/utils/utils.js +3 -3
  73. package/package.json +2 -2
@@ -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
+ }
@@ -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-partitions';
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,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,6 @@
1
+ import type {IPreparedPartitionData} from '../../../../../types/store/consumer';
2
+
3
+ export interface IPreparedPartitionDataWithHosts extends IPreparedPartitionData {
4
+ partitionHost: string | undefined;
5
+ connectionHost: string | undefined;
6
+ }
@@ -155,22 +155,7 @@ export const isDatabaseEntityType = (type?: EPathType) =>
155
155
 
156
156
  // ====================
157
157
 
158
- const pathTypeToIsCdcStream: Record<EPathType, boolean> = {
159
- [EPathType.EPathTypeCdcStream]: true,
160
-
161
- [EPathType.EPathTypeInvalid]: false,
162
- [EPathType.EPathTypeColumnStore]: false,
163
- [EPathType.EPathTypeColumnTable]: false,
164
- [EPathType.EPathTypeDir]: false,
165
- [EPathType.EPathTypeTable]: false,
166
- [EPathType.EPathTypeSubDomain]: false,
167
- [EPathType.EPathTypeTableIndex]: false,
168
- [EPathType.EPathTypeExtSubDomain]: false,
169
- [EPathType.EPathTypePersQueueGroup]: false,
170
- };
171
-
172
- export const isCdcStreamEntityType = (type?: EPathType) =>
173
- (type && pathTypeToIsCdcStream[type]) ?? false;
158
+ export const isCdcStreamEntityType = (type?: EPathType) => type === EPathType.EPathTypeCdcStream;
174
159
 
175
160
  // ====================
176
161
 
@@ -62,6 +62,10 @@ interface Window {
62
62
  getTopic: (params: {
63
63
  path?: string;
64
64
  }) => Promise<import('../types/api/topic').DescribeTopicResult>;
65
+ getConsumer: (params: {
66
+ path?: string;
67
+ consumer?: string;
68
+ }) => Promise<import('../types/api/consumer').DescribeConsumerResult>;
65
69
  [method: string]: Function;
66
70
  };
67
71
  }
@@ -141,12 +141,28 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
141
141
  path,
142
142
  });
143
143
  }
144
- getTopic({path}) {
145
- return this.get(this.getPath('/viewer/json/describe_topic'), {
146
- enums: true,
147
- include_stats: true,
148
- path,
149
- });
144
+ getTopic({path}, {concurrentId} = {}) {
145
+ return this.get(
146
+ this.getPath('/viewer/json/describe_topic'),
147
+ {
148
+ enums: true,
149
+ include_stats: true,
150
+ path,
151
+ },
152
+ {concurrentId: concurrentId || 'getTopic'},
153
+ );
154
+ }
155
+ getConsumer({path, consumer}, {concurrentId} = {}) {
156
+ return this.get(
157
+ this.getPath('/viewer/json/describe_consumer'),
158
+ {
159
+ enums: true,
160
+ include_stats: true,
161
+ path,
162
+ consumer,
163
+ },
164
+ {concurrentId: concurrentId || 'getConsumer'},
165
+ );
150
166
  }
151
167
  getPoolInfo(poolName) {
152
168
  return this.get(this.getPath('/viewer/json/storage'), {
@@ -0,0 +1,160 @@
1
+ /* eslint-disable camelcase */
2
+ import type {Reducer} from 'redux';
3
+ import {createSelector, Selector} from 'reselect';
4
+
5
+ import type {
6
+ IConsumerAction,
7
+ IConsumerRootStateSlice,
8
+ IConsumerState,
9
+ IPreparedPartitionData,
10
+ } from '../../types/store/consumer';
11
+
12
+ import '../../services/api';
13
+
14
+ import {convertBytesObjectToSpeed} from '../../utils/bytesParsers';
15
+ import {parseLag, parseTimestampToIdleTime} from '../../utils/timeParsers';
16
+ import {isNumeric} from '../../utils/utils';
17
+
18
+ import {createRequestActionTypes, createApiRequest} from '../utils';
19
+
20
+ export const FETCH_CONSUMER = createRequestActionTypes('consumer', 'FETCH_CONSUMER');
21
+
22
+ const SET_DATA_WAS_NOT_LOADED = 'consumer/SET_DATA_WAS_NOT_LOADED';
23
+
24
+ const initialState = {
25
+ loading: false,
26
+ wasLoaded: false,
27
+ data: {},
28
+ };
29
+
30
+ const consumer: Reducer<IConsumerState, IConsumerAction> = (state = initialState, action) => {
31
+ switch (action.type) {
32
+ case FETCH_CONSUMER.REQUEST: {
33
+ return {
34
+ ...state,
35
+ loading: true,
36
+ };
37
+ }
38
+ case FETCH_CONSUMER.SUCCESS: {
39
+ // On older version it can return HTML page of Internal Viewer with an error
40
+ if (typeof action.data !== 'object') {
41
+ return {...state, loading: false, error: {}};
42
+ }
43
+
44
+ return {
45
+ ...state,
46
+ data: action.data,
47
+ loading: false,
48
+ wasLoaded: true,
49
+ error: undefined,
50
+ };
51
+ }
52
+ case FETCH_CONSUMER.FAILURE: {
53
+ if (action.error?.isCancelled) {
54
+ return state;
55
+ }
56
+
57
+ return {
58
+ ...state,
59
+ error: action.error,
60
+ loading: false,
61
+ };
62
+ }
63
+ case SET_DATA_WAS_NOT_LOADED: {
64
+ return {
65
+ ...state,
66
+ wasLoaded: false,
67
+ };
68
+ }
69
+ default:
70
+ return state;
71
+ }
72
+ };
73
+
74
+ export const setDataWasNotLoaded = () => {
75
+ return {
76
+ type: SET_DATA_WAS_NOT_LOADED,
77
+ } as const;
78
+ };
79
+
80
+ export function getConsumer(path?: string, consumerName?: string) {
81
+ return createApiRequest({
82
+ request: window.api.getConsumer({path, consumer: consumerName}),
83
+ actions: FETCH_CONSUMER,
84
+ });
85
+ }
86
+
87
+ export const selectPartitions = (state: IConsumerRootStateSlice) => state.consumer.data?.partitions;
88
+
89
+ export const selectPreparedPartitionsData: Selector<
90
+ IConsumerRootStateSlice,
91
+ IPreparedPartitionData[] | undefined
92
+ > = createSelector([selectPartitions], (partitions) => {
93
+ return partitions?.map((partition) => {
94
+ // describe_consumer endpoint doesn't return zero values, so some values will be initialized with 0
95
+ const {partition_id = '0', partition_stats, partition_consumer_stats} = partition;
96
+
97
+ const {
98
+ partition_offsets,
99
+ store_size_bytes = '0',
100
+ last_write_time: partition_last_write_time,
101
+ max_write_time_lag: partition_write_lag,
102
+ bytes_written,
103
+ partition_node_id = 0,
104
+ } = partition_stats || {};
105
+
106
+ const {start: start_offset = '0', end: end_offset = '0'} = partition_offsets || {};
107
+
108
+ const {
109
+ last_read_offset = '0',
110
+ committed_offset = '0',
111
+ read_session_id,
112
+ last_read_time: consumer_last_read_time,
113
+ max_read_time_lag: consumer_read_lag,
114
+ max_write_time_lag: consumer_write_lag,
115
+ bytes_read,
116
+ reader_name,
117
+ connection_node_id = 0,
118
+ } = partition_consumer_stats || {};
119
+
120
+ const uncommitedMessages =
121
+ isNumeric(end_offset) && isNumeric(committed_offset)
122
+ ? Number(end_offset) - Number(committed_offset)
123
+ : 0;
124
+
125
+ const unreadMessages =
126
+ isNumeric(end_offset) && isNumeric(last_read_offset)
127
+ ? Number(end_offset) - Number(last_read_offset)
128
+ : 0;
129
+
130
+ return {
131
+ partitionId: partition_id,
132
+ storeSize: store_size_bytes,
133
+
134
+ writeSpeed: convertBytesObjectToSpeed(bytes_written),
135
+ readSpeed: convertBytesObjectToSpeed(bytes_read),
136
+
137
+ partitionWriteLag: parseLag(partition_write_lag),
138
+ partitionWriteIdleTime: parseTimestampToIdleTime(partition_last_write_time),
139
+
140
+ consumerWriteLag: parseLag(consumer_write_lag),
141
+ consumerReadLag: parseLag(consumer_read_lag),
142
+ consumerReadIdleTime: parseTimestampToIdleTime(consumer_last_read_time),
143
+
144
+ uncommitedMessages,
145
+ unreadMessages,
146
+
147
+ startOffset: start_offset,
148
+ endOffset: end_offset,
149
+ commitedOffset: committed_offset,
150
+
151
+ readSessionId: read_session_id,
152
+ readerName: reader_name,
153
+
154
+ partitionNodeId: partition_node_id,
155
+ connectionNodeId: connection_node_id,
156
+ };
157
+ });
158
+ });
159
+
160
+ export default consumer;
@@ -18,6 +18,7 @@ import pool from './pool';
18
18
  import tenants from './tenants';
19
19
  import tablet from './tablet';
20
20
  import topic from './topic';
21
+ import consumer from './consumer';
21
22
  import executeQuery from './executeQuery';
22
23
  import explainQuery from './explainQuery';
23
24
  import tabletsFilters from './tabletsFilters';
@@ -57,6 +58,7 @@ export const rootReducer = {
57
58
  tenants,
58
59
  tablet,
59
60
  topic,
61
+ consumer,
60
62
  executeQuery,
61
63
  explainQuery,
62
64
  tabletsFilters,
@@ -7,6 +7,7 @@ import {
7
7
  INVERTED_DISKS_KEY,
8
8
  ASIDE_HEADER_COMPACT_KEY,
9
9
  USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
10
+ PARTITIONS_SELECTED_COLUMNS_KEY,
10
11
  } from '../../utils/constants';
11
12
  import '../../services/api';
12
13
  import {getValueFromLS} from '../../utils/utils';
@@ -50,6 +51,7 @@ export const initialState = {
50
51
  ASIDE_HEADER_COMPACT_KEY,
51
52
  legacyAsideNavCompactState || 'true',
52
53
  ),
54
+ [PARTITIONS_SELECTED_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_SELECTED_COLUMNS_KEY),
53
55
  },
54
56
  systemSettings,
55
57
  };