ydb-embedded-ui 6.10.3 → 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/Overview/Overview.js +1 -13
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.d.ts +1 -3
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.js +2 -2
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.d.ts +2 -3
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.js +28 -59
- 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/store/reducers/executeTopQueries/executeTopQueries.js +1 -0
- 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
|
{
|
@@ -18,17 +18,6 @@ import { TableInfo } from './TableInfo';
|
|
18
18
|
import { TopicInfo } from './TopicInfo';
|
19
19
|
function Overview({ type, path }) {
|
20
20
|
const [autoRefreshInterval] = useAutoRefreshInterval();
|
21
|
-
// FIXME: The request is too heavy, stats table may have millions of items
|
22
|
-
// Disabled until fixed
|
23
|
-
// https://github.com/ydb-platform/ydb-embedded-ui/issues/907
|
24
|
-
// https://github.com/ydb-platform/ydb-embedded-ui/issues/908
|
25
|
-
// const olapParams = isTableType(type) && isColumnEntityType(type) ? {path} : skipToken;
|
26
|
-
// const {currentData: olapData, isFetching: olapIsFetching} = olapApi.useGetOlapStatsQuery(
|
27
|
-
// olapParams,
|
28
|
-
// {pollingInterval: autoRefreshInterval},
|
29
|
-
// );
|
30
|
-
// const olapStatsLoading = olapIsFetching && olapData === undefined;
|
31
|
-
// const {result: olapStats} = olapData || {result: undefined};
|
32
21
|
const isEntityWithMergedImpl = isEntityWithMergedImplementation(type);
|
33
22
|
// shallowEqual prevents rerenders when new schema data is loaded
|
34
23
|
const mergedChildrenPaths = useTypedSelector((state) => selectSchemaMergedChildrenPaths(state, path, type), shallowEqual);
|
@@ -45,7 +34,6 @@ function Overview({ type, path }) {
|
|
45
34
|
const overviewLoading = isFetching && currentData === undefined;
|
46
35
|
const { data: rawData, additionalData } = currentData || {};
|
47
36
|
const { error: schemaError } = useGetSchemaQuery({ path });
|
48
|
-
// overviewLoading || olapStatsLoading
|
49
37
|
const entityLoading = overviewLoading;
|
50
38
|
const entityNotReady = isEntityWithMergedImpl && !mergedChildrenPaths;
|
51
39
|
const renderContent = () => {
|
@@ -72,7 +60,7 @@ function Overview({ type, path }) {
|
|
72
60
|
[EPathType.EPathTypeView]: () => _jsx(ViewInfo, { data: data }),
|
73
61
|
[EPathType.EPathTypeReplication]: () => _jsx(AsyncReplicationInfo, { data: data }),
|
74
62
|
};
|
75
|
-
return (
|
63
|
+
return (type && ((_a = pathTypeToComponent[type]) === null || _a === void 0 ? void 0 : _a.call(pathTypeToComponent))) || _jsx(TableInfo, { data: data, type: type });
|
76
64
|
};
|
77
65
|
if (entityLoading || entityNotReady) {
|
78
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, tableStatsInfo, tabletMetricsInfo = [], partitionConfigInfo = [], } = React.useMemo(() => prepareTableInfo(data, type
|
12
|
+
const { generalInfo, tableStatsInfo, tabletMetricsInfo = [], partitionConfigInfo = [], } = React.useMemo(() => prepareTableInfo(data, type), [data, type]);
|
13
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,16 +1,15 @@
|
|
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;
|
10
9
|
partitionConfigInfo?: undefined;
|
11
10
|
} | {
|
12
11
|
generalInfo: InfoViewerItem[];
|
13
|
-
tableStatsInfo: InfoViewerItem[][]
|
12
|
+
tableStatsInfo: InfoViewerItem[][];
|
14
13
|
tabletMetricsInfo: InfoViewerItem[];
|
15
14
|
partitionConfigInfo: InfoViewerItem[];
|
16
15
|
};
|
@@ -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,43 +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
|
-
}),
|
147
|
-
formatObject(formatTableStatsItem, {
|
148
|
-
RowUpdates,
|
149
|
-
RowDeletes,
|
150
|
-
RowReads,
|
151
|
-
RangeReads,
|
152
|
-
RangeReadRows,
|
153
|
-
}),
|
154
|
-
];
|
155
|
-
}
|
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
|
+
];
|
156
125
|
//@ts-expect-error
|
157
126
|
const tabletMetricsInfo = formatObject(formatTabletMetricsItem, TabletMetrics);
|
158
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,
|
@@ -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
|
-
});
|