ydb-embedded-ui 4.19.3 → 4.20.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +16 -0
- package/dist/components/LinkToSchemaObject/LinkToSchemaObject.tsx +20 -0
- package/dist/components/QueryExecutionStatus/QueryExecutionStatus.tsx +3 -2
- package/dist/components/UsageLabel/UsageLabel.scss +6 -0
- package/dist/components/UsageLabel/UsageLabel.tsx +22 -0
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +13 -8
- package/dist/containers/AsideNavigation/i18n/en.json +13 -0
- package/dist/containers/AsideNavigation/i18n/index.ts +11 -0
- package/dist/containers/AsideNavigation/i18n/ru.json +13 -0
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +74 -68
- package/dist/containers/Node/NodeStructure/Vdisk.tsx +9 -33
- package/dist/containers/Nodes/Nodes.tsx +10 -2
- package/dist/containers/Nodes/getNodesColumns.tsx +206 -122
- package/dist/containers/Storage/Storage.tsx +9 -2
- package/dist/containers/Storage/utils/index.ts +1 -22
- package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +2 -3
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +0 -1
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +4 -2
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +1 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckDetails.tsx +8 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx +11 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/IssuesViewer/IssueTree.tsx +0 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +3 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TenantCpu.tsx +21 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx +53 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx +53 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx +85 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx +53 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TenantMemory.tsx +9 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx +55 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +40 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +35 -19
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx +53 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx +15 -7
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +3 -3
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +3 -3
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +0 -2
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +13 -61
- package/dist/containers/Tenant/Diagnostics/TopQueries/getTopQueriesColumns.tsx +82 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +18 -97
- package/dist/containers/Tenant/Diagnostics/TopShards/getTopShardsColumns.tsx +138 -0
- package/dist/containers/Tenant/Info/ExternalTable/ExternalTable.tsx +2 -4
- package/dist/containers/Tenant/Query/ExecuteResult/{ExecuteResult.js → ExecuteResult.tsx} +51 -31
- package/dist/containers/Tenant/Query/Issues/Issues.tsx +4 -6
- package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.tsx +1 -1
- package/dist/containers/Tenant/utils/paneVisibilityToggleHelpers.tsx +1 -1
- package/dist/routes.ts +6 -0
- package/dist/store/reducers/{executeTopQueries.ts → executeTopQueries/executeTopQueries.ts} +23 -75
- package/dist/{types/store/executeTopQueries.ts → store/reducers/executeTopQueries/types.ts} +3 -7
- package/dist/store/reducers/executeTopQueries/utils.ts +36 -0
- package/dist/store/reducers/index.ts +12 -2
- package/dist/store/reducers/nodes/types.ts +1 -0
- package/dist/store/reducers/nodes/utils.ts +16 -6
- package/dist/store/reducers/{shardsWorkload.ts → shardsWorkload/shardsWorkload.ts} +5 -11
- package/dist/{types/store/shardsWorkload.ts → store/reducers/shardsWorkload/types.ts} +3 -7
- package/dist/store/reducers/tenantOverview/topNodesByCpu/topNodesByCpu.ts +87 -0
- package/dist/store/reducers/tenantOverview/topNodesByCpu/types.ts +29 -0
- package/dist/store/reducers/tenantOverview/topNodesByLoad/topNodesByLoad.ts +87 -0
- package/dist/store/reducers/tenantOverview/topNodesByLoad/types.ts +29 -0
- package/dist/store/reducers/tenantOverview/topNodesByMemory/topNodesByMemory.ts +87 -0
- package/dist/store/reducers/tenantOverview/topNodesByMemory/types.ts +29 -0
- package/dist/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts +93 -0
- package/dist/store/reducers/tenantOverview/topQueries/types.ts +14 -0
- package/dist/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts +103 -0
- package/dist/store/reducers/tenantOverview/topShards/types.ts +14 -0
- package/dist/store/reducers/tenantOverview/topShards/utils.ts +3 -0
- package/dist/styles/mixins.scss +4 -0
- package/dist/types/additionalProps.ts +3 -1
- package/dist/types/api/compute.ts +1 -1
- package/dist/types/react-json-inspector.d.ts +21 -0
- package/dist/utils/diagnostics.ts +11 -0
- package/dist/utils/generateEvaluator.ts +21 -0
- package/package.json +1 -1
@@ -0,0 +1,87 @@
|
|
1
|
+
import type {Reducer} from 'redux';
|
2
|
+
|
3
|
+
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
|
4
|
+
import {createApiRequest, createRequestActionTypes} from '../../../utils';
|
5
|
+
import {prepareNodesData} from '../../nodes/utils';
|
6
|
+
import type {NodesApiRequestParams} from '../../nodes/types';
|
7
|
+
import type {TopNodesByLoadAction, TopNodesByLoadState, TopNodesByLoadStateSlice} from './types';
|
8
|
+
|
9
|
+
export const FETCH_TOP_NODES_BY_LOAD = createRequestActionTypes(
|
10
|
+
'topNodesByLoad',
|
11
|
+
'FETCH_TOP_NODES_BY_LOAD',
|
12
|
+
);
|
13
|
+
const SET_DATA_WAS_NOT_LOADED = 'topNodesByLoad/SET_DATA_WAS_NOT_LOADED';
|
14
|
+
|
15
|
+
const initialState = {
|
16
|
+
loading: false,
|
17
|
+
wasLoaded: false,
|
18
|
+
};
|
19
|
+
|
20
|
+
export const topNodesByLoad: Reducer<TopNodesByLoadState, TopNodesByLoadAction> = (
|
21
|
+
state = initialState,
|
22
|
+
action,
|
23
|
+
) => {
|
24
|
+
switch (action.type) {
|
25
|
+
case FETCH_TOP_NODES_BY_LOAD.REQUEST: {
|
26
|
+
return {
|
27
|
+
...state,
|
28
|
+
loading: true,
|
29
|
+
};
|
30
|
+
}
|
31
|
+
case FETCH_TOP_NODES_BY_LOAD.SUCCESS: {
|
32
|
+
return {
|
33
|
+
...state,
|
34
|
+
data: action.data?.Nodes,
|
35
|
+
loading: false,
|
36
|
+
wasLoaded: true,
|
37
|
+
error: undefined,
|
38
|
+
};
|
39
|
+
}
|
40
|
+
case FETCH_TOP_NODES_BY_LOAD.FAILURE: {
|
41
|
+
if (action.error?.isCancelled) {
|
42
|
+
return state;
|
43
|
+
}
|
44
|
+
|
45
|
+
return {
|
46
|
+
...state,
|
47
|
+
error: action.error,
|
48
|
+
loading: false,
|
49
|
+
};
|
50
|
+
}
|
51
|
+
case SET_DATA_WAS_NOT_LOADED: {
|
52
|
+
return {
|
53
|
+
...state,
|
54
|
+
wasLoaded: false,
|
55
|
+
};
|
56
|
+
}
|
57
|
+
default:
|
58
|
+
return state;
|
59
|
+
}
|
60
|
+
};
|
61
|
+
|
62
|
+
const concurrentId = 'getTopNodesByLoad';
|
63
|
+
|
64
|
+
export function getTopNodesByLoad({
|
65
|
+
type = 'any',
|
66
|
+
sortOrder = -1,
|
67
|
+
sortValue = 'LoadAverage',
|
68
|
+
limit = TENANT_OVERVIEW_TABLES_LIMIT,
|
69
|
+
...params
|
70
|
+
}: NodesApiRequestParams) {
|
71
|
+
return createApiRequest({
|
72
|
+
request: window.api.getNodes(
|
73
|
+
{type, sortOrder, sortValue, limit, ...params},
|
74
|
+
{concurrentId},
|
75
|
+
),
|
76
|
+
actions: FETCH_TOP_NODES_BY_LOAD,
|
77
|
+
dataHandler: prepareNodesData,
|
78
|
+
});
|
79
|
+
}
|
80
|
+
|
81
|
+
export const selectTopNodesByLoad = (state: TopNodesByLoadStateSlice) => state.topNodesByLoad.data;
|
82
|
+
|
83
|
+
export const setDataWasNotLoaded = () => {
|
84
|
+
return {
|
85
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
86
|
+
} as const;
|
87
|
+
};
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import type {IResponseError} from '../../../../types/api/error';
|
2
|
+
import type {ApiRequestAction} from '../../../utils';
|
3
|
+
import type {NodesPreparedEntity} from '../../nodes/types';
|
4
|
+
import {FETCH_TOP_NODES_BY_LOAD, setDataWasNotLoaded} from './topNodesByLoad';
|
5
|
+
|
6
|
+
export interface TopNodesByLoadState {
|
7
|
+
loading: boolean;
|
8
|
+
wasLoaded: boolean;
|
9
|
+
data?: NodesPreparedEntity[];
|
10
|
+
error?: IResponseError;
|
11
|
+
}
|
12
|
+
|
13
|
+
export interface TopNodesByLoadHandledResponse {
|
14
|
+
Nodes?: NodesPreparedEntity[];
|
15
|
+
}
|
16
|
+
|
17
|
+
type TopNodesByLoadApiRequestAction = ApiRequestAction<
|
18
|
+
typeof FETCH_TOP_NODES_BY_LOAD,
|
19
|
+
TopNodesByLoadHandledResponse,
|
20
|
+
IResponseError
|
21
|
+
>;
|
22
|
+
|
23
|
+
export type TopNodesByLoadAction =
|
24
|
+
| TopNodesByLoadApiRequestAction
|
25
|
+
| ReturnType<typeof setDataWasNotLoaded>;
|
26
|
+
|
27
|
+
export interface TopNodesByLoadStateSlice {
|
28
|
+
topNodesByLoad: TopNodesByLoadState;
|
29
|
+
}
|
@@ -0,0 +1,87 @@
|
|
1
|
+
import type {Reducer} from 'redux';
|
2
|
+
|
3
|
+
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
|
4
|
+
import {createApiRequest, createRequestActionTypes} from '../../../utils';
|
5
|
+
import {prepareNodesData} from '../../nodes/utils';
|
6
|
+
import type {NodesApiRequestParams} from '../../nodes/types';
|
7
|
+
import type {TopNodesByMemoryAction, TopNodesByMemoryState, TopNodesByMemorySlice} from './types';
|
8
|
+
|
9
|
+
export const FETCH_TOP_NODES_BY_MEMORY = createRequestActionTypes(
|
10
|
+
'topNodesByMemory',
|
11
|
+
'FETCH_TOP_NODES_BY_MEMORY',
|
12
|
+
);
|
13
|
+
const SET_DATA_WAS_NOT_LOADED = 'topNodesByMemory/SET_DATA_WAS_NOT_LOADED';
|
14
|
+
|
15
|
+
const initialState = {
|
16
|
+
loading: false,
|
17
|
+
wasLoaded: false,
|
18
|
+
};
|
19
|
+
|
20
|
+
export const topNodesByMemory: Reducer<TopNodesByMemoryState, TopNodesByMemoryAction> = (
|
21
|
+
state = initialState,
|
22
|
+
action,
|
23
|
+
) => {
|
24
|
+
switch (action.type) {
|
25
|
+
case FETCH_TOP_NODES_BY_MEMORY.REQUEST: {
|
26
|
+
return {
|
27
|
+
...state,
|
28
|
+
loading: true,
|
29
|
+
};
|
30
|
+
}
|
31
|
+
case FETCH_TOP_NODES_BY_MEMORY.SUCCESS: {
|
32
|
+
return {
|
33
|
+
...state,
|
34
|
+
data: action.data?.Nodes,
|
35
|
+
loading: false,
|
36
|
+
wasLoaded: true,
|
37
|
+
error: undefined,
|
38
|
+
};
|
39
|
+
}
|
40
|
+
case FETCH_TOP_NODES_BY_MEMORY.FAILURE: {
|
41
|
+
if (action.error?.isCancelled) {
|
42
|
+
return state;
|
43
|
+
}
|
44
|
+
|
45
|
+
return {
|
46
|
+
...state,
|
47
|
+
error: action.error,
|
48
|
+
loading: false,
|
49
|
+
};
|
50
|
+
}
|
51
|
+
case SET_DATA_WAS_NOT_LOADED: {
|
52
|
+
return {
|
53
|
+
...state,
|
54
|
+
wasLoaded: false,
|
55
|
+
};
|
56
|
+
}
|
57
|
+
default:
|
58
|
+
return state;
|
59
|
+
}
|
60
|
+
};
|
61
|
+
|
62
|
+
const concurrentId = 'getTopNodeByMemory';
|
63
|
+
|
64
|
+
export function getTopNodesByMemory({
|
65
|
+
type = 'any',
|
66
|
+
sortOrder = -1,
|
67
|
+
sortValue = 'Memory',
|
68
|
+
limit = TENANT_OVERVIEW_TABLES_LIMIT,
|
69
|
+
...params
|
70
|
+
}: NodesApiRequestParams) {
|
71
|
+
return createApiRequest({
|
72
|
+
request: window.api.getNodes(
|
73
|
+
{type, sortOrder, sortValue, limit, ...params},
|
74
|
+
{concurrentId},
|
75
|
+
),
|
76
|
+
actions: FETCH_TOP_NODES_BY_MEMORY,
|
77
|
+
dataHandler: prepareNodesData,
|
78
|
+
});
|
79
|
+
}
|
80
|
+
|
81
|
+
export const selectTopNodesByMemory = (state: TopNodesByMemorySlice) => state.topNodesByMemory.data;
|
82
|
+
|
83
|
+
export const setDataWasNotLoaded = () => {
|
84
|
+
return {
|
85
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
86
|
+
} as const;
|
87
|
+
};
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import type {IResponseError} from '../../../../types/api/error';
|
2
|
+
import type {ApiRequestAction} from '../../../utils';
|
3
|
+
import type {NodesPreparedEntity} from '../../nodes/types';
|
4
|
+
import {FETCH_TOP_NODES_BY_MEMORY, setDataWasNotLoaded} from './topNodesByMemory';
|
5
|
+
|
6
|
+
export interface TopNodesByMemoryState {
|
7
|
+
loading: boolean;
|
8
|
+
wasLoaded: boolean;
|
9
|
+
data?: NodesPreparedEntity[];
|
10
|
+
error?: IResponseError;
|
11
|
+
}
|
12
|
+
|
13
|
+
export interface TopNodesByMemoryHandledResponse {
|
14
|
+
Nodes?: NodesPreparedEntity[];
|
15
|
+
}
|
16
|
+
|
17
|
+
type TopNodesByMemoryApiRequestAction = ApiRequestAction<
|
18
|
+
typeof FETCH_TOP_NODES_BY_MEMORY,
|
19
|
+
TopNodesByMemoryHandledResponse,
|
20
|
+
IResponseError
|
21
|
+
>;
|
22
|
+
|
23
|
+
export type TopNodesByMemoryAction =
|
24
|
+
| TopNodesByMemoryApiRequestAction
|
25
|
+
| ReturnType<typeof setDataWasNotLoaded>;
|
26
|
+
|
27
|
+
export interface TopNodesByMemorySlice {
|
28
|
+
topNodesByMemory: TopNodesByMemoryState;
|
29
|
+
}
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import type {Reducer} from 'redux';
|
2
|
+
|
3
|
+
import '../../../../services/api';
|
4
|
+
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
|
5
|
+
import {parseQueryAPIExecuteResponse} from '../../../../utils/query';
|
6
|
+
|
7
|
+
import {createRequestActionTypes, createApiRequest} from '../../../utils';
|
8
|
+
import type {TenantOverviewTopQueriesAction, TenantOverviewTopQueriesState} from './types';
|
9
|
+
|
10
|
+
export const FETCH_TENANT_OVERVIEW_TOP_QUERIES = createRequestActionTypes(
|
11
|
+
'tenantOverviewTopQueries',
|
12
|
+
'FETCH_TOP_QUERIES',
|
13
|
+
);
|
14
|
+
const SET_DATA_WAS_NOT_LOADED = 'tenantOverviewTopQueries/SET_DATA_WAS_NOT_LOADED';
|
15
|
+
|
16
|
+
const initialState = {
|
17
|
+
loading: false,
|
18
|
+
wasLoaded: false,
|
19
|
+
filters: {},
|
20
|
+
};
|
21
|
+
|
22
|
+
const getQueryText = (path: string) => {
|
23
|
+
return `
|
24
|
+
SELECT
|
25
|
+
CPUTime as CPUTimeUs,
|
26
|
+
QueryText,
|
27
|
+
FROM \`${path}/.sys/top_queries_by_cpu_time_one_hour\`
|
28
|
+
ORDER BY CPUTimeUs DESC
|
29
|
+
LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT}
|
30
|
+
`;
|
31
|
+
};
|
32
|
+
|
33
|
+
export const tenantOverviewTopQueries: Reducer<
|
34
|
+
TenantOverviewTopQueriesState,
|
35
|
+
TenantOverviewTopQueriesAction
|
36
|
+
> = (state = initialState, action) => {
|
37
|
+
switch (action.type) {
|
38
|
+
case FETCH_TENANT_OVERVIEW_TOP_QUERIES.REQUEST: {
|
39
|
+
return {
|
40
|
+
...state,
|
41
|
+
loading: true,
|
42
|
+
error: undefined,
|
43
|
+
};
|
44
|
+
}
|
45
|
+
case FETCH_TENANT_OVERVIEW_TOP_QUERIES.SUCCESS: {
|
46
|
+
return {
|
47
|
+
...state,
|
48
|
+
data: action.data,
|
49
|
+
loading: false,
|
50
|
+
error: undefined,
|
51
|
+
wasLoaded: true,
|
52
|
+
};
|
53
|
+
}
|
54
|
+
// 401 Unauthorized error is handled by GenericAPI
|
55
|
+
case FETCH_TENANT_OVERVIEW_TOP_QUERIES.FAILURE: {
|
56
|
+
return {
|
57
|
+
...state,
|
58
|
+
error: action.error || 'Unauthorized',
|
59
|
+
loading: false,
|
60
|
+
};
|
61
|
+
}
|
62
|
+
case SET_DATA_WAS_NOT_LOADED:
|
63
|
+
return {
|
64
|
+
...state,
|
65
|
+
wasLoaded: false,
|
66
|
+
};
|
67
|
+
default:
|
68
|
+
return state;
|
69
|
+
}
|
70
|
+
};
|
71
|
+
|
72
|
+
export const fetchTenantOverviewTopQueries = (database: string) =>
|
73
|
+
createApiRequest({
|
74
|
+
request: window.api.sendQuery(
|
75
|
+
{
|
76
|
+
schema: 'modern',
|
77
|
+
query: getQueryText(database),
|
78
|
+
database,
|
79
|
+
action: 'execute-scan',
|
80
|
+
},
|
81
|
+
{
|
82
|
+
concurrentId: 'executeTopQueries',
|
83
|
+
},
|
84
|
+
),
|
85
|
+
actions: FETCH_TENANT_OVERVIEW_TOP_QUERIES,
|
86
|
+
dataHandler: parseQueryAPIExecuteResponse,
|
87
|
+
});
|
88
|
+
|
89
|
+
export function setDataWasNotLoaded() {
|
90
|
+
return {
|
91
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
92
|
+
} as const;
|
93
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
|
2
|
+
import type {ApiRequestAction} from '../../../utils';
|
3
|
+
import {FETCH_TENANT_OVERVIEW_TOP_QUERIES, setDataWasNotLoaded} from './tenantOverviewTopQueries';
|
4
|
+
|
5
|
+
export interface TenantOverviewTopQueriesState {
|
6
|
+
loading: boolean;
|
7
|
+
wasLoaded: boolean;
|
8
|
+
data?: IQueryResult;
|
9
|
+
error?: QueryErrorResponse;
|
10
|
+
}
|
11
|
+
|
12
|
+
export type TenantOverviewTopQueriesAction =
|
13
|
+
| ApiRequestAction<typeof FETCH_TENANT_OVERVIEW_TOP_QUERIES, IQueryResult, QueryErrorResponse>
|
14
|
+
| ReturnType<typeof setDataWasNotLoaded>;
|
@@ -0,0 +1,103 @@
|
|
1
|
+
import type {Reducer} from 'redux';
|
2
|
+
|
3
|
+
import '../../../../services/api';
|
4
|
+
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
|
5
|
+
import {parseQueryAPIExecuteResponse} from '../../../../utils/query';
|
6
|
+
import {createRequestActionTypes, createApiRequest} from '../../../utils';
|
7
|
+
import {TenantOverviewTopShardsAction, TenantOverviewTopShardsState} from './types';
|
8
|
+
|
9
|
+
export const FETCH_TENANT_OVERVIEW_TOP_SHARDS = createRequestActionTypes(
|
10
|
+
'tenantOverviewTopShards',
|
11
|
+
'FETCH_TENANT_OVERVIEW_TOP_SHARDS',
|
12
|
+
);
|
13
|
+
const SET_DATA_WAS_NOT_LOADED = 'tenantOverviewTopShards/SET_DATA_WAS_NOT_LOADED';
|
14
|
+
|
15
|
+
const initialState = {
|
16
|
+
loading: false,
|
17
|
+
wasLoaded: false,
|
18
|
+
};
|
19
|
+
|
20
|
+
function createShardQuery(path: string, tenantName?: string) {
|
21
|
+
const pathSelect = tenantName
|
22
|
+
? `CAST(SUBSTRING(CAST(Path AS String), ${tenantName.length}) AS Utf8) AS Path`
|
23
|
+
: 'Path';
|
24
|
+
|
25
|
+
return `SELECT
|
26
|
+
${pathSelect},
|
27
|
+
TabletId,
|
28
|
+
CPUCores,
|
29
|
+
FROM \`.sys/partition_stats\`
|
30
|
+
WHERE
|
31
|
+
Path='${path}'
|
32
|
+
OR Path LIKE '${path}/%'
|
33
|
+
ORDER BY CPUCores DESC
|
34
|
+
LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT}`;
|
35
|
+
}
|
36
|
+
|
37
|
+
const queryAction = 'execute-scan';
|
38
|
+
|
39
|
+
export const tenantOverviewTopShards: Reducer<
|
40
|
+
TenantOverviewTopShardsState,
|
41
|
+
TenantOverviewTopShardsAction
|
42
|
+
> = (state = initialState, action) => {
|
43
|
+
switch (action.type) {
|
44
|
+
case FETCH_TENANT_OVERVIEW_TOP_SHARDS.REQUEST: {
|
45
|
+
return {
|
46
|
+
...state,
|
47
|
+
loading: true,
|
48
|
+
error: undefined,
|
49
|
+
};
|
50
|
+
}
|
51
|
+
case FETCH_TENANT_OVERVIEW_TOP_SHARDS.SUCCESS: {
|
52
|
+
return {
|
53
|
+
...state,
|
54
|
+
data: action.data,
|
55
|
+
loading: false,
|
56
|
+
error: undefined,
|
57
|
+
wasLoaded: true,
|
58
|
+
};
|
59
|
+
}
|
60
|
+
// 401 Unauthorized error is handled by GenericAPI
|
61
|
+
case FETCH_TENANT_OVERVIEW_TOP_SHARDS.FAILURE: {
|
62
|
+
if (action.error?.isCancelled) {
|
63
|
+
return state;
|
64
|
+
}
|
65
|
+
|
66
|
+
return {
|
67
|
+
...state,
|
68
|
+
error: action.error || 'Unauthorized',
|
69
|
+
loading: false,
|
70
|
+
};
|
71
|
+
}
|
72
|
+
case SET_DATA_WAS_NOT_LOADED:
|
73
|
+
return {
|
74
|
+
...state,
|
75
|
+
wasLoaded: false,
|
76
|
+
};
|
77
|
+
default:
|
78
|
+
return state;
|
79
|
+
}
|
80
|
+
};
|
81
|
+
|
82
|
+
export const sendTenantOverviewTopShardsQuery = (database: string, path = '') =>
|
83
|
+
createApiRequest({
|
84
|
+
request: window.api.sendQuery(
|
85
|
+
{
|
86
|
+
schema: 'modern',
|
87
|
+
query: createShardQuery(path, database),
|
88
|
+
database,
|
89
|
+
action: queryAction,
|
90
|
+
},
|
91
|
+
{
|
92
|
+
concurrentId: 'executeTopShards',
|
93
|
+
},
|
94
|
+
),
|
95
|
+
actions: FETCH_TENANT_OVERVIEW_TOP_SHARDS,
|
96
|
+
dataHandler: parseQueryAPIExecuteResponse,
|
97
|
+
});
|
98
|
+
|
99
|
+
export function setDataWasNotLoaded() {
|
100
|
+
return {
|
101
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
102
|
+
} as const;
|
103
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
|
2
|
+
import type {ApiRequestAction} from '../../../utils';
|
3
|
+
import {FETCH_TENANT_OVERVIEW_TOP_SHARDS, setDataWasNotLoaded} from './tenantOverviewTopShards';
|
4
|
+
|
5
|
+
export interface TenantOverviewTopShardsState {
|
6
|
+
loading: boolean;
|
7
|
+
wasLoaded: boolean;
|
8
|
+
data?: IQueryResult;
|
9
|
+
error?: QueryErrorResponse;
|
10
|
+
}
|
11
|
+
|
12
|
+
export type TenantOverviewTopShardsAction =
|
13
|
+
| ApiRequestAction<typeof FETCH_TENANT_OVERVIEW_TOP_SHARDS, IQueryResult, QueryErrorResponse>
|
14
|
+
| ReturnType<typeof setDataWasNotLoaded>;
|
package/dist/styles/mixins.scss
CHANGED
@@ -26,6 +26,8 @@ export interface AdditionalTenantsProps {
|
|
26
26
|
|
27
27
|
export type NodeAddress = Pick<TSystemStateInfo, 'Host' | 'Endpoints' | 'NodeId'>;
|
28
28
|
|
29
|
+
export type GetNodeRefFunc = (node?: NodeAddress) => string | null;
|
30
|
+
|
29
31
|
export interface AdditionalNodesProps extends Record<string, unknown> {
|
30
|
-
getNodeRef?:
|
32
|
+
getNodeRef?: GetNodeRefFunc;
|
31
33
|
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
declare module 'react-json-inspector' {
|
2
|
+
// This typing is sufficient for current use cases, but some types are incompelete
|
3
|
+
class JSONTree extends React.Component<{
|
4
|
+
data?: object;
|
5
|
+
search?: boolean;
|
6
|
+
searchOptions?: {
|
7
|
+
debounceTime?: number;
|
8
|
+
};
|
9
|
+
onClick?: ({path: string, key: string, value: object}) => void;
|
10
|
+
validateQuery?: (query: string) => boolean;
|
11
|
+
isExpanded?: (keypath: string) => boolean;
|
12
|
+
filterOptions?: {
|
13
|
+
cacheResults?: bool;
|
14
|
+
ignoreCase?: bool;
|
15
|
+
};
|
16
|
+
query?: string;
|
17
|
+
verboseShowOriginal?: boolean;
|
18
|
+
className?: string;
|
19
|
+
}> {}
|
20
|
+
export default JSONTree;
|
21
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import {ValueOf} from '../types/common';
|
2
|
+
|
3
|
+
export const TOP_SHARDS_SORT_VALUES = {
|
4
|
+
CPUCores: 'CPUCores',
|
5
|
+
DataSize: 'DataSize',
|
6
|
+
} as const;
|
7
|
+
|
8
|
+
export type TopShardsSortValue = ValueOf<typeof TOP_SHARDS_SORT_VALUES>;
|
9
|
+
|
10
|
+
export const isSortableTopShardsProperty = (value: string): value is TopShardsSortValue =>
|
11
|
+
Object.values(TOP_SHARDS_SORT_VALUES).includes(value as TopShardsSortValue);
|
@@ -0,0 +1,21 @@
|
|
1
|
+
export const generateEvaluator =
|
2
|
+
<OkLevel extends string, WarnLevel extends string, CritLevel extends string>(
|
3
|
+
warn: number,
|
4
|
+
crit: number,
|
5
|
+
levels: [OkLevel, WarnLevel, CritLevel],
|
6
|
+
) =>
|
7
|
+
(value: number) => {
|
8
|
+
if (0 <= value && value < warn) {
|
9
|
+
return levels[0];
|
10
|
+
}
|
11
|
+
|
12
|
+
if (warn <= value && value < crit) {
|
13
|
+
return levels[1];
|
14
|
+
}
|
15
|
+
|
16
|
+
if (crit <= value) {
|
17
|
+
return levels[2];
|
18
|
+
}
|
19
|
+
|
20
|
+
return undefined;
|
21
|
+
};
|