ydb-embedded-ui 6.10.2 → 6.11.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.
- package/dist/components/DeveloperUiLink/DeveloperUiLink.d.ts +8 -0
- package/dist/components/DeveloperUiLink/DeveloperUiLink.js +9 -0
- package/dist/components/DeveloperUiLink/DeveloperUiLink.scss +11 -0
- package/dist/components/NodeHostWrapper/NodeHostWrapper.js +9 -2
- package/dist/containers/Tablets/Tablets.js +5 -1
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +2 -3
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.js +5 -10
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.d.ts +1 -3
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.js +3 -3
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.d.ts +1 -2
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.js +28 -57
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +28 -3
- package/dist/containers/Tenant/Diagnostics/TopQueries/getTopQueriesColumns.js +5 -14
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +4 -14
- package/dist/containers/Tenant/Diagnostics/TopShards/getTopShardsColumns.js +5 -1
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.js +4 -4
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.js +15 -5
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +2 -5
- package/dist/containers/Tenant/Tenant.js +2 -2
- package/dist/store/reducers/executeTopQueries/executeTopQueries.js +1 -0
- package/dist/store/reducers/schema/schema.d.ts +13 -2
- package/dist/store/reducers/schema/schema.js +36 -21
- package/dist/types/api/schema/schema.d.ts +21 -0
- package/dist/utils/diagnostics.d.ts +21 -17
- package/dist/utils/diagnostics.js +28 -7
- package/dist/utils/monaco/yql/yql.completionItemProvider.js +1 -1
- package/package.json +1 -1
- package/dist/store/reducers/olapStats.d.ts +0 -5
- package/dist/store/reducers/olapStats.js +0 -31
@@ -0,0 +1,8 @@
|
|
1
|
+
import './DeveloperUiLink.scss';
|
2
|
+
interface DeveloperUiLinkProps {
|
3
|
+
className?: string;
|
4
|
+
visible?: boolean;
|
5
|
+
href: string;
|
6
|
+
}
|
7
|
+
export declare function DeveloperUiLink({ href, visible, className }: DeveloperUiLinkProps): import("react/jsx-runtime").JSX.Element;
|
8
|
+
export {};
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import { ArrowUpRightFromSquare } from '@gravity-ui/icons';
|
3
|
+
import { Button, Icon } from '@gravity-ui/uikit';
|
4
|
+
import { cn } from '../../utils/cn';
|
5
|
+
import './DeveloperUiLink.scss';
|
6
|
+
const b = cn('developer-ui-link');
|
7
|
+
export function DeveloperUiLink({ href, visible = false, className }) {
|
8
|
+
return (_jsx(Button, { size: "s", href: href, className: b({ visible }, className), target: "_blank", children: _jsx(Icon, { data: ArrowUpRightFromSquare }) }));
|
9
|
+
}
|
@@ -3,6 +3,7 @@ import { ArrowUpRightFromSquare } from '@gravity-ui/icons';
|
|
3
3
|
import { Button, Icon, PopoverBehavior } from '@gravity-ui/uikit';
|
4
4
|
import { getDefaultNodePath } from '../../containers/Node/NodePages';
|
5
5
|
import { cn } from '../../utils/cn';
|
6
|
+
import { createDeveloperUILinkWithNodeId } from '../../utils/developerUI/developerUI';
|
6
7
|
import { isUnavailableNode } from '../../utils/nodes';
|
7
8
|
import { CellWithPopover } from '../CellWithPopover/CellWithPopover';
|
8
9
|
import { EntityStatus } from '../EntityStatus/EntityStatus';
|
@@ -14,12 +15,18 @@ export const NodeHostWrapper = ({ node, getNodeRef }) => {
|
|
14
15
|
return _jsx("span", { children: "\u2014" });
|
15
16
|
}
|
16
17
|
const isNodeAvailable = !isUnavailableNode(node);
|
17
|
-
|
18
|
+
let nodeHref;
|
19
|
+
if (getNodeRef) {
|
20
|
+
nodeHref = getNodeRef(node) + 'internal';
|
21
|
+
}
|
22
|
+
else if (node.NodeId) {
|
23
|
+
nodeHref = createDeveloperUILinkWithNodeId(node.NodeId) + 'internal';
|
24
|
+
}
|
18
25
|
const nodePath = isNodeAvailable
|
19
26
|
? getDefaultNodePath(node.NodeId, {
|
20
27
|
tenantName: node.TenantName,
|
21
28
|
})
|
22
29
|
: undefined;
|
23
|
-
const additionalControls =
|
30
|
+
const additionalControls = nodeHref ? (_jsx(Button, { size: "s", href: nodeHref, className: b('external-button'), target: "_blank", children: _jsx(Icon, { data: ArrowUpRightFromSquare }) })) : null;
|
24
31
|
return (_jsx(CellWithPopover, { disabled: !isNodeAvailable, content: _jsx(NodeEndpointsTooltipContent, { data: node }), placement: ['top', 'bottom'], behavior: PopoverBehavior.Immediate, children: _jsx(EntityStatus, { name: node.Host, status: node.SystemState, path: nodePath, hasClipboardButton: true, additionalControls: additionalControls }) }));
|
25
32
|
};
|
@@ -3,12 +3,14 @@ import { ArrowsRotateRight } from '@gravity-ui/icons';
|
|
3
3
|
import { Icon, Label, Text } from '@gravity-ui/uikit';
|
4
4
|
import { skipToken } from '@reduxjs/toolkit/query';
|
5
5
|
import { ButtonWithConfirmDialog } from '../../components/ButtonWithConfirmDialog/ButtonWithConfirmDialog';
|
6
|
+
import { DeveloperUiLink } from '../../components/DeveloperUiLink/DeveloperUiLink';
|
6
7
|
import { EntityStatus } from '../../components/EntityStatus/EntityStatus';
|
7
8
|
import { ResponseError } from '../../components/Errors/ResponseError';
|
8
9
|
import { InternalLink } from '../../components/InternalLink';
|
9
10
|
import { ResizeableDataTable } from '../../components/ResizeableDataTable/ResizeableDataTable';
|
10
11
|
import { TableSkeleton } from '../../components/TableSkeleton/TableSkeleton';
|
11
12
|
import routes, { createHref } from '../../routes';
|
13
|
+
import { backend } from '../../store';
|
12
14
|
import { selectTabletsWithFqdn, tabletsApi } from '../../store/reducers/tablets';
|
13
15
|
import { ETabletState } from '../../types/api/tablet';
|
14
16
|
import { cn } from '../../utils/cn';
|
@@ -31,13 +33,15 @@ const columns = [
|
|
31
33
|
},
|
32
34
|
{
|
33
35
|
name: 'TabletId',
|
36
|
+
width: 230,
|
34
37
|
get header() {
|
35
38
|
return i18n('Tablet');
|
36
39
|
},
|
37
40
|
render: ({ row }) => {
|
41
|
+
var _a;
|
38
42
|
const tabletPath = row.TabletId &&
|
39
43
|
createHref(routes.tablet, { id: row.TabletId }, { nodeId: row.NodeId, type: row.Type });
|
40
|
-
return _jsx(
|
44
|
+
return (_jsx(EntityStatus, { name: (_a = row.TabletId) === null || _a === void 0 ? void 0 : _a.toString(), path: tabletPath, hasClipboardButton: true, showStatus: false, additionalControls: _jsx(DeveloperUiLink, { href: `${backend}/tablets?TabletID=${row.TabletId}` }) }));
|
41
45
|
},
|
42
46
|
},
|
43
47
|
{
|
@@ -6,7 +6,7 @@ import { Button, Card, Icon } from '@gravity-ui/uikit';
|
|
6
6
|
import { ResponseError } from '../../../../components/Errors/ResponseError';
|
7
7
|
import { ResizeableDataTable } from '../../../../components/ResizeableDataTable/ResizeableDataTable';
|
8
8
|
import { hotKeysApi } from '../../../../store/reducers/hotKeys/hotKeys';
|
9
|
-
import {
|
9
|
+
import { useGetSchemaQuery } from '../../../../store/reducers/schema/schema';
|
10
10
|
import { cn } from '../../../../utils/cn';
|
11
11
|
import { DEFAULT_TABLE_SETTINGS, IS_HOTKEYS_HELP_HIDDEN_KEY } from '../../../../utils/constants';
|
12
12
|
import { useSetting } from '../../../../utils/hooks';
|
@@ -41,8 +41,7 @@ export function HotKeys({ path }) {
|
|
41
41
|
var _a, _b;
|
42
42
|
const { currentData: data, isFetching, error } = hotKeysApi.useGetHotKeysQuery({ path });
|
43
43
|
const loading = isFetching && data === undefined;
|
44
|
-
const {
|
45
|
-
const schemaLoading = schemaIsFetching && schemaData === undefined;
|
44
|
+
const { data: schemaData, isLoading: schemaLoading } = useGetSchemaQuery({ path });
|
46
45
|
const keyColumnsIds = (_b = (_a = schemaData === null || schemaData === void 0 ? void 0 : schemaData.PathDescription) === null || _a === void 0 ? void 0 : _a.Table) === null || _b === void 0 ? void 0 : _b.KeyColumnNames;
|
47
46
|
const tableColumns = React.useMemo(() => {
|
48
47
|
return getHotKeysColumns(keyColumnsIds);
|
@@ -4,25 +4,20 @@ import { shallowEqual } from 'react-redux';
|
|
4
4
|
import { ResponseError } from '../../../../components/Errors/ResponseError';
|
5
5
|
import { TableIndexInfo } from '../../../../components/InfoViewer/schemaInfo';
|
6
6
|
import { Loader } from '../../../../components/Loader';
|
7
|
-
import { olapApi } from '../../../../store/reducers/olapStats';
|
8
7
|
import { overviewApi } from '../../../../store/reducers/overview/overview';
|
9
|
-
import {
|
8
|
+
import { selectSchemaMergedChildrenPaths, useGetSchemaQuery, } from '../../../../store/reducers/schema/schema';
|
10
9
|
import { EPathType } from '../../../../types/api/schema';
|
11
10
|
import { useAutoRefreshInterval, useTypedSelector } from '../../../../utils/hooks';
|
12
11
|
import { ExternalDataSourceInfo } from '../../Info/ExternalDataSource/ExternalDataSource';
|
13
12
|
import { ExternalTableInfo } from '../../Info/ExternalTable/ExternalTable';
|
14
13
|
import { ViewInfo } from '../../Info/View/View';
|
15
|
-
import {
|
14
|
+
import { isEntityWithMergedImplementation } from '../../utils/schema';
|
16
15
|
import { AsyncReplicationInfo } from './AsyncReplicationInfo';
|
17
16
|
import { ChangefeedInfo } from './ChangefeedInfo';
|
18
17
|
import { TableInfo } from './TableInfo';
|
19
18
|
import { TopicInfo } from './TopicInfo';
|
20
19
|
function Overview({ type, path }) {
|
21
20
|
const [autoRefreshInterval] = useAutoRefreshInterval();
|
22
|
-
const olapParams = isTableType(type) && isColumnEntityType(type) ? { path } : skipToken;
|
23
|
-
const { currentData: olapData, isFetching: olapIsFetching } = olapApi.useGetOlapStatsQuery(olapParams, { pollingInterval: autoRefreshInterval });
|
24
|
-
const olapStatsLoading = olapIsFetching && olapData === undefined;
|
25
|
-
const { result: olapStats } = olapData || { result: undefined };
|
26
21
|
const isEntityWithMergedImpl = isEntityWithMergedImplementation(type);
|
27
22
|
// shallowEqual prevents rerenders when new schema data is loaded
|
28
23
|
const mergedChildrenPaths = useTypedSelector((state) => selectSchemaMergedChildrenPaths(state, path, type), shallowEqual);
|
@@ -38,8 +33,8 @@ function Overview({ type, path }) {
|
|
38
33
|
});
|
39
34
|
const overviewLoading = isFetching && currentData === undefined;
|
40
35
|
const { data: rawData, additionalData } = currentData || {};
|
41
|
-
const { error: schemaError } =
|
42
|
-
const entityLoading = overviewLoading
|
36
|
+
const { error: schemaError } = useGetSchemaQuery({ path });
|
37
|
+
const entityLoading = overviewLoading;
|
43
38
|
const entityNotReady = isEntityWithMergedImpl && !mergedChildrenPaths;
|
44
39
|
const renderContent = () => {
|
45
40
|
var _a;
|
@@ -65,7 +60,7 @@ function Overview({ type, path }) {
|
|
65
60
|
[EPathType.EPathTypeView]: () => _jsx(ViewInfo, { data: data }),
|
66
61
|
[EPathType.EPathTypeReplication]: () => _jsx(AsyncReplicationInfo, { data: data }),
|
67
62
|
};
|
68
|
-
return (
|
63
|
+
return (type && ((_a = pathTypeToComponent[type]) === null || _a === void 0 ? void 0 : _a.call(pathTypeToComponent))) || _jsx(TableInfo, { data: data, type: type });
|
69
64
|
};
|
70
65
|
if (entityLoading || entityNotReady) {
|
71
66
|
return _jsx(Loader, { size: "m" });
|
@@ -1,10 +1,8 @@
|
|
1
|
-
import type { KeyValueRow } from '../../../../../types/api/query';
|
2
1
|
import type { EPathType, TEvDescribeSchemeResult } from '../../../../../types/api/schema';
|
3
2
|
import './TableInfo.scss';
|
4
3
|
interface TableInfoProps {
|
5
4
|
data?: TEvDescribeSchemeResult;
|
6
5
|
type?: EPathType;
|
7
|
-
olapStats?: KeyValueRow[];
|
8
6
|
}
|
9
|
-
export declare const TableInfo: ({ data, type
|
7
|
+
export declare const TableInfo: ({ data, type }: TableInfoProps) => import("react/jsx-runtime").JSX.Element;
|
10
8
|
export {};
|
@@ -7,8 +7,8 @@ import i18n from './i18n';
|
|
7
7
|
import { prepareTableInfo } from './prepareTableInfo';
|
8
8
|
import './TableInfo.scss';
|
9
9
|
const b = cn('ydb-diagnostics-table-info');
|
10
|
-
export const TableInfo = ({ data, type
|
10
|
+
export const TableInfo = ({ data, type }) => {
|
11
11
|
const title = _jsx(EntityTitle, { data: data === null || data === void 0 ? void 0 : data.PathDescription });
|
12
|
-
const { generalInfo
|
13
|
-
return (_jsxs("div", { className: b(), children: [_jsx(InfoViewer, { info: generalInfo, title: title, className: b('info-block'), renderEmptyState: () => _jsx("div", { className: b('title'), children: title }) }), _jsxs("div", { className: b('row'), children: [_jsx("div", { className: b('col'), children: tableStatsInfo.map((info, index) => (_jsx(InfoViewer, { info: info, title: index === 0 ? i18n('tableStats') : undefined, className: b('info-block'), renderEmptyState: () => null }, index))) }), tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (_jsxs("div", { className: b('col'), children: [_jsx(InfoViewer, { info: tabletMetricsInfo, title: i18n('tabletMetrics'), className: b('info-block'), renderEmptyState: () => null }), _jsx(InfoViewer, { info: partitionConfigInfo, title: i18n('partitionConfig'), className: b('info-block'), renderEmptyState: () => null })] })) : null] })] }));
|
12
|
+
const { generalInfo, tableStatsInfo, tabletMetricsInfo = [], partitionConfigInfo = [], } = React.useMemo(() => prepareTableInfo(data, type), [data, type]);
|
13
|
+
return (_jsxs("div", { className: b(), children: [_jsx(InfoViewer, { info: generalInfo, title: title, className: b('info-block'), renderEmptyState: () => _jsx("div", { className: b('title'), children: title }) }), _jsxs("div", { className: b('row'), children: [tableStatsInfo ? (_jsx("div", { className: b('col'), children: tableStatsInfo.map((info, index) => (_jsx(InfoViewer, { info: info, title: index === 0 ? i18n('tableStats') : undefined, className: b('info-block'), renderEmptyState: () => null }, index))) })) : null, tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (_jsxs("div", { className: b('col'), children: [_jsx(InfoViewer, { info: tabletMetricsInfo, title: i18n('tabletMetrics'), className: b('info-block'), renderEmptyState: () => null }), _jsx(InfoViewer, { info: partitionConfigInfo, title: i18n('partitionConfig'), className: b('info-block'), renderEmptyState: () => null })] })) : null] })] }));
|
14
14
|
};
|
@@ -1,9 +1,8 @@
|
|
1
1
|
import type { InfoViewerItem } from '../../../../../components/InfoViewer';
|
2
|
-
import type { KeyValueRow } from '../../../../../types/api/query';
|
3
2
|
import type { TEvDescribeSchemeResult } from '../../../../../types/api/schema';
|
4
3
|
import { EPathType } from '../../../../../types/api/schema';
|
5
4
|
/** Prepares data for Table, ColumnTable and ColumnStore */
|
6
|
-
export declare const prepareTableInfo: (data?: TEvDescribeSchemeResult, type?: EPathType
|
5
|
+
export declare const prepareTableInfo: (data?: TEvDescribeSchemeResult, type?: EPathType) => {
|
7
6
|
generalInfo?: undefined;
|
8
7
|
tableStatsInfo?: undefined;
|
9
8
|
tabletMetricsInfo?: undefined;
|
@@ -3,31 +3,10 @@ import { formatFollowerGroupItem, formatPartitionConfigItem, formatTableStatsIte
|
|
3
3
|
import { EPathType } from '../../../../../types/api/schema';
|
4
4
|
import { formatBytes, formatNumber } from '../../../../../utils/dataFormatters/dataFormatters';
|
5
5
|
import { formatDurationToShortTimeFormat } from '../../../../../utils/timeParsers';
|
6
|
-
import { isNumeric } from '../../../../../utils/utils';
|
7
6
|
const isInStoreColumnTable = (table) => {
|
8
7
|
// SchemaPresetId could be 0
|
9
8
|
return table.SchemaPresetName && table.SchemaPresetId !== undefined;
|
10
9
|
};
|
11
|
-
const prepareOlapStats = (olapStats) => {
|
12
|
-
var _a, _b, _c;
|
13
|
-
const Bytes = olapStats === null || olapStats === void 0 ? void 0 : olapStats.reduce((acc, el) => {
|
14
|
-
const value = isNumeric(el.Bytes) ? Number(el.Bytes) : 0;
|
15
|
-
return acc + value;
|
16
|
-
}, 0);
|
17
|
-
const Rows = olapStats === null || olapStats === void 0 ? void 0 : olapStats.reduce((acc, el) => {
|
18
|
-
const value = isNumeric(el.Rows) ? Number(el.Rows) : 0;
|
19
|
-
return acc + value;
|
20
|
-
}, 0);
|
21
|
-
const tabletIds = olapStats === null || olapStats === void 0 ? void 0 : olapStats.reduce((acc, el) => {
|
22
|
-
acc.add(el.TabletId);
|
23
|
-
return acc;
|
24
|
-
}, new Set());
|
25
|
-
return [
|
26
|
-
{ label: 'PartCount', value: (_a = tabletIds === null || tabletIds === void 0 ? void 0 : tabletIds.size) !== null && _a !== void 0 ? _a : 0 },
|
27
|
-
{ label: 'RowCount', value: (_b = formatNumber(Rows)) !== null && _b !== void 0 ? _b : 0 },
|
28
|
-
{ label: 'DataSize', value: (_c = formatBytes(Bytes)) !== null && _c !== void 0 ? _c : 0 },
|
29
|
-
];
|
30
|
-
};
|
31
10
|
const prepareTTL = (ttl) => {
|
32
11
|
// ExpireAfterSeconds could be 0
|
33
12
|
if (ttl.Enabled && ttl.Enabled.ColumnName && ttl.Enabled.ExpireAfterSeconds !== undefined) {
|
@@ -97,7 +76,7 @@ const prepareTableGeneralInfo = (PartitionConfig, TTLSettings) => {
|
|
97
76
|
return generalTableInfo;
|
98
77
|
};
|
99
78
|
/** Prepares data for Table, ColumnTable and ColumnStore */
|
100
|
-
export const prepareTableInfo = (data, type
|
79
|
+
export const prepareTableInfo = (data, type) => {
|
101
80
|
if (!data) {
|
102
81
|
return {};
|
103
82
|
}
|
@@ -116,41 +95,33 @@ export const prepareTableInfo = (data, type, olapStats) => {
|
|
116
95
|
break;
|
117
96
|
}
|
118
97
|
}
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
RowUpdates,
|
147
|
-
RowDeletes,
|
148
|
-
RowReads,
|
149
|
-
RangeReads,
|
150
|
-
RangeReadRows,
|
151
|
-
}),
|
152
|
-
];
|
153
|
-
}
|
98
|
+
const tableStatsInfo = [
|
99
|
+
formatObject(formatTableStatsItem, {
|
100
|
+
PartCount,
|
101
|
+
RowCount,
|
102
|
+
DataSize,
|
103
|
+
IndexSize,
|
104
|
+
}),
|
105
|
+
formatObject(formatTableStatsItem, {
|
106
|
+
LastAccessTime,
|
107
|
+
LastUpdateTime,
|
108
|
+
}),
|
109
|
+
formatObject(formatTableStatsItem, {
|
110
|
+
ImmediateTxCompleted,
|
111
|
+
PlannedTxCompleted,
|
112
|
+
TxRejectedByOverload,
|
113
|
+
TxRejectedBySpace,
|
114
|
+
TxCompleteLagMsec,
|
115
|
+
InFlightTxCount,
|
116
|
+
}),
|
117
|
+
formatObject(formatTableStatsItem, {
|
118
|
+
RowUpdates,
|
119
|
+
RowDeletes,
|
120
|
+
RowReads,
|
121
|
+
RangeReads,
|
122
|
+
RangeReadRows,
|
123
|
+
}),
|
124
|
+
];
|
154
125
|
//@ts-expect-error
|
155
126
|
const tabletMetricsInfo = formatObject(formatTabletMetricsItem, TabletMetrics);
|
156
127
|
let partitionConfigInfo = [];
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import { Loader } from '@gravity-ui/uikit';
|
3
3
|
import { EntityStatus } from '../../../../components/EntityStatus/EntityStatus';
|
4
|
+
import { useGetSchemaQuery } from '../../../../store/reducers/schema/schema';
|
4
5
|
import { TENANT_METRICS_TABS_IDS } from '../../../../store/reducers/tenant/constants';
|
5
6
|
import { tenantApi } from '../../../../store/reducers/tenant/tenant';
|
6
7
|
import { calculateTenantMetrics } from '../../../../store/reducers/tenants/utils';
|
@@ -16,7 +17,7 @@ import { TenantStorage } from './TenantStorage/TenantStorage';
|
|
16
17
|
import { b } from './utils';
|
17
18
|
import './TenantOverview.scss';
|
18
19
|
export function TenantOverview({ tenantName, additionalTenantProps, additionalNodesProps, }) {
|
19
|
-
var _a;
|
20
|
+
var _a, _b, _c;
|
20
21
|
const { metricsTab } = useTypedSelector((state) => state.tenant);
|
21
22
|
const [autoRefreshInterval] = useAutoRefreshInterval();
|
22
23
|
const { currentData: tenant, isFetching } = tenantApi.useGetTenantInfoQuery({ path: tenantName }, {
|
@@ -25,7 +26,31 @@ export function TenantOverview({ tenantName, additionalTenantProps, additionalNo
|
|
25
26
|
const tenantLoading = isFetching && tenant === undefined;
|
26
27
|
const { Name, Type, Overall } = tenant || {};
|
27
28
|
const tenantType = mapDatabaseTypeToDBName(Type);
|
28
|
-
|
29
|
+
// FIXME: remove after correct data is added to tenantInfo
|
30
|
+
const { data: tenantSchemaData } = useGetSchemaQuery({ path: tenantName });
|
31
|
+
const { Tables, Topics } = ((_b = (_a = tenantSchemaData === null || tenantSchemaData === void 0 ? void 0 : tenantSchemaData.PathDescription) === null || _a === void 0 ? void 0 : _a.DomainDescription) === null || _b === void 0 ? void 0 : _b.DiskSpaceUsage) || {};
|
32
|
+
const usedTabletStorage = [
|
33
|
+
Tables === null || Tables === void 0 ? void 0 : Tables.TotalSize,
|
34
|
+
Topics === null || Topics === void 0 ? void 0 : Topics.AccountSize,
|
35
|
+
Topics === null || Topics === void 0 ? void 0 : Topics.DataSize,
|
36
|
+
Topics === null || Topics === void 0 ? void 0 : Topics.ReserveSize,
|
37
|
+
Topics === null || Topics === void 0 ? void 0 : Topics.UsedReserveSize,
|
38
|
+
].reduce((sum, current) => {
|
39
|
+
if (current) {
|
40
|
+
return sum + Number(current);
|
41
|
+
}
|
42
|
+
return sum;
|
43
|
+
}, 0);
|
44
|
+
const tenantData = {
|
45
|
+
...tenant,
|
46
|
+
Metrics: {
|
47
|
+
...tenant === null || tenant === void 0 ? void 0 : tenant.Metrics,
|
48
|
+
// Replace incorrect tenant metric with correct value
|
49
|
+
Storage: String(usedTabletStorage),
|
50
|
+
},
|
51
|
+
};
|
52
|
+
// === === ===
|
53
|
+
const { blobStorage, tabletStorage, blobStorageLimit, tabletStorageLimit, poolsStats, memoryStats, blobStorageStats, tabletStorageStats, } = calculateTenantMetrics(tenantData);
|
29
54
|
const storageMetrics = {
|
30
55
|
blobStorageUsed: blobStorage,
|
31
56
|
blobStorageLimit,
|
@@ -57,5 +82,5 @@ export function TenantOverview({ tenantName, additionalTenantProps, additionalNo
|
|
57
82
|
if (tenantLoading) {
|
58
83
|
return (_jsx("div", { className: b('loader'), children: _jsx(Loader, { size: "m" }) }));
|
59
84
|
}
|
60
|
-
return (_jsxs("div", { className: b(), children: [_jsxs("div", { className: b('info'), children: [_jsx("div", { className: b('top-label'), children: tenantType }), _jsxs("div", { className: b('top'), children: [renderName(), (
|
85
|
+
return (_jsxs("div", { className: b(), children: [_jsxs("div", { className: b('info'), children: [_jsx("div", { className: b('top-label'), children: tenantType }), _jsxs("div", { className: b('top'), children: [renderName(), (_c = additionalTenantProps === null || additionalTenantProps === void 0 ? void 0 : additionalTenantProps.getMonitoringLink) === null || _c === void 0 ? void 0 : _c.call(additionalTenantProps, Name, Type)] }), _jsx(MetricsCards, { poolsCpuStats: poolsStats, memoryStats: memoryStats, blobStorageStats: blobStorageStats, tabletStorageStats: tabletStorageStats, tenantName: tenantName })] }), renderTabContent()] }));
|
61
86
|
}
|
@@ -3,26 +3,17 @@ import DataTable from '@gravity-ui/react-data-table';
|
|
3
3
|
import { OneLineQueryWithPopover, TruncatedQuery, } from '../../../../components/TruncatedQuery/TruncatedQuery';
|
4
4
|
import { cn } from '../../../../utils/cn';
|
5
5
|
import { formatDateTime, formatNumber } from '../../../../utils/dataFormatters/dataFormatters';
|
6
|
+
import { TOP_QUERIES_COLUMNS_IDS } from '../../../../utils/diagnostics';
|
6
7
|
import { generateHash } from '../../../../utils/generateHash';
|
7
|
-
import { parseUsToMs } from '../../../../utils/timeParsers';
|
8
|
+
import { formatToMs, parseUsToMs } from '../../../../utils/timeParsers';
|
8
9
|
import { MAX_QUERY_HEIGHT } from '../../utils/constants';
|
9
10
|
import './TopQueries.scss';
|
10
11
|
const b = cn('kv-top-queries');
|
11
12
|
export const TOP_QUERIES_COLUMNS_WIDTH_LS_KEY = 'topQueriesColumnsWidth';
|
12
|
-
const TOP_QUERIES_COLUMNS_IDS = {
|
13
|
-
CPUTimeUs: 'CPUTimeUs',
|
14
|
-
QueryText: 'QueryText',
|
15
|
-
EndTime: 'EndTime',
|
16
|
-
ReadRows: 'ReadRows',
|
17
|
-
ReadBytes: 'ReadBytes',
|
18
|
-
UserSID: 'UserSID',
|
19
|
-
OneLineQueryText: 'OneLineQueryText',
|
20
|
-
QueryHash: 'QueryHash',
|
21
|
-
Duration: 'Duration',
|
22
|
-
};
|
23
13
|
const cpuTimeUsColumn = {
|
24
14
|
name: TOP_QUERIES_COLUMNS_IDS.CPUTimeUs,
|
25
15
|
sortAccessor: (row) => Number(row.CPUTimeUs),
|
16
|
+
render: ({ row }) => { var _a; return formatToMs(parseUsToMs((_a = row.CPUTimeUs) !== null && _a !== void 0 ? _a : undefined)); },
|
26
17
|
width: 120,
|
27
18
|
align: DataTable.RIGHT,
|
28
19
|
sortable: false,
|
@@ -78,8 +69,8 @@ const queryHashColumn = {
|
|
78
69
|
};
|
79
70
|
const durationColumn = {
|
80
71
|
name: TOP_QUERIES_COLUMNS_IDS.Duration,
|
81
|
-
header: 'Duration
|
82
|
-
render: ({ row }) => { var _a; return
|
72
|
+
header: 'Duration',
|
73
|
+
render: ({ row }) => { var _a; return formatToMs(parseUsToMs((_a = row.Duration) !== null && _a !== void 0 ? _a : undefined)); },
|
83
74
|
sortAccessor: (row) => Number(row.Duration),
|
84
75
|
align: DataTable.RIGHT,
|
85
76
|
width: 150,
|
@@ -9,7 +9,7 @@ import { EShardsWorkloadMode } from '../../../../store/reducers/shardsWorkload/t
|
|
9
9
|
import { cn } from '../../../../utils/cn';
|
10
10
|
import { DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS } from '../../../../utils/constants';
|
11
11
|
import { formatDateTime } from '../../../../utils/dataFormatters/dataFormatters';
|
12
|
-
import { isSortableTopShardsProperty } from '../../../../utils/diagnostics';
|
12
|
+
import { TOP_SHARD_COLUMNS_IDS, isSortableTopShardsProperty } from '../../../../utils/diagnostics';
|
13
13
|
import { useAutoRefreshInterval, useTypedDispatch, useTypedSelector } from '../../../../utils/hooks';
|
14
14
|
import { parseQueryErrorToString } from '../../../../utils/query';
|
15
15
|
import { isColumnEntityType } from '../../utils/schema';
|
@@ -25,16 +25,6 @@ const TABLE_SETTINGS = {
|
|
25
25
|
disableSortReset: true,
|
26
26
|
defaultOrder: DataTable.DESCENDING,
|
27
27
|
};
|
28
|
-
const tableColumnsNames = {
|
29
|
-
TabletId: 'TabletId',
|
30
|
-
CPUCores: 'CPUCores',
|
31
|
-
DataSize: 'DataSize',
|
32
|
-
Path: 'Path',
|
33
|
-
NodeId: 'NodeId',
|
34
|
-
PeakTime: 'PeakTime',
|
35
|
-
InFlightTxCount: 'InFlightTxCount',
|
36
|
-
IntervalEnd: 'IntervalEnd',
|
37
|
-
};
|
38
28
|
function prepareDateTimeValue(value) {
|
39
29
|
if (!value) {
|
40
30
|
return '–';
|
@@ -83,7 +73,7 @@ export const TopShards = ({ tenantName, path, type }) => {
|
|
83
73
|
}
|
84
74
|
return defaultValue;
|
85
75
|
});
|
86
|
-
const [sortOrder, setSortOrder] = React.useState(
|
76
|
+
const [sortOrder, setSortOrder] = React.useState(TOP_SHARD_COLUMNS_IDS.CPUCores);
|
87
77
|
const { data: result, isFetching, error, } = shardApi.useSendShardQueryQuery({
|
88
78
|
database: tenantName,
|
89
79
|
path: path,
|
@@ -124,14 +114,14 @@ export const TopShards = ({ tenantName, path, type }) => {
|
|
124
114
|
if (filters.mode === EShardsWorkloadMode.History) {
|
125
115
|
// after NodeId
|
126
116
|
columns.splice(5, 0, {
|
127
|
-
name:
|
117
|
+
name: TOP_SHARD_COLUMNS_IDS.PeakTime,
|
128
118
|
render: ({ row }) => {
|
129
119
|
return prepareDateTimeValue(row.PeakTime);
|
130
120
|
},
|
131
121
|
sortable: false,
|
132
122
|
});
|
133
123
|
columns.push({
|
134
|
-
name:
|
124
|
+
name: TOP_SHARD_COLUMNS_IDS.IntervalEnd,
|
135
125
|
render: ({ row }) => {
|
136
126
|
return prepareDateTimeValue(row.IntervalEnd);
|
137
127
|
},
|
@@ -1,9 +1,12 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
2
|
import DataTable from '@gravity-ui/react-data-table';
|
3
|
+
import { DeveloperUiLink } from '../../../../components/DeveloperUiLink/DeveloperUiLink';
|
4
|
+
import { EntityStatus } from '../../../../components/EntityStatus/EntityStatus';
|
3
5
|
import { InternalLink } from '../../../../components/InternalLink';
|
4
6
|
import { LinkToSchemaObject } from '../../../../components/LinkToSchemaObject/LinkToSchemaObject';
|
5
7
|
import { UsageLabel } from '../../../../components/UsageLabel/UsageLabel';
|
6
8
|
import routes, { createHref } from '../../../../routes';
|
9
|
+
import { backend } from '../../../../store';
|
7
10
|
import { getLoadSeverityForShard } from '../../../../store/reducers/tenantOverview/topShards/utils';
|
8
11
|
import { formatNumber, roundToPrecision } from '../../../../utils/dataFormatters/dataFormatters';
|
9
12
|
import { getDefaultNodePath } from '../../../Node/NodePages';
|
@@ -61,10 +64,11 @@ const tabletIdColumn = {
|
|
61
64
|
name: TOP_SHARDS_COLUMNS_IDS.TabletId,
|
62
65
|
header: tableColumnsNames[TOP_SHARDS_COLUMNS_IDS.TabletId],
|
63
66
|
render: ({ row }) => {
|
67
|
+
var _a;
|
64
68
|
if (!row.TabletId) {
|
65
69
|
return '–';
|
66
70
|
}
|
67
|
-
return (_jsx(
|
71
|
+
return (_jsx(EntityStatus, { name: (_a = row.TabletId) === null || _a === void 0 ? void 0 : _a.toString(), path: createHref(routes.tablet, { id: row.TabletId }), hasClipboardButton: true, showStatus: false, additionalControls: _jsx(DeveloperUiLink, { href: `${backend}/tablets?TabletID=${row.TabletId}` }) }));
|
68
72
|
},
|
69
73
|
sortable: false,
|
70
74
|
width: 190,
|
@@ -13,7 +13,7 @@ import { LinkWithIcon } from '../../../components/LinkWithIcon/LinkWithIcon';
|
|
13
13
|
import { Loader } from '../../../components/Loader';
|
14
14
|
import SplitPane from '../../../components/SplitPane';
|
15
15
|
import routes, { createExternalUILink, createHref } from '../../../routes';
|
16
|
-
import {
|
16
|
+
import { setShowPreview, useGetSchemaQuery } from '../../../store/reducers/schema/schema';
|
17
17
|
import { TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID, TENANT_SUMMARY_TABS_IDS, } from '../../../store/reducers/tenant/constants';
|
18
18
|
import { setQueryTab, setSummaryTab, setTenantPage } from '../../../store/reducers/tenant/tenant';
|
19
19
|
import { EPathSubType, EPathType } from '../../../types/api/schema';
|
@@ -48,7 +48,7 @@ export function ObjectSummary({ type, subType, tenantName, path, onCollapseSumma
|
|
48
48
|
const queryParams = qs.parse(location.search, {
|
49
49
|
ignoreQueryPrefix: true,
|
50
50
|
});
|
51
|
-
const {
|
51
|
+
const { data: currentObjectData } = useGetSchemaQuery({ path });
|
52
52
|
const currentSchemaData = (_a = currentObjectData === null || currentObjectData === void 0 ? void 0 : currentObjectData.PathDescription) === null || _a === void 0 ? void 0 : _a.Self;
|
53
53
|
React.useEffect(() => {
|
54
54
|
const isTable = isTableType(type);
|
@@ -255,12 +255,12 @@ export function ObjectSummary({ type, subType, tenantName, path, onCollapseSumma
|
|
255
255
|
}
|
256
256
|
function ObjectTree({ tenantName, path }) {
|
257
257
|
var _a;
|
258
|
-
const {
|
258
|
+
const { data: tenantData = {}, isLoading } = useGetSchemaQuery({
|
259
259
|
path: tenantName,
|
260
260
|
});
|
261
261
|
const pathData = (_a = tenantData === null || tenantData === void 0 ? void 0 : tenantData.PathDescription) === null || _a === void 0 ? void 0 : _a.Self;
|
262
262
|
const [, setCurrentPath] = useQueryParam('schema', StringParam);
|
263
|
-
if (!pathData &&
|
263
|
+
if (!pathData && isLoading) {
|
264
264
|
// If Loader isn't wrapped with div, SplitPane doesn't calculate panes height correctly
|
265
265
|
return (_jsx("div", { children: _jsx(Loader, {}) }));
|
266
266
|
}
|
@@ -20,13 +20,23 @@ export function SchemaTree(props) {
|
|
20
20
|
const [parentPath, setParentPath] = React.useState('');
|
21
21
|
const [schemaTreeKey, setSchemaTreeKey] = React.useState('');
|
22
22
|
const fetchPath = async (path) => {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
let schemaData;
|
24
|
+
do {
|
25
|
+
const promise = dispatch(schemaApi.endpoints.getSchema.initiate({ path }, { forceRefetch: true }));
|
26
|
+
const { data, originalArgs } = await promise;
|
27
|
+
promise.unsubscribe();
|
28
|
+
// Check if the result from the current request is received. rtk-query may skip the current request and
|
29
|
+
// return data from a parallel request, due to the same cache key.
|
30
|
+
if ((originalArgs === null || originalArgs === void 0 ? void 0 : originalArgs.path) === path) {
|
31
|
+
schemaData = data === null || data === void 0 ? void 0 : data[path];
|
32
|
+
break;
|
33
|
+
}
|
34
|
+
// eslint-disable-next-line no-constant-condition
|
35
|
+
} while (true);
|
36
|
+
if (!schemaData) {
|
27
37
|
throw new Error(`no describe data about path ${path}`);
|
28
38
|
}
|
29
|
-
const { PathDescription: { Children = [] } = {} } =
|
39
|
+
const { PathDescription: { Children = [] } = {} } = schemaData;
|
30
40
|
const childItems = Children.map((childData) => {
|
31
41
|
const { Name = '', PathType, PathSubType } = childData;
|
32
42
|
return {
|
@@ -4,7 +4,7 @@ import DataTable from '@gravity-ui/react-data-table';
|
|
4
4
|
import { skipToken } from '@reduxjs/toolkit/query';
|
5
5
|
import { ResizeableDataTable } from '../../../../components/ResizeableDataTable/ResizeableDataTable';
|
6
6
|
import { TableSkeleton } from '../../../../components/TableSkeleton/TableSkeleton';
|
7
|
-
import {
|
7
|
+
import { useGetSchemaQuery } from '../../../../store/reducers/schema/schema';
|
8
8
|
import { viewSchemaApi } from '../../../../store/reducers/viewSchema/viewSchema';
|
9
9
|
import { DEFAULT_TABLE_SETTINGS } from '../../../../utils/constants';
|
10
10
|
import { isColumnEntityType, isExternalTableType, isRowTableType, isViewType, } from '../../utils/schema';
|
@@ -13,10 +13,7 @@ import { prepareSchemaData, prepareViewSchema } from './prepareData';
|
|
13
13
|
import { b } from './shared';
|
14
14
|
import './SchemaViewer.scss';
|
15
15
|
export const SchemaViewer = ({ type, path, tenantName, extended = false }) => {
|
16
|
-
const {
|
17
|
-
path,
|
18
|
-
});
|
19
|
-
const loading = isFetching && schemaData === undefined;
|
16
|
+
const { data: schemaData, isLoading: loading } = useGetSchemaQuery({ path });
|
20
17
|
const viewSchemaRequestParams = isViewType(type) ? { path, database: tenantName } : skipToken;
|
21
18
|
const { data: viewColumnsData, isLoading: isViewSchemaLoading } = viewSchemaApi.useGetViewSchemaQuery(viewSchemaRequestParams);
|
22
19
|
const tableData = React.useMemo(() => {
|
@@ -6,7 +6,7 @@ import { AccessDenied } from '../../components/Errors/403';
|
|
6
6
|
import { Loader } from '../../components/Loader';
|
7
7
|
import SplitPane from '../../components/SplitPane';
|
8
8
|
import { setHeaderBreadcrumbs } from '../../store/reducers/header/header';
|
9
|
-
import {
|
9
|
+
import { useGetSchemaQuery } from '../../store/reducers/schema/schema';
|
10
10
|
import { cn } from '../../utils/cn';
|
11
11
|
import { DEFAULT_IS_TENANT_SUMMARY_COLLAPSED, DEFAULT_SIZE_TENANT_KEY } from '../../utils/constants';
|
12
12
|
import { useTypedDispatch } from '../../utils/hooks';
|
@@ -47,7 +47,7 @@ export function Tenant(props) {
|
|
47
47
|
dispatch(setHeaderBreadcrumbs('tenant', { tenantName }));
|
48
48
|
}, [tenantName, dispatch]);
|
49
49
|
const path = schema !== null && schema !== void 0 ? schema : tenantName;
|
50
|
-
const {
|
50
|
+
const { data: currentItem, error, isLoading } = useGetSchemaQuery({ path });
|
51
51
|
const { PathType: currentPathType, PathSubType: currentPathSubType } = ((_a = currentItem === null || currentItem === void 0 ? void 0 : currentItem.PathDescription) === null || _a === void 0 ? void 0 : _a.Self) || {};
|
52
52
|
let showBlockingError = false;
|
53
53
|
if (error && typeof error === 'object' && 'status' in error) {
|
@@ -21,11 +21,22 @@ export declare const schemaApi: import("@reduxjs/toolkit/query").Api<import("@re
|
|
21
21
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<void, typeof import("../api")._NEVER, unknown, {}>, "All", unknown, "api">;
|
22
22
|
getSchema: import("@reduxjs/toolkit/query").QueryDefinition<{
|
23
23
|
path: string;
|
24
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<void, typeof import("../api")._NEVER, unknown, {}>, "All",
|
25
|
-
|
24
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<void, typeof import("../api")._NEVER, unknown, {}>, "All", {
|
25
|
+
[path: string]: TEvDescribeSchemeResult & {
|
26
|
+
partial?: boolean;
|
27
|
+
};
|
26
28
|
}, "api">;
|
27
29
|
}, "api", "All", typeof import("@reduxjs/toolkit/query").coreModuleName | typeof import("@reduxjs/toolkit/query/react").reactHooksModuleName>;
|
28
30
|
export declare const selectSchemaMergedChildrenPaths: Selector<RootState, string[] | undefined, [
|
29
31
|
string | undefined,
|
30
32
|
EPathType | undefined
|
31
33
|
]>;
|
34
|
+
export declare function useGetSchemaQuery({ path }: {
|
35
|
+
path: string;
|
36
|
+
}): {
|
37
|
+
data: (TEvDescribeSchemeResult & {
|
38
|
+
partial?: boolean;
|
39
|
+
}) | undefined;
|
40
|
+
isLoading: boolean;
|
41
|
+
error: unknown;
|
42
|
+
};
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import React from 'react';
|
1
2
|
import { createSelector } from '@reduxjs/toolkit';
|
2
3
|
import { isEntityWithMergedImplementation } from '../../../containers/Tenant/utils/schema';
|
3
4
|
import { api } from '../api';
|
@@ -44,42 +45,44 @@ export const schemaApi = api.injectEndpoints({
|
|
44
45
|
queryFn: async ({ path }, { signal }) => {
|
45
46
|
try {
|
46
47
|
const data = await window.api.getSchema({ path }, { signal });
|
47
|
-
return { data: data
|
48
|
+
return { data: data ? { [path]: data, ...getSchemaChildren(data) } : {} };
|
48
49
|
}
|
49
50
|
catch (error) {
|
50
51
|
return { error };
|
51
52
|
}
|
52
53
|
},
|
53
54
|
keepUnusedDataFor: Infinity,
|
54
|
-
|
55
|
-
const
|
56
|
-
|
57
|
-
return true;
|
58
|
-
}
|
59
|
-
return false;
|
55
|
+
serializeQueryArgs: ({ queryArgs: { path } }) => {
|
56
|
+
const parts = path.split('/');
|
57
|
+
return { path: parts[0] || parts[1] };
|
60
58
|
},
|
61
|
-
|
62
|
-
const { data } =
|
59
|
+
merge: (existing, incoming, { arg: { path } }) => {
|
60
|
+
const { [path]: data, ...children } = incoming;
|
63
61
|
if (data) {
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
const cachedData = schemaApi.endpoints.getSchema.select({ path: childPath })(state).data;
|
70
|
-
if (!cachedData) {
|
71
|
-
// not full data, but it contains PathType, which ensures seamless switch between nodes
|
72
|
-
dispatch(schemaApi.util.upsertQueryData('getSchema', { path: childPath }, { PathDescription: { Self: child }, partial: true }));
|
73
|
-
}
|
74
|
-
}
|
62
|
+
return {
|
63
|
+
...children,
|
64
|
+
...existing,
|
65
|
+
[path]: data,
|
66
|
+
};
|
75
67
|
}
|
68
|
+
return existing;
|
76
69
|
},
|
77
70
|
}),
|
78
71
|
}),
|
79
72
|
overrideExisting: 'throw',
|
80
73
|
});
|
74
|
+
function getSchemaChildren(data) {
|
75
|
+
const children = {};
|
76
|
+
const { PathDescription: { Children = [] } = {}, Path: path } = data;
|
77
|
+
for (const child of Children) {
|
78
|
+
const { Name = '' } = child;
|
79
|
+
const childPath = `${path}/${Name}`;
|
80
|
+
children[childPath] = { PathDescription: { Self: child }, Path: childPath, partial: true };
|
81
|
+
}
|
82
|
+
return children;
|
83
|
+
}
|
81
84
|
const getSchemaSelector = createSelector((path) => path, (path) => schemaApi.endpoints.getSchema.select({ path }));
|
82
|
-
const selectGetSchema = createSelector((state) => state, (_state, path) => getSchemaSelector(path), (state, selectTabletsInfo) => selectTabletsInfo(state).data);
|
85
|
+
const selectGetSchema = createSelector((state) => state, (_state, path) => path, (_state, path) => getSchemaSelector(path), (state, path, selectTabletsInfo) => { var _a; return (_a = selectTabletsInfo(state).data) === null || _a === void 0 ? void 0 : _a[path]; });
|
83
86
|
const selectSchemaChildren = (state, path) => { var _a, _b; return (_b = (_a = selectGetSchema(state, path)) === null || _a === void 0 ? void 0 : _a.PathDescription) === null || _b === void 0 ? void 0 : _b.Children; };
|
84
87
|
export const selectSchemaMergedChildrenPaths = createSelector([
|
85
88
|
(_, path) => path,
|
@@ -90,3 +93,15 @@ export const selectSchemaMergedChildrenPaths = createSelector([
|
|
90
93
|
? children === null || children === void 0 ? void 0 : children.map(({ Name }) => path + '/' + Name)
|
91
94
|
: undefined;
|
92
95
|
});
|
96
|
+
export function useGetSchemaQuery({ path }) {
|
97
|
+
const { currentData, isFetching, error, refetch } = schemaApi.useGetSchemaQuery({ path });
|
98
|
+
const data = currentData === null || currentData === void 0 ? void 0 : currentData[path];
|
99
|
+
const isLoading = isFetching && data === undefined;
|
100
|
+
const shouldLoad = !isLoading && ((!data && !error) || (data === null || data === void 0 ? void 0 : data.partial));
|
101
|
+
React.useEffect(() => {
|
102
|
+
if (shouldLoad) {
|
103
|
+
refetch();
|
104
|
+
}
|
105
|
+
}, [refetch, path, shouldLoad]);
|
106
|
+
return { data, isLoading, error };
|
107
|
+
}
|
@@ -148,6 +148,8 @@ interface TDomainState {
|
|
148
148
|
}
|
149
149
|
interface TDiskSpaceUsage {
|
150
150
|
Tables?: TTables;
|
151
|
+
Topics?: TTopics;
|
152
|
+
TStoragePoolUsage?: TStoragePoolUsage[];
|
151
153
|
}
|
152
154
|
interface TTables {
|
153
155
|
/** uint64 */
|
@@ -157,6 +159,25 @@ interface TTables {
|
|
157
159
|
/** uint64 */
|
158
160
|
IndexSize?: string;
|
159
161
|
}
|
162
|
+
interface TTopics {
|
163
|
+
/** uint64 */
|
164
|
+
ReserveSize?: string;
|
165
|
+
/** uint64 */
|
166
|
+
AccountSize?: string;
|
167
|
+
/** uint64 */
|
168
|
+
DataSize?: string;
|
169
|
+
/** uint64 */
|
170
|
+
UsedReserveSize?: string;
|
171
|
+
}
|
172
|
+
interface TStoragePoolUsage {
|
173
|
+
PoolKind?: string;
|
174
|
+
/** uint64 */
|
175
|
+
TotalSize?: string;
|
176
|
+
/** uint64 */
|
177
|
+
DataSize?: string;
|
178
|
+
/** uint64 */
|
179
|
+
IndexSize?: string;
|
180
|
+
}
|
160
181
|
interface TStoragePool {
|
161
182
|
Name?: string;
|
162
183
|
Kind?: string;
|
@@ -1,19 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
export declare const TOP_QUERIES_COLUMNS_IDS: {
|
2
|
+
CPUTimeUs: string;
|
3
|
+
QueryText: string;
|
4
|
+
EndTime: string;
|
5
|
+
ReadRows: string;
|
6
|
+
ReadBytes: string;
|
7
|
+
UserSID: string;
|
8
|
+
OneLineQueryText: string;
|
9
|
+
QueryHash: string;
|
10
|
+
Duration: string;
|
6
11
|
};
|
7
|
-
declare const
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
export declare const TOP_SHARD_COLUMNS_IDS: {
|
13
|
+
TabletId: string;
|
14
|
+
CPUCores: string;
|
15
|
+
DataSize: string;
|
16
|
+
Path: string;
|
17
|
+
NodeId: string;
|
18
|
+
PeakTime: string;
|
19
|
+
InFlightTxCount: string;
|
20
|
+
IntervalEnd: string;
|
14
21
|
};
|
15
|
-
|
16
|
-
|
17
|
-
export declare const isSortableTopShardsProperty: (value: string) => value is TopShardsSortValue;
|
18
|
-
export declare const isSortableTopQueriesProperty: (value: string) => value is TopQueriesSortValue;
|
19
|
-
export {};
|
22
|
+
export declare const isSortableTopShardsProperty: (value: string) => boolean;
|
23
|
+
export declare const isSortableTopQueriesProperty: (value: string) => boolean;
|
@@ -1,15 +1,36 @@
|
|
1
|
-
const
|
2
|
-
|
3
|
-
|
4
|
-
InFlightTxCount: 'InFlightTxCount',
|
5
|
-
};
|
6
|
-
const TOP_QUERIES_SORT_VALUES = {
|
7
|
-
CPUTimeUs: 'CPUTimeUs',
|
1
|
+
export const TOP_QUERIES_COLUMNS_IDS = {
|
2
|
+
CPUTimeUs: 'CPUTime',
|
3
|
+
QueryText: 'QueryText',
|
8
4
|
EndTime: 'EndTime',
|
9
5
|
ReadRows: 'ReadRows',
|
10
6
|
ReadBytes: 'ReadBytes',
|
11
7
|
UserSID: 'UserSID',
|
8
|
+
OneLineQueryText: 'OneLineQueryText',
|
9
|
+
QueryHash: 'QueryHash',
|
12
10
|
Duration: 'Duration',
|
13
11
|
};
|
12
|
+
export const TOP_SHARD_COLUMNS_IDS = {
|
13
|
+
TabletId: 'TabletId',
|
14
|
+
CPUCores: 'CPUCores',
|
15
|
+
DataSize: 'DataSize',
|
16
|
+
Path: 'Path',
|
17
|
+
NodeId: 'NodeId',
|
18
|
+
PeakTime: 'PeakTime',
|
19
|
+
InFlightTxCount: 'InFlightTxCount',
|
20
|
+
IntervalEnd: 'IntervalEnd',
|
21
|
+
};
|
22
|
+
const TOP_SHARDS_SORT_VALUES = [
|
23
|
+
TOP_SHARD_COLUMNS_IDS.CPUCores,
|
24
|
+
TOP_SHARD_COLUMNS_IDS.DataSize,
|
25
|
+
TOP_SHARD_COLUMNS_IDS.InFlightTxCount,
|
26
|
+
];
|
27
|
+
const TOP_QUERIES_SORT_VALUES = [
|
28
|
+
TOP_QUERIES_COLUMNS_IDS.CPUTimeUs,
|
29
|
+
TOP_QUERIES_COLUMNS_IDS.EndTime,
|
30
|
+
TOP_QUERIES_COLUMNS_IDS.ReadRows,
|
31
|
+
TOP_QUERIES_COLUMNS_IDS.ReadBytes,
|
32
|
+
TOP_QUERIES_COLUMNS_IDS.UserSID,
|
33
|
+
TOP_QUERIES_COLUMNS_IDS.Duration,
|
34
|
+
];
|
14
35
|
export const isSortableTopShardsProperty = (value) => Object.values(TOP_SHARDS_SORT_VALUES).includes(value);
|
15
36
|
export const isSortableTopQueriesProperty = (value) => Object.values(TOP_QUERIES_SORT_VALUES).includes(value);
|
@@ -10,7 +10,7 @@ function disableCodeSuggestions() {
|
|
10
10
|
export function registerYQLCompletionItemProvider(database) {
|
11
11
|
disableCodeSuggestions();
|
12
12
|
completionProvider = monaco.languages.registerCompletionItemProvider(LANGUAGE_YQL_ID, {
|
13
|
-
triggerCharacters: [' ', '
|
13
|
+
triggerCharacters: [' ', '.', '`', '(', '/'],
|
14
14
|
provideCompletionItems: createProvideSuggestionsFunction(database),
|
15
15
|
});
|
16
16
|
}
|
package/package.json
CHANGED
@@ -1,5 +0,0 @@
|
|
1
|
-
export declare const olapApi: import("@reduxjs/toolkit/query").Api<import("@reduxjs/toolkit/query").BaseQueryFn<void, typeof import("./api")._NEVER, unknown, {}>, {
|
2
|
-
getOlapStats: import("@reduxjs/toolkit/query").QueryDefinition<{
|
3
|
-
path?: string;
|
4
|
-
} | undefined, import("@reduxjs/toolkit/query").BaseQueryFn<void, typeof import("./api")._NEVER, unknown, {}>, "All", import("../../types/store/query").IQueryResult | undefined, "api">;
|
5
|
-
}, "api", "All", typeof import("@reduxjs/toolkit/query").coreModuleName | typeof import("@reduxjs/toolkit/query/react").reactHooksModuleName>;
|
@@ -1,31 +0,0 @@
|
|
1
|
-
import { isQueryErrorResponse, parseQueryAPIExecuteResponse } from '../../utils/query';
|
2
|
-
import { api } from './api';
|
3
|
-
function createOlatStatsQuery(path) {
|
4
|
-
return `SELECT * FROM \`${path}/.sys/primary_index_stats\``;
|
5
|
-
}
|
6
|
-
const queryAction = 'execute-scan';
|
7
|
-
export const olapApi = api.injectEndpoints({
|
8
|
-
endpoints: (build) => ({
|
9
|
-
getOlapStats: build.query({
|
10
|
-
queryFn: async ({ path = '' } = {}, { signal }) => {
|
11
|
-
try {
|
12
|
-
const response = await window.api.sendQuery({
|
13
|
-
schema: 'modern',
|
14
|
-
query: createOlatStatsQuery(path),
|
15
|
-
database: path,
|
16
|
-
action: queryAction,
|
17
|
-
}, { signal });
|
18
|
-
if (isQueryErrorResponse(response)) {
|
19
|
-
return { error: response };
|
20
|
-
}
|
21
|
-
return { data: parseQueryAPIExecuteResponse(response) };
|
22
|
-
}
|
23
|
-
catch (error) {
|
24
|
-
return { error: error || new Error('Unauthorized') };
|
25
|
-
}
|
26
|
-
},
|
27
|
-
providesTags: ['All'],
|
28
|
-
}),
|
29
|
-
}),
|
30
|
-
overrideExisting: 'throw',
|
31
|
-
});
|