ydb-embedded-ui 4.16.1 → 4.17.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +23 -0
- package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +4 -4
- package/dist/components/CircularProgressBar/CircularProgressBar.scss +42 -0
- package/dist/components/CircularProgressBar/CircularProgressBar.tsx +59 -0
- package/dist/components/DiagnosticCard/DiagnosticCard.scss +20 -3
- package/dist/components/DiagnosticCard/DiagnosticCard.tsx +5 -6
- package/dist/containers/Cluster/Cluster.tsx +4 -4
- package/dist/containers/Node/Node.tsx +4 -4
- package/dist/containers/Node/NodeStructure/NodeStructure.tsx +5 -5
- package/dist/containers/Nodes/Nodes.tsx +3 -3
- package/dist/containers/Storage/Storage.tsx +3 -3
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +3 -3
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +1 -5
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +41 -18
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -4
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Details/Details.tsx +3 -3
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Healthcheck.scss +27 -14
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Healthcheck.tsx +6 -6
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Preview/Preview.tsx +15 -16
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/Healthcheck.scss +108 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckDetails.tsx +45 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx +83 -0
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTree.scss +1 -3
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTree.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/IssueTreeItem.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/en.json +2 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/index.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/ru.json +2 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricCard/MetricCard.scss +52 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricCard/MetricCard.tsx +48 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.scss +12 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +134 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/OldTenantOverview.tsx +155 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +3 -5
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +79 -89
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +3 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +3 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/useHealthcheck.ts +53 -0
- package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +5 -5
- package/dist/containers/Tenant/Tenant.tsx +4 -4
- package/dist/containers/Tenant/TenantPages.tsx +1 -0
- package/dist/containers/Tenant/utils/queryTemplates.ts +23 -23
- package/dist/containers/UserSettings/i18n/en.json +4 -1
- package/dist/containers/UserSettings/i18n/ru.json +4 -1
- package/dist/containers/UserSettings/settings.ts +7 -0
- package/dist/services/api.ts +6 -4
- package/dist/store/reducers/healthcheckInfo.ts +20 -12
- package/dist/store/reducers/settings/settings.ts +5 -0
- package/dist/store/reducers/tenant/constants.ts +7 -0
- package/dist/store/reducers/tenant/tenant.ts +15 -0
- package/dist/store/reducers/tenant/types.ts +5 -0
- package/dist/store/reducers/tenants/contants.ts +6 -0
- package/dist/store/reducers/tenants/types.ts +4 -0
- package/dist/store/reducers/tenants/utils.ts +114 -7
- package/dist/store/state-url-mapping.js +3 -0
- package/dist/styles/constants.scss +2 -0
- package/dist/types/api/tenant.ts +3 -0
- package/dist/utils/constants.ts +1 -0
- package/dist/utils/formatCPU/formatCPU.ts +20 -0
- package/dist/utils/formatCPU/i18n/en.json +3 -0
- package/dist/utils/formatCPU/i18n/index.ts +11 -0
- package/dist/utils/formatCPU/i18n/ru.json +3 -0
- package/package.json +1 -1
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Details/index.ts +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Preview/index.ts +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/index.ts +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/IssueTreeItem.scss +0 -0
- /package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/index.ts +0 -0
@@ -0,0 +1,155 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
import {useCallback} from 'react';
|
3
|
+
import {useDispatch} from 'react-redux';
|
4
|
+
|
5
|
+
import {Loader} from '@gravity-ui/uikit';
|
6
|
+
|
7
|
+
import {InfoViewer} from '../../../../components/InfoViewer';
|
8
|
+
import {PoolUsage} from '../../../../components/PoolUsage/PoolUsage';
|
9
|
+
import {Tablet} from '../../../../components/Tablet';
|
10
|
+
import EntityStatus from '../../../../components/EntityStatus/EntityStatus';
|
11
|
+
import {formatCPU} from '../../../../utils';
|
12
|
+
import {TABLET_STATES, TENANT_DEFAULT_TITLE} from '../../../../utils/constants';
|
13
|
+
import {bytesToGB} from '../../../../utils/utils';
|
14
|
+
import {mapDatabaseTypeToDBName} from '../../utils/schema';
|
15
|
+
import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
|
16
|
+
import type {ETabletVolatileState} from '../../../../types/api/tenant';
|
17
|
+
import type {AdditionalTenantsProps} from '../../../../types/additionalProps';
|
18
|
+
import {getTenantInfo, setDataWasNotLoaded} from '../../../../store/reducers/tenant/tenant';
|
19
|
+
|
20
|
+
import i18n from './i18n';
|
21
|
+
import './TenantOverview.scss';
|
22
|
+
|
23
|
+
const b = cn('tenant-overview');
|
24
|
+
|
25
|
+
interface OldTenantOverviewProps {
|
26
|
+
tenantName: string;
|
27
|
+
additionalTenantProps?: AdditionalTenantsProps;
|
28
|
+
}
|
29
|
+
|
30
|
+
export function OldTenantOverview({tenantName, additionalTenantProps}: OldTenantOverviewProps) {
|
31
|
+
const {tenant, loading, wasLoaded} = useTypedSelector((state) => state.tenant);
|
32
|
+
const {autorefresh} = useTypedSelector((state) => state.schema);
|
33
|
+
const dispatch = useDispatch();
|
34
|
+
const fetchTenant = useCallback(
|
35
|
+
(isBackground = true) => {
|
36
|
+
if (!isBackground) {
|
37
|
+
dispatch(setDataWasNotLoaded());
|
38
|
+
}
|
39
|
+
dispatch(getTenantInfo({path: tenantName}));
|
40
|
+
},
|
41
|
+
[dispatch, tenantName],
|
42
|
+
);
|
43
|
+
|
44
|
+
useAutofetcher(fetchTenant, [fetchTenant], autorefresh);
|
45
|
+
|
46
|
+
const {
|
47
|
+
Metrics = {},
|
48
|
+
PoolStats,
|
49
|
+
StateStats = [],
|
50
|
+
MemoryUsed,
|
51
|
+
Name,
|
52
|
+
State,
|
53
|
+
CoresUsed,
|
54
|
+
StorageGroups,
|
55
|
+
StorageAllocatedSize,
|
56
|
+
Type,
|
57
|
+
SystemTablets,
|
58
|
+
} = tenant || {};
|
59
|
+
|
60
|
+
const tenantType = mapDatabaseTypeToDBName(Type);
|
61
|
+
const memoryRaw = MemoryUsed ?? Metrics.Memory;
|
62
|
+
|
63
|
+
const memory = (memoryRaw && bytesToGB(memoryRaw)) || i18n('no-data');
|
64
|
+
const storage = (Metrics.Storage && bytesToGB(Metrics.Storage)) || i18n('no-data');
|
65
|
+
const storageGroups = StorageGroups ?? i18n('no-data');
|
66
|
+
const blobStorage =
|
67
|
+
(StorageAllocatedSize && bytesToGB(StorageAllocatedSize)) || i18n('no-data');
|
68
|
+
const storageEfficiency =
|
69
|
+
Metrics.Storage && StorageAllocatedSize
|
70
|
+
? `${((parseInt(Metrics.Storage) * 100) / parseInt(StorageAllocatedSize)).toFixed(2)}%`
|
71
|
+
: i18n('no-data');
|
72
|
+
|
73
|
+
const cpuRaw = CoresUsed !== undefined ? Number(CoresUsed) * 1_000_000 : Metrics.CPU;
|
74
|
+
|
75
|
+
const cpu = formatCPU(cpuRaw);
|
76
|
+
|
77
|
+
const metricsInfo = [
|
78
|
+
{label: 'Type', value: Type},
|
79
|
+
{label: 'Memory', value: memory},
|
80
|
+
{label: 'CPU', value: cpu},
|
81
|
+
{label: 'Tablet storage', value: storage},
|
82
|
+
{label: 'Storage groups', value: storageGroups},
|
83
|
+
{label: 'Blob storage', value: blobStorage},
|
84
|
+
{label: 'Storage efficiency', value: storageEfficiency},
|
85
|
+
];
|
86
|
+
|
87
|
+
const tabletsInfo = StateStats.filter(
|
88
|
+
(item): item is {VolatileState: ETabletVolatileState; Count: number} => {
|
89
|
+
return item.VolatileState !== undefined && item.Count !== undefined;
|
90
|
+
},
|
91
|
+
).map((info) => {
|
92
|
+
return {label: TABLET_STATES[info.VolatileState], value: info.Count};
|
93
|
+
});
|
94
|
+
|
95
|
+
const renderName = () => {
|
96
|
+
return (
|
97
|
+
<div className={b('tenant-name-wrapper')}>
|
98
|
+
<EntityStatus
|
99
|
+
status={State}
|
100
|
+
name={Name || TENANT_DEFAULT_TITLE}
|
101
|
+
withLeftTrim
|
102
|
+
hasClipboardButton={Boolean(tenant)}
|
103
|
+
clipboardButtonAlwaysVisible
|
104
|
+
/>
|
105
|
+
</div>
|
106
|
+
);
|
107
|
+
};
|
108
|
+
|
109
|
+
if (loading && !wasLoaded) {
|
110
|
+
return (
|
111
|
+
<div className={b('loader')}>
|
112
|
+
<Loader size="m" />
|
113
|
+
</div>
|
114
|
+
);
|
115
|
+
}
|
116
|
+
|
117
|
+
return (
|
118
|
+
<div className={b()}>
|
119
|
+
<div className={b('top-label')}>{tenantType}</div>
|
120
|
+
<div className={b('top')}>
|
121
|
+
{renderName()}
|
122
|
+
{additionalTenantProps?.getMonitoringLink?.(Name, Type)}
|
123
|
+
</div>
|
124
|
+
<div className={b('system-tablets')}>
|
125
|
+
{SystemTablets &&
|
126
|
+
SystemTablets.map((tablet, tabletIndex) => (
|
127
|
+
<Tablet key={tabletIndex} tablet={tablet} tenantName={Name} />
|
128
|
+
))}
|
129
|
+
</div>
|
130
|
+
<div className={b('common-info')}>
|
131
|
+
<div>
|
132
|
+
<div className={b('section-title')}>{i18n('title.pools')}</div>
|
133
|
+
{PoolStats ? (
|
134
|
+
<div className={b('section', {pools: true})}>
|
135
|
+
{PoolStats.map((pool, poolIndex) => (
|
136
|
+
<PoolUsage key={poolIndex} data={pool} />
|
137
|
+
))}
|
138
|
+
</div>
|
139
|
+
) : (
|
140
|
+
<div className="error">{i18n('no-pools-data')}</div>
|
141
|
+
)}
|
142
|
+
</div>
|
143
|
+
<InfoViewer
|
144
|
+
title={i18n('title.metrics')}
|
145
|
+
className={b('section', {metrics: true})}
|
146
|
+
info={metricsInfo}
|
147
|
+
/>
|
148
|
+
|
149
|
+
<div className={b('section')}>
|
150
|
+
<InfoViewer info={tabletsInfo} title="Tablets" />
|
151
|
+
</div>
|
152
|
+
</div>
|
153
|
+
</div>
|
154
|
+
);
|
155
|
+
}
|
@@ -1,7 +1,6 @@
|
|
1
|
-
@use '../DetailedOverview/DetailedOverview.scss' as detailedOverview;
|
2
|
-
|
3
1
|
.tenant-overview {
|
4
2
|
padding-bottom: 20px;
|
3
|
+
|
5
4
|
&__loader {
|
6
5
|
display: flex;
|
7
6
|
justify-content: center;
|
@@ -22,10 +21,10 @@
|
|
22
21
|
}
|
23
22
|
|
24
23
|
&__top-label {
|
25
|
-
margin-bottom:
|
24
|
+
margin-bottom: var(--diagnostics-section-title-margin);
|
26
25
|
|
27
26
|
font-weight: 600;
|
28
|
-
line-height:
|
27
|
+
line-height: 24px;
|
29
28
|
gap: 10px;
|
30
29
|
}
|
31
30
|
|
@@ -50,7 +49,6 @@
|
|
50
49
|
font-size: var(--yc-text-body-2-font-size);
|
51
50
|
font-weight: 500;
|
52
51
|
line-height: var(--yc-text-body-2-line-height);
|
53
|
-
//text-transform: uppercase;
|
54
52
|
}
|
55
53
|
|
56
54
|
&__section {
|
@@ -4,18 +4,17 @@ import {useDispatch} from 'react-redux';
|
|
4
4
|
|
5
5
|
import {Loader} from '@gravity-ui/uikit';
|
6
6
|
|
7
|
-
import {InfoViewer} from '../../../../components/InfoViewer';
|
8
|
-
import {PoolUsage} from '../../../../components/PoolUsage/PoolUsage';
|
9
|
-
import {Tablet} from '../../../../components/Tablet';
|
10
7
|
import EntityStatus from '../../../../components/EntityStatus/EntityStatus';
|
11
|
-
import {
|
12
|
-
import {
|
13
|
-
import {bytesToGB} from '../../../../utils/utils';
|
8
|
+
import {TENANT_DEFAULT_TITLE} from '../../../../utils/constants';
|
9
|
+
import {TENANT_METRICS_TABS_IDS} from '../../../../store/reducers/tenant/constants';
|
14
10
|
import {mapDatabaseTypeToDBName} from '../../utils/schema';
|
15
11
|
import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
|
16
|
-
import type {ETabletVolatileState} from '../../../../types/api/tenant';
|
17
12
|
import type {AdditionalTenantsProps} from '../../../../types/additionalProps';
|
18
13
|
import {getTenantInfo, setDataWasNotLoaded} from '../../../../store/reducers/tenant/tenant';
|
14
|
+
import {calculateTenantMetrics} from '../../../../store/reducers/tenants/utils';
|
15
|
+
import {HealthcheckDetails} from './Healthcheck/HealthcheckDetails';
|
16
|
+
import {MetricsCards, type TenantMetrics} from './MetricsCards/MetricsCards';
|
17
|
+
import {useHealthcheck} from './useHealthcheck';
|
19
18
|
|
20
19
|
import i18n from './i18n';
|
21
20
|
import './TenantOverview.scss';
|
@@ -24,13 +23,30 @@ const b = cn('tenant-overview');
|
|
24
23
|
|
25
24
|
interface TenantOverviewProps {
|
26
25
|
tenantName: string;
|
27
|
-
|
26
|
+
additionalTenantProps?: AdditionalTenantsProps;
|
28
27
|
}
|
29
28
|
|
30
|
-
export function TenantOverview({tenantName,
|
31
|
-
const {tenant, loading, wasLoaded} = useTypedSelector((state) => state.tenant);
|
32
|
-
const {autorefresh} = useTypedSelector((state) => state.schema);
|
29
|
+
export function TenantOverview({tenantName, additionalTenantProps}: TenantOverviewProps) {
|
33
30
|
const dispatch = useDispatch();
|
31
|
+
|
32
|
+
const {
|
33
|
+
tenant,
|
34
|
+
loading: tenantLoading,
|
35
|
+
wasLoaded: tenantWasLoaded,
|
36
|
+
metricsTab,
|
37
|
+
} = useTypedSelector((state) => state.tenant);
|
38
|
+
const {autorefresh} = useTypedSelector((state) => state.schema);
|
39
|
+
|
40
|
+
const {
|
41
|
+
issueTrees,
|
42
|
+
issuesStatistics,
|
43
|
+
selfCheckResult,
|
44
|
+
fetchHealthcheck,
|
45
|
+
loading: healthcheckLoading,
|
46
|
+
wasLoaded: healthCheckWasLoaded,
|
47
|
+
error: healthcheckError,
|
48
|
+
} = useHealthcheck(tenantName);
|
49
|
+
|
34
50
|
const fetchTenant = useCallback(
|
35
51
|
(isBackground = true) => {
|
36
52
|
if (!isBackground) {
|
@@ -41,56 +57,30 @@ export function TenantOverview({tenantName, additionalTenantInfo}: TenantOvervie
|
|
41
57
|
[dispatch, tenantName],
|
42
58
|
);
|
43
59
|
|
44
|
-
useAutofetcher(
|
60
|
+
useAutofetcher(
|
61
|
+
(isBackground) => {
|
62
|
+
fetchTenant(isBackground);
|
63
|
+
fetchHealthcheck(isBackground);
|
64
|
+
},
|
65
|
+
[fetchTenant, fetchHealthcheck],
|
66
|
+
autorefresh,
|
67
|
+
);
|
45
68
|
|
46
|
-
const {
|
47
|
-
Metrics = {},
|
48
|
-
PoolStats,
|
49
|
-
StateStats = [],
|
50
|
-
MemoryUsed,
|
51
|
-
Name,
|
52
|
-
State,
|
53
|
-
CoresUsed,
|
54
|
-
StorageGroups,
|
55
|
-
StorageAllocatedSize,
|
56
|
-
Type,
|
57
|
-
SystemTablets,
|
58
|
-
} = tenant || {};
|
69
|
+
const {Name, State, Type} = tenant || {};
|
59
70
|
|
60
71
|
const tenantType = mapDatabaseTypeToDBName(Type);
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
const
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
const cpuRaw = CoresUsed !== undefined ? Number(CoresUsed) * 1_000_000 : Metrics.CPU;
|
74
|
-
|
75
|
-
const cpu = formatCPU(cpuRaw);
|
76
|
-
|
77
|
-
const metricsInfo = [
|
78
|
-
{label: 'Type', value: Type},
|
79
|
-
{label: 'Memory', value: memory},
|
80
|
-
{label: 'CPU', value: cpu},
|
81
|
-
{label: 'Tablet storage', value: storage},
|
82
|
-
{label: 'Storage groups', value: storageGroups},
|
83
|
-
{label: 'Blob storage', value: blobStorage},
|
84
|
-
{label: 'Storage efficiency', value: storageEfficiency},
|
85
|
-
];
|
86
|
-
|
87
|
-
const tabletsInfo = StateStats.filter(
|
88
|
-
(item): item is {VolatileState: ETabletVolatileState; Count: number} => {
|
89
|
-
return item.VolatileState !== undefined && item.Count !== undefined;
|
90
|
-
},
|
91
|
-
).map((info) => {
|
92
|
-
return {label: TABLET_STATES[info.VolatileState], value: info.Count};
|
93
|
-
});
|
72
|
+
|
73
|
+
const {cpu, storage, memory, cpuLimit, storageLimit, memoryLimit} =
|
74
|
+
calculateTenantMetrics(tenant);
|
75
|
+
|
76
|
+
const calculatedMetrics: TenantMetrics = {
|
77
|
+
memoryUsed: memory,
|
78
|
+
memoryLimit,
|
79
|
+
cpuUsed: cpu,
|
80
|
+
cpuLimit,
|
81
|
+
storageUsed: storage,
|
82
|
+
storageLimit,
|
83
|
+
};
|
94
84
|
|
95
85
|
const renderName = () => {
|
96
86
|
return (
|
@@ -106,7 +96,27 @@ export function TenantOverview({tenantName, additionalTenantInfo}: TenantOvervie
|
|
106
96
|
);
|
107
97
|
};
|
108
98
|
|
109
|
-
|
99
|
+
const renderTabContent = () => {
|
100
|
+
switch (metricsTab) {
|
101
|
+
case TENANT_METRICS_TABS_IDS.cpu: {
|
102
|
+
return i18n('label.under-development');
|
103
|
+
}
|
104
|
+
case TENANT_METRICS_TABS_IDS.storage: {
|
105
|
+
return i18n('label.under-development');
|
106
|
+
}
|
107
|
+
case TENANT_METRICS_TABS_IDS.memory: {
|
108
|
+
return i18n('label.under-development');
|
109
|
+
}
|
110
|
+
case TENANT_METRICS_TABS_IDS.healthcheck: {
|
111
|
+
return <HealthcheckDetails issueTrees={issueTrees} error={healthcheckError} />;
|
112
|
+
}
|
113
|
+
default: {
|
114
|
+
return undefined;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
};
|
118
|
+
|
119
|
+
if ((tenantLoading && !tenantWasLoaded) || (healthcheckLoading && !healthCheckWasLoaded)) {
|
110
120
|
return (
|
111
121
|
<div className={b('loader')}>
|
112
122
|
<Loader size="m" />
|
@@ -119,37 +129,17 @@ export function TenantOverview({tenantName, additionalTenantInfo}: TenantOvervie
|
|
119
129
|
<div className={b('top-label')}>{tenantType}</div>
|
120
130
|
<div className={b('top')}>
|
121
131
|
{renderName()}
|
122
|
-
{
|
123
|
-
</div>
|
124
|
-
<div className={b('system-tablets')}>
|
125
|
-
{SystemTablets &&
|
126
|
-
SystemTablets.map((tablet, tabletIndex) => (
|
127
|
-
<Tablet key={tabletIndex} tablet={tablet} tenantName={Name} />
|
128
|
-
))}
|
129
|
-
</div>
|
130
|
-
<div className={b('common-info')}>
|
131
|
-
<div>
|
132
|
-
<div className={b('section-title')}>{i18n('title.pools')}</div>
|
133
|
-
{PoolStats ? (
|
134
|
-
<div className={b('section', {pools: true})}>
|
135
|
-
{PoolStats.map((pool, poolIndex) => (
|
136
|
-
<PoolUsage key={poolIndex} data={pool} />
|
137
|
-
))}
|
138
|
-
</div>
|
139
|
-
) : (
|
140
|
-
<div className="error">{i18n('no-pools-data')}</div>
|
141
|
-
)}
|
142
|
-
</div>
|
143
|
-
<InfoViewer
|
144
|
-
title={i18n('title.metrics')}
|
145
|
-
className={b('section', {metrics: true})}
|
146
|
-
info={metricsInfo}
|
147
|
-
/>
|
148
|
-
|
149
|
-
<div className={b('section')}>
|
150
|
-
<InfoViewer info={tabletsInfo} title="Tablets" />
|
151
|
-
</div>
|
132
|
+
{additionalTenantProps?.getMonitoringLink?.(Name, Type)}
|
152
133
|
</div>
|
134
|
+
<MetricsCards
|
135
|
+
metrics={calculatedMetrics}
|
136
|
+
issuesStatistics={issuesStatistics}
|
137
|
+
selfCheckResult={selfCheckResult}
|
138
|
+
fetchHealthcheck={fetchHealthcheck}
|
139
|
+
healthcheckLoading={healthcheckLoading}
|
140
|
+
healthcheckError={healthcheckError}
|
141
|
+
/>
|
142
|
+
{renderTabContent()}
|
153
143
|
</div>
|
154
144
|
);
|
155
145
|
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import {useCallback} from 'react';
|
2
|
+
import {useDispatch} from 'react-redux';
|
3
|
+
|
4
|
+
import {
|
5
|
+
getHealthcheckInfo,
|
6
|
+
selectIssuesStatistics,
|
7
|
+
selectIssuesTrees,
|
8
|
+
setDataWasNotLoaded,
|
9
|
+
} from '../../../../store/reducers/healthcheckInfo';
|
10
|
+
import type {IIssuesTree} from '../../../../types/store/healthcheck';
|
11
|
+
import {type StatusFlag, SelfCheckResult} from '../../../../types/api/healthcheck';
|
12
|
+
import type {IResponseError} from '../../../../types/api/error';
|
13
|
+
import {useTypedSelector} from '../../../../utils/hooks/useTypedSelector';
|
14
|
+
|
15
|
+
interface HealthcheckParams {
|
16
|
+
issueTrees: IIssuesTree[];
|
17
|
+
issuesStatistics: [StatusFlag, number][];
|
18
|
+
fetchHealthcheck: (isBackground?: boolean) => void;
|
19
|
+
loading: boolean;
|
20
|
+
wasLoaded: boolean;
|
21
|
+
error?: IResponseError;
|
22
|
+
selfCheckResult: SelfCheckResult;
|
23
|
+
}
|
24
|
+
|
25
|
+
export const useHealthcheck = (tenantName: string): HealthcheckParams => {
|
26
|
+
const dispatch = useDispatch();
|
27
|
+
|
28
|
+
const {data, loading, wasLoaded, error} = useTypedSelector((state) => state.healthcheckInfo);
|
29
|
+
const selfCheckResult = data?.self_check_result || SelfCheckResult.UNSPECIFIED;
|
30
|
+
const issuesStatistics = useTypedSelector(selectIssuesStatistics);
|
31
|
+
const issueTrees = useTypedSelector(selectIssuesTrees);
|
32
|
+
|
33
|
+
const fetchHealthcheck = useCallback(
|
34
|
+
(isBackground = true) => {
|
35
|
+
if (!isBackground) {
|
36
|
+
dispatch(setDataWasNotLoaded());
|
37
|
+
}
|
38
|
+
|
39
|
+
dispatch(getHealthcheckInfo(tenantName));
|
40
|
+
},
|
41
|
+
[dispatch, tenantName],
|
42
|
+
);
|
43
|
+
|
44
|
+
return {
|
45
|
+
issueTrees,
|
46
|
+
issuesStatistics,
|
47
|
+
fetchHealthcheck,
|
48
|
+
loading,
|
49
|
+
wasLoaded,
|
50
|
+
error,
|
51
|
+
selfCheckResult,
|
52
|
+
};
|
53
|
+
};
|
@@ -19,8 +19,8 @@ const b = cn('object-general');
|
|
19
19
|
|
20
20
|
interface ObjectGeneralProps {
|
21
21
|
type?: EPathType;
|
22
|
-
|
23
|
-
|
22
|
+
additionalTenantProps?: AdditionalTenantsProps;
|
23
|
+
additionalNodesProps?: AdditionalNodesProps;
|
24
24
|
}
|
25
25
|
|
26
26
|
function ObjectGeneral(props: ObjectGeneralProps) {
|
@@ -33,7 +33,7 @@ function ObjectGeneral(props: ObjectGeneralProps) {
|
|
33
33
|
const {name: tenantName, tenantPage = initialPage} = queryParams;
|
34
34
|
|
35
35
|
const renderTabContent = () => {
|
36
|
-
const {type,
|
36
|
+
const {type, additionalTenantProps, additionalNodesProps} = props;
|
37
37
|
switch (tenantPage) {
|
38
38
|
case TENANT_PAGES_IDS.query: {
|
39
39
|
return <Query path={tenantName as string} theme={theme} type={type} />;
|
@@ -42,8 +42,8 @@ function ObjectGeneral(props: ObjectGeneralProps) {
|
|
42
42
|
return (
|
43
43
|
<Diagnostics
|
44
44
|
type={type}
|
45
|
-
|
46
|
-
|
45
|
+
additionalTenantProps={additionalTenantProps}
|
46
|
+
additionalNodesProps={additionalNodesProps}
|
47
47
|
/>
|
48
48
|
);
|
49
49
|
}
|
@@ -38,8 +38,8 @@ const initialTenantSummaryState = {
|
|
38
38
|
};
|
39
39
|
|
40
40
|
interface TenantProps {
|
41
|
-
|
42
|
-
|
41
|
+
additionalTenantProps?: AdditionalTenantsProps;
|
42
|
+
additionalNodesProps?: AdditionalNodesProps;
|
43
43
|
}
|
44
44
|
|
45
45
|
function Tenant(props: TenantProps) {
|
@@ -125,8 +125,8 @@ function Tenant(props: TenantProps) {
|
|
125
125
|
/>
|
126
126
|
<ObjectGeneral
|
127
127
|
type={preloadedPathType || currentPathType}
|
128
|
-
|
129
|
-
|
128
|
+
additionalTenantProps={props.additionalTenantProps}
|
129
|
+
additionalNodesProps={props.additionalNodesProps}
|
130
130
|
/>
|
131
131
|
</SplitPane>
|
132
132
|
)}
|
@@ -69,42 +69,42 @@ export const createTopicTemplate = (path: string) => {
|
|
69
69
|
return `-- docs: https://ydb.tech/en/docs/yql/reference/syntax/create_topic
|
70
70
|
CREATE TOPIC \`${path}/my_topic\` (
|
71
71
|
CONSUMER consumer1,
|
72
|
-
CONSUMER consumer2 WITH (read_from = Datetime('
|
72
|
+
CONSUMER consumer2 WITH (read_from = Datetime('1970-01-01T00:00:00Z')) -- Sets up the message write time starting from which the consumer will receive data.
|
73
73
|
-- Value type: Datetime OR Timestamp OR integer (unix-timestamp in the numeric format).
|
74
74
|
-- Default value: now
|
75
75
|
) WITH (
|
76
|
-
min_active_partitions =
|
77
|
-
partition_count_limit =
|
78
|
-
retention_period = Interval('
|
79
|
-
retention_storage_mb =
|
76
|
+
min_active_partitions = 1, -- Minimum number of topic partitions.
|
77
|
+
partition_count_limit = 0, -- Maximum number of active partitions in the topic. 0 is interpreted as unlimited.
|
78
|
+
retention_period = Interval('PT18H'), -- Data retention period in the topic. Value type: Interval.
|
79
|
+
retention_storage_mb = 0, -- Limit on the maximum disk space occupied by the topic data.
|
80
80
|
-- When this value is exceeded, the older data is cleared, like under a retention policy.
|
81
81
|
-- 0 is interpreted as unlimited.
|
82
|
-
partition_write_speed_bytes_per_second =
|
83
|
-
partition_write_burst_bytes =
|
84
|
-
|
85
|
-
|
82
|
+
partition_write_speed_bytes_per_second = 1048576, -- Maximum allowed write speed per partition.
|
83
|
+
partition_write_burst_bytes = 0 -- Write quota allocated for write bursts.
|
84
|
+
-- When set to zero, the actual write_burst value is equalled to
|
85
|
+
-- the quota value (this allows write bursts of up to one second).
|
86
86
|
);`;
|
87
87
|
};
|
88
88
|
|
89
89
|
export const alterTopicTemplate = (path: string) => {
|
90
90
|
return `-- docs: https://ydb.tech/en/docs/yql/reference/syntax/alter_topic
|
91
91
|
ALTER TOPIC \`${path}\`
|
92
|
-
ADD CONSUMER new_consumer WITH (read_from =
|
93
|
-
|
94
|
-
|
95
|
-
ALTER CONSUMER consumer1 SET (read_from = Datetime('
|
92
|
+
ADD CONSUMER new_consumer WITH (read_from = Datetime('1970-01-01T00:00:00Z')), -- Sets up the message write time starting from which the consumer will receive data.
|
93
|
+
-- Value type: Datetime OR Timestamp OR integer (unix-timestamp in the numeric format).
|
94
|
+
-- Default value: now
|
95
|
+
ALTER CONSUMER consumer1 SET (read_from = Datetime('1970-01-01T00:00:00Z')),
|
96
96
|
DROP CONSUMER consumer2,
|
97
97
|
SET (
|
98
|
-
min_active_partitions =
|
99
|
-
partition_count_limit =
|
100
|
-
retention_period = Interval('
|
101
|
-
retention_storage_mb =
|
102
|
-
|
103
|
-
|
104
|
-
partition_write_speed_bytes_per_second =
|
105
|
-
partition_write_burst_bytes =
|
106
|
-
|
107
|
-
|
98
|
+
min_active_partitions = 1, -- Minimum number of topic partitions.
|
99
|
+
partition_count_limit = 0, -- Maximum number of active partitions in the topic. 0 is interpreted as unlimited.
|
100
|
+
retention_period = Interval('PT18H'), -- Data retention period in the topic. Value type: Interval.
|
101
|
+
retention_storage_mb = 0, -- Limit on the maximum disk space occupied by the topic data.
|
102
|
+
-- When this value is exceeded, the older data is cleared, like under a retention policy.
|
103
|
+
-- 0 is interpreted as unlimited.
|
104
|
+
partition_write_speed_bytes_per_second = 1048576, -- Maximum allowed write speed per partition.
|
105
|
+
partition_write_burst_bytes = 0 -- Write quota allocated for write bursts.
|
106
|
+
-- When set to zero, the actual write_burst value is equalled to
|
107
|
+
-- the quota value (this allows write bursts of up to one second).
|
108
108
|
);`;
|
109
109
|
};
|
110
110
|
|
@@ -23,5 +23,8 @@
|
|
23
23
|
"settings.useBackendParamsForTables.popover": "Filter and sort Nodes and Storage tables with request params. May increase performance, but could causes additional fetches and longer loading time on older versions",
|
24
24
|
|
25
25
|
"settings.enableAdditionalQueryModes.title": "Enable additional query modes",
|
26
|
-
"settings.enableAdditionalQueryModes.popover": "Adds 'Data', 'YQL - QueryService' and 'PostgreSQL' modes. May not work on some versions"
|
26
|
+
"settings.enableAdditionalQueryModes.popover": "Adds 'Data', 'YQL - QueryService' and 'PostgreSQL' modes. May not work on some versions",
|
27
|
+
|
28
|
+
"settings.tenantDiagnostics.title": "Enable new database diagnostics design",
|
29
|
+
"settings.tenantDiagnostics.popover": "Adds indicators of database resources usage. Incomplete data may be displayed for some databases"
|
27
30
|
}
|
@@ -23,5 +23,8 @@
|
|
23
23
|
"settings.useBackendParamsForTables.popover": "Добавляет фильтрацию и сортировку таблиц Nodes и Storage с использованием параметров запроса. Может улушить производительность, но на старых версиях может привести к дополнительным запросам и большему времени ожидания загрузки",
|
24
24
|
|
25
25
|
"settings.enableAdditionalQueryModes.title": "Включить дополнительные режимы выполнения запросов",
|
26
|
-
"settings.enableAdditionalQueryModes.popover": "Добавляет режимы 'Data', 'YQL - QueryService' и 'PostgreSQL'. Может работать некорректно на некоторых версиях"
|
26
|
+
"settings.enableAdditionalQueryModes.popover": "Добавляет режимы 'Data', 'YQL - QueryService' и 'PostgreSQL'. Может работать некорректно на некоторых версиях",
|
27
|
+
|
28
|
+
"settings.tenantDiagnostics.title": "Включить новый дизайн для диагностики баз данных",
|
29
|
+
"settings.tenantDiagnostics.popover": "Добавляет индикаторы использования ресурсов базы данных. Для некоторых баз могут отображаться неполные данные"
|
27
30
|
}
|
@@ -5,6 +5,7 @@ import flaskIcon from '../../assets/icons/flask.svg';
|
|
5
5
|
|
6
6
|
import {
|
7
7
|
ENABLE_ADDITIONAL_QUERY_MODES,
|
8
|
+
ENABLE_NEW_TENANT_DIAGNOSTICS_DESIGN,
|
8
9
|
INVERTED_DISKS_KEY,
|
9
10
|
LANGUAGE_KEY,
|
10
11
|
THEME_KEY,
|
@@ -94,6 +95,11 @@ export const enableQueryModesForExplainSetting: SettingProps = {
|
|
94
95
|
title: i18n('settings.enableAdditionalQueryModes.title'),
|
95
96
|
helpPopoverContent: i18n('settings.enableAdditionalQueryModes.popover'),
|
96
97
|
};
|
98
|
+
export const enableNewTenantDiagnosticsDesign: SettingProps = {
|
99
|
+
settingKey: ENABLE_NEW_TENANT_DIAGNOSTICS_DESIGN,
|
100
|
+
title: i18n('settings.tenantDiagnostics.title'),
|
101
|
+
helpPopoverContent: i18n('settings.tenantDiagnostics.popover'),
|
102
|
+
};
|
97
103
|
|
98
104
|
export const generalSection: SettingsSection = {
|
99
105
|
id: 'generalSection',
|
@@ -108,6 +114,7 @@ export const experimentsSection: SettingsSection = {
|
|
108
114
|
useNodesEndpointSetting,
|
109
115
|
useBackendParamsForTables,
|
110
116
|
enableQueryModesForExplainSetting,
|
117
|
+
enableNewTenantDiagnosticsDesign,
|
111
118
|
],
|
112
119
|
};
|
113
120
|
|