ydb-embedded-ui 3.0.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +17 -0
- package/dist/components/ClusterInfo/ClusterInfo.tsx +1 -1
- package/dist/components/InfoViewer/InfoViewer.tsx +1 -1
- package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +5 -2
- package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +6 -5
- package/dist/components/InfoViewer/schemaInfo/TableIndexInfo.tsx +5 -2
- package/dist/components/ProblemFilter/ProblemFilter.tsx +18 -0
- package/dist/components/ProblemFilter/index.ts +1 -0
- package/dist/components/UptimeFIlter/UptimeFilter.tsx +4 -3
- package/dist/containers/Nodes/Nodes.js +2 -2
- package/dist/containers/NodesViewer/NodesViewer.js +2 -2
- package/dist/containers/Pool/Pool.js +2 -2
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +2 -3
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +2 -2
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -9
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +6 -3
- package/dist/containers/Tenant/Diagnostics/TopShards/DateRange/DateRange.scss +13 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/DateRange/DateRange.tsx +75 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/DateRange/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.scss +17 -1
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +278 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/i18n/en.json +4 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/i18n/ru.json +4 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/index.ts +1 -0
- package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +35 -22
- package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.scss +8 -0
- package/dist/containers/Tenant/Tenant.tsx +1 -1
- package/dist/containers/Tenant/utils/index.ts +8 -0
- package/dist/containers/Tenant/utils/schema.ts +45 -0
- package/dist/containers/Tenants/Tenants.js +2 -2
- package/dist/services/api.d.ts +3 -0
- package/dist/services/api.js +1 -1
- package/dist/store/reducers/{nodes.js → nodes.ts} +20 -14
- package/dist/store/reducers/shardsWorkload.ts +182 -0
- package/dist/store/reducers/{tooltip.js → tooltip.ts} +28 -11
- package/dist/store/state-url-mapping.js +8 -0
- package/dist/types/api/nodes.ts +3 -3
- package/dist/types/api/schema.ts +1 -1
- package/dist/types/api/tenant.ts +131 -0
- package/dist/types/store/nodes.ts +32 -0
- package/dist/types/store/shardsWorkload.ts +28 -0
- package/dist/types/store/tooltip.ts +25 -0
- package/dist/utils/constants.ts +2 -0
- package/dist/utils/nodes.ts +4 -4
- package/dist/utils/query.ts +1 -1
- package/dist/utils/tooltip.js +8 -6
- package/package.json +2 -2
- package/dist/components/ProblemFilter/ProblemFilter.js +0 -24
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +0 -246
- package/dist/store/reducers/shardsWorkload.js +0 -101
- package/dist/utils/actionsConstants.js +0 -4
@@ -1,246 +0,0 @@
|
|
1
|
-
import {useState, useContext, useEffect, useMemo} from 'react';
|
2
|
-
import cn from 'bem-cn-lite';
|
3
|
-
import {connect} from 'react-redux';
|
4
|
-
import {Loader} from '@gravity-ui/uikit';
|
5
|
-
import DataTable from '@yandex-cloud/react-data-table';
|
6
|
-
|
7
|
-
import InternalLink from '../../../../components/InternalLink/InternalLink';
|
8
|
-
|
9
|
-
import routes, {createHref} from '../../../../routes';
|
10
|
-
import {sendShardQuery, setShardQueryOptions} from '../../../../store/reducers/shardsWorkload';
|
11
|
-
import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema';
|
12
|
-
import {AutoFetcher} from '../../../../utils/autofetcher';
|
13
|
-
import HistoryContext from '../../../../contexts/HistoryContext';
|
14
|
-
import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';
|
15
|
-
import {isColumnEntityType} from '../../utils/schema';
|
16
|
-
import {prepareQueryError} from '../../../../utils/query';
|
17
|
-
import {i18n} from '../../../../utils/i18n';
|
18
|
-
|
19
|
-
import './TopShards.scss';
|
20
|
-
|
21
|
-
const b = cn('top-shards');
|
22
|
-
const bLink = cn('yc-link');
|
23
|
-
|
24
|
-
const TABLE_SETTINGS = {
|
25
|
-
...DEFAULT_TABLE_SETTINGS,
|
26
|
-
dynamicRender: false, // no more than 20 rows
|
27
|
-
externalSort: true,
|
28
|
-
disableSortReset: true,
|
29
|
-
defaultOrder: DataTable.DESCENDING,
|
30
|
-
};
|
31
|
-
|
32
|
-
const tableColumnsNames = {
|
33
|
-
TabletId: 'TabletId',
|
34
|
-
CPUCores: 'CPUCores',
|
35
|
-
DataSize: 'DataSize',
|
36
|
-
Path: 'Path',
|
37
|
-
};
|
38
|
-
|
39
|
-
const autofetcher = new AutoFetcher();
|
40
|
-
|
41
|
-
function prepareCPUWorkloadValue(value) {
|
42
|
-
return `${(value * 100).toFixed(2)}%`;
|
43
|
-
}
|
44
|
-
|
45
|
-
function prepareDateSizeValue(value) {
|
46
|
-
return new Intl.NumberFormat(i18n.lang).format(value);
|
47
|
-
}
|
48
|
-
|
49
|
-
function stringToDataTableSortOrder(value) {
|
50
|
-
return (
|
51
|
-
value &&
|
52
|
-
value.split(',').map((columnId) => ({
|
53
|
-
columnId,
|
54
|
-
order: DataTable.DESCENDING,
|
55
|
-
}))
|
56
|
-
);
|
57
|
-
}
|
58
|
-
|
59
|
-
function stringToQuerySortOrder(value) {
|
60
|
-
return (
|
61
|
-
value &&
|
62
|
-
value.split(',').map((columnId) => ({
|
63
|
-
columnId,
|
64
|
-
order: 'DESC',
|
65
|
-
}))
|
66
|
-
);
|
67
|
-
}
|
68
|
-
|
69
|
-
function dataTableToStringSortOrder(value = []) {
|
70
|
-
return value.map(({columnId}) => columnId).join(',');
|
71
|
-
}
|
72
|
-
|
73
|
-
function TopShards({
|
74
|
-
sendShardQuery,
|
75
|
-
currentSchemaPath,
|
76
|
-
path,
|
77
|
-
loading,
|
78
|
-
data,
|
79
|
-
error,
|
80
|
-
setCurrentSchemaPath,
|
81
|
-
getSchema,
|
82
|
-
autorefresh,
|
83
|
-
wasLoaded,
|
84
|
-
setShardQueryOptions,
|
85
|
-
type,
|
86
|
-
}) {
|
87
|
-
const [sortOrder, setSortOrder] = useState(tableColumnsNames.CPUCores);
|
88
|
-
|
89
|
-
useEffect(() => {
|
90
|
-
autofetcher.stop();
|
91
|
-
|
92
|
-
if (autorefresh) {
|
93
|
-
autofetcher.start();
|
94
|
-
autofetcher.fetch(() =>
|
95
|
-
sendShardQuery({
|
96
|
-
database: path,
|
97
|
-
path: currentSchemaPath,
|
98
|
-
sortOrder: stringToQuerySortOrder(sortOrder),
|
99
|
-
}),
|
100
|
-
);
|
101
|
-
}
|
102
|
-
|
103
|
-
return () => {
|
104
|
-
autofetcher.stop();
|
105
|
-
};
|
106
|
-
}, [autorefresh, currentSchemaPath, path, sendShardQuery, sortOrder]);
|
107
|
-
|
108
|
-
// don't show loader for requests triggered by table sort, only for path change
|
109
|
-
useEffect(() => {
|
110
|
-
setShardQueryOptions({
|
111
|
-
wasLoaded: false,
|
112
|
-
data: undefined,
|
113
|
-
});
|
114
|
-
}, [currentSchemaPath, path, setShardQueryOptions]);
|
115
|
-
|
116
|
-
useEffect(() => {
|
117
|
-
sendShardQuery({
|
118
|
-
database: path,
|
119
|
-
path: currentSchemaPath,
|
120
|
-
sortOrder: stringToQuerySortOrder(sortOrder),
|
121
|
-
});
|
122
|
-
}, [currentSchemaPath, path, sendShardQuery, sortOrder]);
|
123
|
-
|
124
|
-
const history = useContext(HistoryContext);
|
125
|
-
|
126
|
-
const onSchemaClick = (schemaPath) => {
|
127
|
-
return () => {
|
128
|
-
setCurrentSchemaPath(schemaPath);
|
129
|
-
getSchema({path: schemaPath});
|
130
|
-
history.go(0);
|
131
|
-
};
|
132
|
-
};
|
133
|
-
|
134
|
-
const onSort = (newSortOrder) => {
|
135
|
-
// omit information about sort order to disable ASC order, only DESC makes sense for top shards
|
136
|
-
// use a string (and not the DataTable default format) to prevent reference change,
|
137
|
-
// which would cause an excess state change, to avoid repeating requests
|
138
|
-
setSortOrder(dataTableToStringSortOrder(newSortOrder));
|
139
|
-
};
|
140
|
-
|
141
|
-
const tableColumns = useMemo(() => {
|
142
|
-
return [
|
143
|
-
{
|
144
|
-
name: tableColumnsNames.Path,
|
145
|
-
// eslint-disable-next-line
|
146
|
-
render: ({value}) => {
|
147
|
-
return (
|
148
|
-
<span
|
149
|
-
// tenant name is substringed out in sql query but is needed here
|
150
|
-
onClick={onSchemaClick(path + value)}
|
151
|
-
className={bLink({view: 'normal'})}
|
152
|
-
>
|
153
|
-
{value}
|
154
|
-
</span>
|
155
|
-
);
|
156
|
-
},
|
157
|
-
sortable: false,
|
158
|
-
},
|
159
|
-
{
|
160
|
-
name: tableColumnsNames.CPUCores,
|
161
|
-
// eslint-disable-next-line
|
162
|
-
render: ({value}) => {
|
163
|
-
return prepareCPUWorkloadValue(value);
|
164
|
-
},
|
165
|
-
align: DataTable.RIGHT,
|
166
|
-
},
|
167
|
-
{
|
168
|
-
name: tableColumnsNames.DataSize,
|
169
|
-
header: 'DataSize (B)',
|
170
|
-
render: ({value}) => {
|
171
|
-
return prepareDateSizeValue(value);
|
172
|
-
},
|
173
|
-
align: DataTable.RIGHT,
|
174
|
-
},
|
175
|
-
{
|
176
|
-
name: tableColumnsNames.TabletId,
|
177
|
-
// eslint-disable-next-line
|
178
|
-
render: ({value}) => {
|
179
|
-
return (
|
180
|
-
<InternalLink to={createHref(routes.tablet, {id: value})}>
|
181
|
-
{value}
|
182
|
-
</InternalLink>
|
183
|
-
);
|
184
|
-
},
|
185
|
-
sortable: false,
|
186
|
-
},
|
187
|
-
];
|
188
|
-
}, []);
|
189
|
-
|
190
|
-
const renderLoader = () => {
|
191
|
-
return (
|
192
|
-
<div className={b('loader')}>
|
193
|
-
<Loader size="m" />
|
194
|
-
</div>
|
195
|
-
);
|
196
|
-
};
|
197
|
-
|
198
|
-
const renderContent = () => {
|
199
|
-
if (isColumnEntityType(type)) {
|
200
|
-
return 'No data';
|
201
|
-
}
|
202
|
-
if (error && !error.isCancelled) {
|
203
|
-
return prepareQueryError(error);
|
204
|
-
}
|
205
|
-
|
206
|
-
return data && data.length > 0 ? (
|
207
|
-
<div className={b('table')}>
|
208
|
-
<DataTable
|
209
|
-
columns={tableColumns}
|
210
|
-
data={data}
|
211
|
-
settings={TABLE_SETTINGS}
|
212
|
-
className={b('table')}
|
213
|
-
theme="yandex-cloud"
|
214
|
-
onSort={onSort}
|
215
|
-
sortOrder={stringToDataTableSortOrder(sortOrder)}
|
216
|
-
/>
|
217
|
-
</div>
|
218
|
-
) : (
|
219
|
-
data
|
220
|
-
);
|
221
|
-
};
|
222
|
-
|
223
|
-
return loading && !wasLoaded ? renderLoader() : <div className={b()}>{renderContent()}</div>;
|
224
|
-
}
|
225
|
-
|
226
|
-
const mapStateToProps = (state) => {
|
227
|
-
const {loading, data = {}, error, wasLoaded} = state.shardsWorkload;
|
228
|
-
const {autorefresh} = state.schema;
|
229
|
-
return {
|
230
|
-
loading,
|
231
|
-
data: data.result,
|
232
|
-
error,
|
233
|
-
currentSchemaPath: state.schema?.currentSchema?.Path,
|
234
|
-
autorefresh,
|
235
|
-
wasLoaded,
|
236
|
-
};
|
237
|
-
};
|
238
|
-
|
239
|
-
const mapDispatchToProps = {
|
240
|
-
sendShardQuery,
|
241
|
-
setCurrentSchemaPath,
|
242
|
-
getSchema,
|
243
|
-
setShardQueryOptions,
|
244
|
-
};
|
245
|
-
|
246
|
-
export default connect(mapStateToProps, mapDispatchToProps)(TopShards);
|
@@ -1,101 +0,0 @@
|
|
1
|
-
import '../../services/api';
|
2
|
-
|
3
|
-
import {parseQueryAPIExecuteResponse} from '../../utils/query';
|
4
|
-
|
5
|
-
import {createRequestActionTypes, createApiRequest} from '../utils';
|
6
|
-
|
7
|
-
const SEND_SHARD_QUERY = createRequestActionTypes('query', 'SEND_SHARD_QUERY');
|
8
|
-
const SET_SHARD_QUERY_OPTIONS = 'query/SET_SHARD_QUERY_OPTIONS';
|
9
|
-
|
10
|
-
const initialState = {
|
11
|
-
loading: false,
|
12
|
-
wasLoaded: false,
|
13
|
-
};
|
14
|
-
|
15
|
-
function formatSortOrder({columnId, order}) {
|
16
|
-
return `${columnId} ${order}`;
|
17
|
-
}
|
18
|
-
|
19
|
-
function createShardQuery(path, sortOrder, tenantName) {
|
20
|
-
const orderBy = Array.isArray(sortOrder) ?
|
21
|
-
`ORDER BY ${sortOrder.map(formatSortOrder).join(', ')}` :
|
22
|
-
'';
|
23
|
-
|
24
|
-
const pathSelect = tenantName ?
|
25
|
-
`CAST(SUBSTRING(CAST(Path AS String), ${tenantName.length}) AS Utf8) AS Path` :
|
26
|
-
'Path';
|
27
|
-
|
28
|
-
return `SELECT
|
29
|
-
${pathSelect},
|
30
|
-
TabletId,
|
31
|
-
CPUCores,
|
32
|
-
DataSize
|
33
|
-
FROM \`.sys/partition_stats\`
|
34
|
-
WHERE
|
35
|
-
Path='${path}'
|
36
|
-
OR Path LIKE '${path}/%'
|
37
|
-
${orderBy}
|
38
|
-
LIMIT 20`;
|
39
|
-
}
|
40
|
-
|
41
|
-
const queryAction = 'execute-scan';
|
42
|
-
|
43
|
-
const shardsWorkload = (state = initialState, action) => {
|
44
|
-
switch (action.type) {
|
45
|
-
case SEND_SHARD_QUERY.REQUEST: {
|
46
|
-
return {
|
47
|
-
...state,
|
48
|
-
loading: true,
|
49
|
-
error: undefined,
|
50
|
-
};
|
51
|
-
}
|
52
|
-
case SEND_SHARD_QUERY.SUCCESS: {
|
53
|
-
return {
|
54
|
-
...state,
|
55
|
-
data: action.data,
|
56
|
-
loading: false,
|
57
|
-
error: undefined,
|
58
|
-
wasLoaded: true,
|
59
|
-
};
|
60
|
-
}
|
61
|
-
// 401 Unauthorized error is handled by GenericAPI
|
62
|
-
case SEND_SHARD_QUERY.FAILURE: {
|
63
|
-
return {
|
64
|
-
...state,
|
65
|
-
error: action.error || 'Unauthorized',
|
66
|
-
loading: false,
|
67
|
-
};
|
68
|
-
}
|
69
|
-
case SET_SHARD_QUERY_OPTIONS:
|
70
|
-
return {
|
71
|
-
...state,
|
72
|
-
...action.data,
|
73
|
-
};
|
74
|
-
default:
|
75
|
-
return state;
|
76
|
-
}
|
77
|
-
};
|
78
|
-
|
79
|
-
export const sendShardQuery = ({database, path = '', sortOrder}) => {
|
80
|
-
return createApiRequest({
|
81
|
-
request: window.api.sendQuery({
|
82
|
-
schema: 'modern',
|
83
|
-
query: createShardQuery(path, sortOrder, database),
|
84
|
-
database,
|
85
|
-
action: queryAction,
|
86
|
-
}, {
|
87
|
-
concurrentId: 'topShards',
|
88
|
-
}),
|
89
|
-
actions: SEND_SHARD_QUERY,
|
90
|
-
dataHandler: parseQueryAPIExecuteResponse,
|
91
|
-
});
|
92
|
-
};
|
93
|
-
|
94
|
-
export function setShardQueryOptions(options) {
|
95
|
-
return {
|
96
|
-
type: SET_SHARD_QUERY_OPTIONS,
|
97
|
-
data: options,
|
98
|
-
};
|
99
|
-
}
|
100
|
-
|
101
|
-
export default shardsWorkload;
|