ydb-embedded-ui 3.3.4 → 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.
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
  };