ydb-embedded-ui 4.21.1 → 4.23.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +27 -0
- package/dist/components/ProgressViewer/ProgressViewer.tsx +1 -1
- package/dist/components/VirtualTable/TableChunk.tsx +2 -1
- package/dist/components/VirtualTable/VirtualTable.tsx +1 -1
- package/dist/containers/Cluster/Cluster.tsx +2 -0
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.scss +14 -5
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +104 -24
- package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.tsx +1 -1
- package/dist/containers/Cluster/i18n/en.json +16 -0
- package/dist/containers/Cluster/i18n/index.ts +11 -0
- package/dist/containers/Cluster/i18n/ru.json +16 -0
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +4 -1
- package/dist/containers/Nodes/getNodesColumns.tsx +57 -13
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +5 -10
- package/dist/containers/Tenant/Diagnostics/Network/utils.ts +6 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx +18 -3
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx +18 -3
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx +17 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx +20 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx +18 -3
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx +2 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopGroups.tsx +19 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx +8 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/getSectionTitle.tsx +28 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +17 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +17 -1
- package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.scss +13 -5
- package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx +72 -18
- package/dist/containers/Tenant/Query/ExplainResult/ExplainResult.js +2 -1
- package/dist/containers/Tenant/Query/ExplainResult/utils.ts +6 -0
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +11 -24
- package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +4 -5
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.tsx +19 -11
- package/dist/containers/UserSettings/i18n/en.json +3 -0
- package/dist/containers/UserSettings/i18n/ru.json +3 -0
- package/dist/containers/UserSettings/settings.ts +7 -0
- package/dist/store/reducers/cluster/__test__/parseGroupsStatsQueryResponse.test.ts +121 -0
- package/dist/store/reducers/cluster/cluster.ts +46 -2
- package/dist/store/reducers/cluster/types.ts +29 -4
- package/dist/store/reducers/cluster/utils.ts +88 -0
- package/dist/store/reducers/executeQuery.ts +4 -3
- package/dist/store/reducers/nodes/types.ts +11 -1
- package/dist/store/reducers/nodes/utils.ts +6 -0
- package/dist/store/reducers/settings/settings.ts +2 -0
- package/dist/types/api/cluster.ts +3 -0
- package/dist/types/api/netInfo.ts +1 -1
- package/dist/types/api/nodes.ts +24 -0
- package/dist/types/api/query.ts +23 -8
- package/dist/types/store/query.ts +6 -0
- package/dist/utils/constants.ts +3 -0
- package/dist/utils/developerUI/__test__/developerUI.test.ts +50 -0
- package/dist/utils/developerUI/developerUI.ts +42 -0
- package/dist/utils/diagnostics.ts +1 -0
- package/dist/utils/hooks/index.ts +1 -0
- package/dist/utils/hooks/useSearchQuery.ts +9 -0
- package/dist/utils/query.ts +60 -12
- package/package.json +1 -1
- package/dist/utils/developerUI.ts +0 -32
- package/dist/utils/index.js +0 -9
- /package/dist/{components/VirtualTable/utils.ts → utils/index.ts} +0 -0
package/dist/types/api/nodes.ts
CHANGED
@@ -26,6 +26,9 @@ export interface TNodeInfo {
|
|
26
26
|
Tablets?: TTabletStateInfo[];
|
27
27
|
}
|
28
28
|
|
29
|
+
/**
|
30
|
+
* source: https://github.com/ydb-platform/ydb/blob/main/ydb/core/protos/node_whiteboard.proto
|
31
|
+
*/
|
29
32
|
export interface TSystemStateInfo {
|
30
33
|
/** uint64 */
|
31
34
|
StartTime?: string;
|
@@ -62,6 +65,20 @@ export interface TSystemStateInfo {
|
|
62
65
|
/** double */
|
63
66
|
MaxDiskUsage?: number;
|
64
67
|
Location?: TNodeLocation;
|
68
|
+
|
69
|
+
/**
|
70
|
+
* int64
|
71
|
+
*
|
72
|
+
* a positive value means the peer is ahead in time; a negative value means it's behind
|
73
|
+
*/
|
74
|
+
MaxClockSkewWithPeerUs?: string;
|
75
|
+
MaxClockSkewPeerId?: number;
|
76
|
+
|
77
|
+
/** uint64 */
|
78
|
+
DisconnectTime?: string;
|
79
|
+
|
80
|
+
SharedCacheStats?: TNodeSharedCache;
|
81
|
+
TotalSessions?: number;
|
65
82
|
}
|
66
83
|
|
67
84
|
export interface TPoolStats {
|
@@ -97,6 +114,13 @@ interface TNodeLocation {
|
|
97
114
|
Unit?: string;
|
98
115
|
}
|
99
116
|
|
117
|
+
interface TNodeSharedCache {
|
118
|
+
/** uint64 */
|
119
|
+
UsedBytes: string;
|
120
|
+
/** uint64 */
|
121
|
+
LimitBytes: string;
|
122
|
+
}
|
123
|
+
|
100
124
|
enum EConfigState {
|
101
125
|
'Consistent' = 'Consistent',
|
102
126
|
'Outdated' = 'Outdated',
|
package/dist/types/api/query.ts
CHANGED
@@ -180,7 +180,7 @@ export interface ColumnType {
|
|
180
180
|
}
|
181
181
|
|
182
182
|
/** undefined = 'classic' */
|
183
|
-
export type Schemas = 'classic' | 'modern' | 'ydb' | undefined;
|
183
|
+
export type Schemas = 'classic' | 'modern' | 'ydb' | 'multi' | undefined;
|
184
184
|
|
185
185
|
/** undefined = 'execute' */
|
186
186
|
export type ExecuteActions =
|
@@ -231,16 +231,29 @@ export type ExplainResponse<Action extends ExplainActions> = Action extends 'exp
|
|
231
231
|
? ExplainScriptResponse
|
232
232
|
: ExplainQueryResponse;
|
233
233
|
|
234
|
+
// ==== Execute Results ====
|
235
|
+
|
236
|
+
interface ModernSchemaResult {
|
237
|
+
result?: ArrayRow[];
|
238
|
+
columns?: ColumnType[];
|
239
|
+
}
|
240
|
+
interface MultiSchemaResult {
|
241
|
+
result?: {
|
242
|
+
rows?: ArrayRow[] | null;
|
243
|
+
columns?: ColumnType[];
|
244
|
+
}[];
|
245
|
+
}
|
246
|
+
interface DefaultSchemaResult {
|
247
|
+
result?: KeyValueRow[];
|
248
|
+
}
|
249
|
+
|
234
250
|
// ==== Execute Responses ====
|
235
251
|
|
236
252
|
type ResultFields<Schema extends Schemas> = Schema extends 'modern'
|
237
|
-
?
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
: {
|
242
|
-
result?: KeyValueRow[];
|
243
|
-
};
|
253
|
+
? ModernSchemaResult
|
254
|
+
: Schema extends 'multi'
|
255
|
+
? MultiSchemaResult
|
256
|
+
: DefaultSchemaResult;
|
244
257
|
|
245
258
|
/**
|
246
259
|
* meta.type = 'query'
|
@@ -287,6 +300,7 @@ export type AnyExplainResponse = ExplainQueryResponse | ExplainScriptResponse;
|
|
287
300
|
export type ExecuteModernResponse =
|
288
301
|
| ExecuteQueryResponse<'modern'>
|
289
302
|
| ExecuteScriptResponse<'modern'>;
|
303
|
+
export type ExecuteMultiResponse = ExecuteQueryResponse<'multi'> | ExecuteScriptResponse<'multi'>;
|
290
304
|
export type ExecuteClassicResponse =
|
291
305
|
| ExecuteQueryResponse<'classic'>
|
292
306
|
| ExecuteScriptResponse<'classic'>;
|
@@ -294,5 +308,6 @@ export type ExecuteYdbResponse = ExecuteQueryResponse<'ydb'> | ExecuteScriptResp
|
|
294
308
|
|
295
309
|
export type AnyExecuteResponse =
|
296
310
|
| ExecuteModernResponse
|
311
|
+
| ExecuteMultiResponse
|
297
312
|
| ExecuteClassicResponse
|
298
313
|
| ExecuteYdbResponse;
|
@@ -11,7 +11,13 @@ import type {
|
|
11
11
|
} from '../api/query';
|
12
12
|
import type {ValueOf} from '../common';
|
13
13
|
|
14
|
+
export interface ParsedResultSet {
|
15
|
+
columns?: ColumnType[];
|
16
|
+
result?: KeyValueRow[];
|
17
|
+
}
|
18
|
+
|
14
19
|
export interface IQueryResult {
|
20
|
+
resultSets?: ParsedResultSet[];
|
15
21
|
result?: KeyValueRow[];
|
16
22
|
columns?: ColumnType[];
|
17
23
|
stats?: TKqpStatsQuery;
|
package/dist/utils/constants.ts
CHANGED
@@ -133,3 +133,6 @@ export const TENANT_INITIAL_PAGE_KEY = 'saved_tenant_initial_tab';
|
|
133
133
|
|
134
134
|
// Send filters and sort params to backend for Nodes and Storage tables
|
135
135
|
export const USE_BACKEND_PARAMS_FOR_TABLES_KEY = 'useBackendParamsForTables';
|
136
|
+
|
137
|
+
// Enable schema that supports multiple resultsets
|
138
|
+
export const QUERY_USE_MULTI_SCHEMA_KEY = 'queryUseMultiSchema';
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import {
|
2
|
+
createDeveloperUILinkWithNodeId,
|
3
|
+
createPDiskDeveloperUILink,
|
4
|
+
createVDiskDeveloperUILink,
|
5
|
+
} from '../developerUI';
|
6
|
+
|
7
|
+
describe('Developer UI links generators', () => {
|
8
|
+
describe('createDeveloperUILinkWithNodeId', () => {
|
9
|
+
it('should create relative link with no host', () => {
|
10
|
+
expect(createDeveloperUILinkWithNodeId(1)).toBe('/node/1/');
|
11
|
+
});
|
12
|
+
it('should create relative link with existing relative path with nodeId', () => {
|
13
|
+
expect(createDeveloperUILinkWithNodeId(1, '/node/3/')).toBe('/node/1/');
|
14
|
+
});
|
15
|
+
it('should create full link with host', () => {
|
16
|
+
expect(
|
17
|
+
createDeveloperUILinkWithNodeId(
|
18
|
+
1,
|
19
|
+
'http://ydb-vla-dev02-001.search.yandex.net:8765',
|
20
|
+
),
|
21
|
+
).toBe('http://ydb-vla-dev02-001.search.yandex.net:8765/node/1/');
|
22
|
+
});
|
23
|
+
it('should create full link with host with existing node path with nodeId', () => {
|
24
|
+
expect(
|
25
|
+
createDeveloperUILinkWithNodeId(
|
26
|
+
1,
|
27
|
+
'http://ydb-vla-dev02-001.search.yandex.net:8765/node/3',
|
28
|
+
),
|
29
|
+
).toBe('http://ydb-vla-dev02-001.search.yandex.net:8765/node/1/');
|
30
|
+
});
|
31
|
+
});
|
32
|
+
describe('createPDiskDeveloperUILink', () => {
|
33
|
+
it('should create link with pDiskId and nodeId', () => {
|
34
|
+
expect(createPDiskDeveloperUILink({nodeId: 1, pDiskId: 1})).toBe(
|
35
|
+
'/node/1/actors/pdisks/pdisk000000001',
|
36
|
+
);
|
37
|
+
});
|
38
|
+
});
|
39
|
+
describe('createVDiskDeveloperUILink', () => {
|
40
|
+
it('should create link with pDiskId, vDiskSlotId nodeId', () => {
|
41
|
+
expect(
|
42
|
+
createVDiskDeveloperUILink({
|
43
|
+
nodeId: 1,
|
44
|
+
pDiskId: 1,
|
45
|
+
vDiskSlotId: 1,
|
46
|
+
}),
|
47
|
+
).toBe('/node/1/actors/vdisks/vdisk000000001_000000001');
|
48
|
+
});
|
49
|
+
});
|
50
|
+
});
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import {backend} from '../../store';
|
2
|
+
import {pad9} from '../utils';
|
3
|
+
|
4
|
+
// Current node connects with target node by itself using nodeId
|
5
|
+
export const createDeveloperUILinkWithNodeId = (nodeId: number | string, host = backend) => {
|
6
|
+
const nodePathRegexp = /\/node\/\d+\/?$/g;
|
7
|
+
|
8
|
+
// In case current backend is already relative node path ({host}/node/{nodeId})
|
9
|
+
// We replace existing nodeId path with new nodeId path
|
10
|
+
if (nodePathRegexp.test(String(host))) {
|
11
|
+
return String(host).replace(nodePathRegexp, `/node/${nodeId}/`);
|
12
|
+
}
|
13
|
+
|
14
|
+
return `${host ?? ''}/node/${nodeId}/`;
|
15
|
+
};
|
16
|
+
|
17
|
+
interface PDiskDeveloperUILinkParams {
|
18
|
+
nodeId: number | string;
|
19
|
+
pDiskId: number | string;
|
20
|
+
host?: string;
|
21
|
+
}
|
22
|
+
|
23
|
+
export const createPDiskDeveloperUILink = ({nodeId, pDiskId, host}: PDiskDeveloperUILinkParams) => {
|
24
|
+
const pdiskPath = 'actors/pdisks/pdisk' + pad9(pDiskId);
|
25
|
+
|
26
|
+
return createDeveloperUILinkWithNodeId(nodeId, host) + pdiskPath;
|
27
|
+
};
|
28
|
+
|
29
|
+
interface VDiskDeveloperUILinkParams extends PDiskDeveloperUILinkParams {
|
30
|
+
vDiskSlotId: number | string;
|
31
|
+
}
|
32
|
+
|
33
|
+
export const createVDiskDeveloperUILink = ({
|
34
|
+
nodeId,
|
35
|
+
pDiskId,
|
36
|
+
vDiskSlotId,
|
37
|
+
host,
|
38
|
+
}: VDiskDeveloperUILinkParams) => {
|
39
|
+
const vdiskPath = 'actors/vdisks/vdisk' + pad9(pDiskId) + '_' + pad9(vDiskSlotId);
|
40
|
+
|
41
|
+
return createDeveloperUILinkWithNodeId(nodeId, host) + vdiskPath;
|
42
|
+
};
|
package/dist/utils/query.ts
CHANGED
@@ -2,7 +2,10 @@ import {YQLType} from '../types';
|
|
2
2
|
import type {
|
3
3
|
AnyExecuteResponse,
|
4
4
|
AnyExplainResponse,
|
5
|
+
ArrayRow,
|
6
|
+
ColumnType,
|
5
7
|
ExecuteModernResponse,
|
8
|
+
ExecuteMultiResponse,
|
6
9
|
KeyValueRow,
|
7
10
|
QueryPlan,
|
8
11
|
ScriptPlan,
|
@@ -76,34 +79,74 @@ export const getColumnType = (type: string) => {
|
|
76
79
|
}
|
77
80
|
};
|
78
81
|
|
79
|
-
/** parse response result
|
82
|
+
/** parse response result from ArrayRow to KeyValueRow */
|
83
|
+
const parseModernResult = (rows: ArrayRow[], columns: ColumnType[]) => {
|
84
|
+
return rows.map((row) => {
|
85
|
+
return row.reduce<KeyValueRow>((newRow, cellData, columnIndex) => {
|
86
|
+
const {name} = columns[columnIndex];
|
87
|
+
newRow[name] = cellData;
|
88
|
+
return newRow;
|
89
|
+
}, {});
|
90
|
+
});
|
91
|
+
};
|
92
|
+
|
80
93
|
const parseExecuteModernResponse = (data: ExecuteModernResponse): IQueryResult => {
|
81
94
|
const {result, columns, ...restData} = data;
|
82
95
|
|
83
96
|
return {
|
84
|
-
result:
|
85
|
-
result &&
|
86
|
-
columns &&
|
87
|
-
result.map((row) => {
|
88
|
-
return row.reduce((newRow, cellData, columnIndex) => {
|
89
|
-
const {name} = columns[columnIndex];
|
90
|
-
newRow[name] = cellData;
|
91
|
-
return newRow;
|
92
|
-
}, {} as KeyValueRow);
|
93
|
-
}),
|
97
|
+
result: result && columns && parseModernResult(result, columns),
|
94
98
|
columns,
|
95
99
|
...restData,
|
96
100
|
};
|
97
101
|
};
|
98
102
|
|
103
|
+
const parseExecuteMultiResponse = (data: ExecuteMultiResponse): IQueryResult => {
|
104
|
+
const {result, ...restData} = data;
|
105
|
+
|
106
|
+
const parsedResult = result?.map((resultSet) => {
|
107
|
+
const {rows, columns} = resultSet;
|
108
|
+
|
109
|
+
let parsedRows: KeyValueRow[] | undefined;
|
110
|
+
|
111
|
+
if (columns) {
|
112
|
+
// Result shouldn't be null if there are columns
|
113
|
+
parsedRows = [];
|
114
|
+
}
|
115
|
+
|
116
|
+
if (rows && columns) {
|
117
|
+
parsedRows = parseModernResult(rows, columns);
|
118
|
+
}
|
119
|
+
|
120
|
+
return {
|
121
|
+
columns: columns,
|
122
|
+
result: parsedRows,
|
123
|
+
};
|
124
|
+
});
|
125
|
+
|
126
|
+
return {
|
127
|
+
resultSets: parsedResult, // use a separate field to make result compatible
|
128
|
+
...restData,
|
129
|
+
};
|
130
|
+
};
|
131
|
+
|
99
132
|
const isModern = (response: AnyExecuteResponse): response is ExecuteModernResponse =>
|
100
133
|
Boolean(
|
101
134
|
response &&
|
102
135
|
!Array.isArray(response) &&
|
103
|
-
Array.isArray(
|
136
|
+
Array.isArray(response.result) &&
|
104
137
|
Array.isArray((response as ExecuteModernResponse).columns),
|
105
138
|
);
|
106
139
|
|
140
|
+
const isMulti = (response: AnyExecuteResponse): response is ExecuteMultiResponse =>
|
141
|
+
Boolean(
|
142
|
+
response &&
|
143
|
+
!Array.isArray(response) &&
|
144
|
+
Array.isArray(response.result) &&
|
145
|
+
typeof response.result[0] === 'object' &&
|
146
|
+
'rows' in response.result[0] &&
|
147
|
+
'columns' in response.result[0],
|
148
|
+
);
|
149
|
+
|
107
150
|
type UnsupportedQueryResponseFormat =
|
108
151
|
| Array<unknown>
|
109
152
|
| string
|
@@ -122,12 +165,17 @@ const isUnsupportedType = (
|
|
122
165
|
);
|
123
166
|
};
|
124
167
|
|
168
|
+
// Although schema is set in request, if schema is not supported default schema for the version will be used
|
169
|
+
// So we should additionally parse response
|
125
170
|
export const parseQueryAPIExecuteResponse = (
|
126
171
|
data: AnyExecuteResponse | UnsupportedQueryResponseFormat,
|
127
172
|
): IQueryResult => {
|
128
173
|
if (isUnsupportedType(data)) {
|
129
174
|
return {};
|
130
175
|
}
|
176
|
+
if (isMulti(data)) {
|
177
|
+
return parseExecuteMultiResponse(data);
|
178
|
+
}
|
131
179
|
if (isModern(data)) {
|
132
180
|
return parseExecuteModernResponse(data);
|
133
181
|
}
|
package/package.json
CHANGED
@@ -1,32 +0,0 @@
|
|
1
|
-
import {backend} from '../store';
|
2
|
-
import {pad9} from './utils';
|
3
|
-
|
4
|
-
// Current node connects with target node by itself using nodeId
|
5
|
-
export const createDeveloperUILinkWithNodeId = (nodeId: number | string) => {
|
6
|
-
return `${backend}/node/${nodeId}/`;
|
7
|
-
};
|
8
|
-
|
9
|
-
interface PDiskDeveloperUILinkParams {
|
10
|
-
nodeId: number | string;
|
11
|
-
pDiskId: number | string;
|
12
|
-
}
|
13
|
-
|
14
|
-
export const createPDiskDeveloperUILink = ({nodeId, pDiskId}: PDiskDeveloperUILinkParams) => {
|
15
|
-
const pdiskPath = 'actors/pdisks/pdisk' + pad9(pDiskId);
|
16
|
-
|
17
|
-
return createDeveloperUILinkWithNodeId(nodeId) + pdiskPath;
|
18
|
-
};
|
19
|
-
|
20
|
-
interface VDiskDeveloperUILinkParams extends PDiskDeveloperUILinkParams {
|
21
|
-
vDiskSlotId: number | string;
|
22
|
-
}
|
23
|
-
|
24
|
-
export const createVDiskDeveloperUILink = ({
|
25
|
-
nodeId,
|
26
|
-
pDiskId,
|
27
|
-
vDiskSlotId,
|
28
|
-
}: VDiskDeveloperUILinkParams) => {
|
29
|
-
const vdiskPath = 'actors/vdisks/vdisk' + pad9(pDiskId) + '_' + pad9(vDiskSlotId);
|
30
|
-
|
31
|
-
return createDeveloperUILinkWithNodeId(nodeId) + vdiskPath;
|
32
|
-
};
|
package/dist/utils/index.js
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
// determine how many nodes have status Connected "true"
|
2
|
-
export const getConnectedNodesCount = (nodeStateInfo) => {
|
3
|
-
return nodeStateInfo?.reduce((acc, item) => (item.Connected ? acc + 1 : acc), 0);
|
4
|
-
};
|
5
|
-
|
6
|
-
export const renderExplainNode = (node) => {
|
7
|
-
const parts = node.name.split('|');
|
8
|
-
return parts.length > 1 ? parts[1] : node.name;
|
9
|
-
};
|
File without changes
|