ydb-embedded-ui 4.16.2 → 4.17.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/CHANGELOG.md +15 -0
- 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/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +1 -5
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +40 -17
- 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 +76 -86
- 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/TenantPages.tsx +1 -0
- 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
| @@ -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';
         | 
| @@ -28,9 +27,26 @@ interface TenantOverviewProps { | |
| 28 27 | 
             
            }
         | 
| 29 28 |  | 
| 30 29 | 
             
            export function TenantOverview({tenantName, additionalTenantProps}: TenantOverviewProps) {
         | 
| 31 | 
            -
                const {tenant, loading, wasLoaded} = useTypedSelector((state) => state.tenant);
         | 
| 32 | 
            -
                const {autorefresh} = useTypedSelector((state) => state.schema);
         | 
| 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, additionalTenantProps}: TenantOvervi | |
| 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, additionalTenantProps}: TenantOvervi | |
| 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" />
         | 
| @@ -121,35 +131,15 @@ export function TenantOverview({tenantName, additionalTenantProps}: TenantOvervi | |
| 121 131 | 
             
                            {renderName()}
         | 
| 122 132 | 
             
                            {additionalTenantProps?.getMonitoringLink?.(Name, Type)}
         | 
| 123 133 | 
             
                        </div>
         | 
| 124 | 
            -
                        < | 
| 125 | 
            -
                            { | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 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>
         | 
| 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 | 
            +
            };
         | 
| @@ -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 |  | 
    
        package/dist/services/api.ts
    CHANGED
    
    | @@ -350,10 +350,12 @@ export class YdbEmbeddedAPI extends AxiosWrapper { | |
| 350 350 | 
             
                        enable_sampling: enableSampling,
         | 
| 351 351 | 
             
                    });
         | 
| 352 352 | 
             
                }
         | 
| 353 | 
            -
                getHealthcheckInfo(database: string) {
         | 
| 354 | 
            -
                    return this.get<HealthCheckAPIResponse>( | 
| 355 | 
            -
                         | 
| 356 | 
            -
             | 
| 353 | 
            +
                getHealthcheckInfo(database: string, {concurrentId}: AxiosOptions = {}) {
         | 
| 354 | 
            +
                    return this.get<HealthCheckAPIResponse>(
         | 
| 355 | 
            +
                        this.getPath('/viewer/json/healthcheck'),
         | 
| 356 | 
            +
                        {tenant: database},
         | 
| 357 | 
            +
                        {concurrentId},
         | 
| 358 | 
            +
                    );
         | 
| 357 359 | 
             
                }
         | 
| 358 360 | 
             
                killTablet(id?: string) {
         | 
| 359 361 | 
             
                    return this.get<string>(this.getPath(`/tablets?KillTabletID=${id}`), {});
         | 
| @@ -44,6 +44,10 @@ const healthcheckInfo: Reducer<IHealthcheckInfoState, IHealthCheckInfoAction> = | |
| 44 44 | 
             
                        };
         | 
| 45 45 | 
             
                    }
         | 
| 46 46 | 
             
                    case FETCH_HEALTHCHECK.FAILURE: {
         | 
| 47 | 
            +
                        if (action.error?.isCancelled) {
         | 
| 48 | 
            +
                            return state;
         | 
| 49 | 
            +
                        }
         | 
| 50 | 
            +
             | 
| 47 51 | 
             
                        return {
         | 
| 48 52 | 
             
                            ...state,
         | 
| 49 53 | 
             
                            error: action.error,
         | 
| @@ -72,21 +76,25 @@ const mapStatusToPriority: Partial<Record<StatusFlag, number>> = { | |
| 72 76 | 
             
                GREEN: 4,
         | 
| 73 77 | 
             
            };
         | 
| 74 78 |  | 
| 75 | 
            -
            const  | 
| 76 | 
            -
                return data. | 
| 77 | 
            -
             | 
| 79 | 
            +
            const sortIssues = (data: IssueLog[]): IssueLog[] => {
         | 
| 80 | 
            +
                return data.sort((a, b) => {
         | 
| 81 | 
            +
                    const aPriority = mapStatusToPriority[a.status] || 0;
         | 
| 82 | 
            +
                    const bPriority = mapStatusToPriority[b.status] || 0;
         | 
| 78 83 |  | 
| 79 | 
            -
             | 
| 80 | 
            -
                let roots = data.filter((item) => {
         | 
| 81 | 
            -
                    return !data.find((issue) => issue.reason && issue.reason.indexOf(item.id) !== -1);
         | 
| 84 | 
            +
                    return aPriority - bPriority;
         | 
| 82 85 | 
             
                });
         | 
| 86 | 
            +
            };
         | 
| 83 87 |  | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
                ])(roots);
         | 
| 88 | 
            +
            const getReasonsForIssue = ({issue, data}: {issue: IssueLog; data: IssueLog[]}) => {
         | 
| 89 | 
            +
                return sortIssues(data.filter((item) => issue.reason && issue.reason.indexOf(item.id) !== -1));
         | 
| 90 | 
            +
            };
         | 
| 88 91 |  | 
| 89 | 
            -
             | 
| 92 | 
            +
            const getRoots = (data: IssueLog[]): IssueLog[] => {
         | 
| 93 | 
            +
                return sortIssues(
         | 
| 94 | 
            +
                    data.filter((item) => {
         | 
| 95 | 
            +
                        return !data.find((issue) => issue.reason && issue.reason.indexOf(item.id) !== -1);
         | 
| 96 | 
            +
                    }),
         | 
| 97 | 
            +
                );
         | 
| 90 98 | 
             
            };
         | 
| 91 99 |  | 
| 92 100 | 
             
            const getInvertedConsequencesTree = ({
         | 
| @@ -147,7 +155,7 @@ export const selectIssuesStatistics: Selector< | |
| 147 155 |  | 
| 148 156 | 
             
            export function getHealthcheckInfo(database: string) {
         | 
| 149 157 | 
             
                return createApiRequest({
         | 
| 150 | 
            -
                    request: window.api.getHealthcheckInfo(database),
         | 
| 158 | 
            +
                    request: window.api.getHealthcheckInfo(database, {concurrentId: 'getHealthcheckInfo'}),
         | 
| 151 159 | 
             
                    actions: FETCH_HEALTHCHECK,
         | 
| 152 160 | 
             
                });
         | 
| 153 161 | 
             
            }
         | 
| @@ -15,6 +15,7 @@ import { | |
| 15 15 | 
             
                LAST_USED_QUERY_ACTION_KEY,
         | 
| 16 16 | 
             
                USE_BACKEND_PARAMS_FOR_TABLES_KEY,
         | 
| 17 17 | 
             
                LANGUAGE_KEY,
         | 
| 18 | 
            +
                ENABLE_NEW_TENANT_DIAGNOSTICS_DESIGN,
         | 
| 18 19 | 
             
            } from '../../../utils/constants';
         | 
| 19 20 | 
             
            import '../../../services/api';
         | 
| 20 21 | 
             
            import {parseJson} from '../../../utils/utils';
         | 
| @@ -55,6 +56,10 @@ export const initialState = { | |
| 55 56 | 
             
                        ENABLE_ADDITIONAL_QUERY_MODES,
         | 
| 56 57 | 
             
                        'false',
         | 
| 57 58 | 
             
                    ),
         | 
| 59 | 
            +
                    [ENABLE_NEW_TENANT_DIAGNOSTICS_DESIGN]: readSavedSettingsValue(
         | 
| 60 | 
            +
                        ENABLE_NEW_TENANT_DIAGNOSTICS_DESIGN,
         | 
| 61 | 
            +
                        'false',
         | 
| 62 | 
            +
                    ),
         | 
| 58 63 | 
             
                    [SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
         | 
| 59 64 | 
             
                    [TENANT_INITIAL_PAGE_KEY]: readSavedSettingsValue(
         | 
| 60 65 | 
             
                        TENANT_INITIAL_PAGE_KEY,
         | 
| @@ -4,6 +4,7 @@ import type {TTenant} from '../../../types/api/tenant'; | |
| 4 4 | 
             
            import type {
         | 
| 5 5 | 
             
                TenantAction,
         | 
| 6 6 | 
             
                TenantDiagnosticsTab,
         | 
| 7 | 
            +
                TenantMetricsTab,
         | 
| 7 8 | 
             
                TenantPage,
         | 
| 8 9 | 
             
                TenantQueryTab,
         | 
| 9 10 | 
             
                TenantState,
         | 
| @@ -19,6 +20,7 @@ const SET_TOP_LEVEL_TAB = 'tenant/SET_TOP_LEVEL_TAB'; | |
| 19 20 | 
             
            const SET_QUERY_TAB = 'tenant/SET_QUERY_TAB';
         | 
| 20 21 | 
             
            const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
         | 
| 21 22 | 
             
            const SET_SUMMARY_TAB = 'tenant/SET_SUMMARY_TAB';
         | 
| 23 | 
            +
            const SET_METRICS_TAB = 'tenant/SET_METRICS_TAB';
         | 
| 22 24 | 
             
            const CLEAR_TENANT = 'tenant/CLEAR_TENANT';
         | 
| 23 25 | 
             
            const SET_DATA_WAS_NOT_LOADED = 'tenant/SET_DATA_WAS_NOT_LOADED';
         | 
| 24 26 |  | 
| @@ -88,6 +90,12 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState, | |
| 88 90 | 
             
                            summaryTab: action.data,
         | 
| 89 91 | 
             
                        };
         | 
| 90 92 | 
             
                    }
         | 
| 93 | 
            +
                    case SET_METRICS_TAB: {
         | 
| 94 | 
            +
                        return {
         | 
| 95 | 
            +
                            ...state,
         | 
| 96 | 
            +
                            metricsTab: action.data,
         | 
| 97 | 
            +
                        };
         | 
| 98 | 
            +
                    }
         | 
| 91 99 |  | 
| 92 100 | 
             
                    case SET_DATA_WAS_NOT_LOADED: {
         | 
| 93 101 | 
             
                        return {
         | 
| @@ -143,6 +151,13 @@ export function setSummaryTab(tab: TenantSummaryTab) { | |
| 143 151 | 
             
                } as const;
         | 
| 144 152 | 
             
            }
         | 
| 145 153 |  | 
| 154 | 
            +
            export function setMetricsTab(tab: TenantMetricsTab) {
         | 
| 155 | 
            +
                return {
         | 
| 156 | 
            +
                    type: SET_METRICS_TAB,
         | 
| 157 | 
            +
                    data: tab,
         | 
| 158 | 
            +
                } as const;
         | 
| 159 | 
            +
            }
         | 
| 160 | 
            +
             | 
| 146 161 | 
             
            export const setDataWasNotLoaded = () => {
         | 
| 147 162 | 
             
                return {
         | 
| 148 163 | 
             
                    type: SET_DATA_WAS_NOT_LOADED,
         | 
| @@ -8,6 +8,7 @@ import { | |
| 8 8 | 
             
                TENANT_DIAGNOSTICS_TABS_IDS,
         | 
| 9 9 | 
             
                TENANT_PAGES_IDS,
         | 
| 10 10 | 
             
                TENANT_SUMMARY_TABS_IDS,
         | 
| 11 | 
            +
                TENANT_METRICS_TABS_IDS,
         | 
| 11 12 | 
             
            } from './constants';
         | 
| 12 13 | 
             
            import {
         | 
| 13 14 | 
             
                FETCH_TENANT,
         | 
| @@ -15,6 +16,7 @@ import { | |
| 15 16 | 
             
                setDiagnosticsTab,
         | 
| 16 17 | 
             
                setQueryTab,
         | 
| 17 18 | 
             
                setSummaryTab,
         | 
| 19 | 
            +
                setMetricsTab,
         | 
| 18 20 | 
             
                setTenantPage,
         | 
| 19 21 | 
             
                setDataWasNotLoaded,
         | 
| 20 22 | 
             
            } from './tenant';
         | 
| @@ -24,6 +26,7 @@ export type TenantPage = ValueOf<typeof TENANT_PAGES_IDS>; | |
| 24 26 | 
             
            export type TenantQueryTab = ValueOf<typeof TENANT_QUERY_TABS_ID>;
         | 
| 25 27 | 
             
            export type TenantDiagnosticsTab = ValueOf<typeof TENANT_DIAGNOSTICS_TABS_IDS>;
         | 
| 26 28 | 
             
            export type TenantSummaryTab = ValueOf<typeof TENANT_SUMMARY_TABS_IDS>;
         | 
| 29 | 
            +
            export type TenantMetricsTab = ValueOf<typeof TENANT_METRICS_TABS_IDS>;
         | 
| 27 30 |  | 
| 28 31 | 
             
            export interface TenantState {
         | 
| 29 32 | 
             
                loading: boolean;
         | 
| @@ -32,6 +35,7 @@ export interface TenantState { | |
| 32 35 | 
             
                queryTab?: TenantQueryTab;
         | 
| 33 36 | 
             
                diagnosticsTab?: TenantDiagnosticsTab;
         | 
| 34 37 | 
             
                summaryTab?: TenantSummaryTab;
         | 
| 38 | 
            +
                metricsTab?: TenantMetricsTab;
         | 
| 35 39 | 
             
                tenant?: TTenant;
         | 
| 36 40 | 
             
                error?: IResponseError;
         | 
| 37 41 | 
             
            }
         | 
| @@ -43,4 +47,5 @@ export type TenantAction = | |
| 43 47 | 
             
                | ReturnType<typeof setQueryTab>
         | 
| 44 48 | 
             
                | ReturnType<typeof setDiagnosticsTab>
         | 
| 45 49 | 
             
                | ReturnType<typeof setSummaryTab>
         | 
| 50 | 
            +
                | ReturnType<typeof setMetricsTab>
         | 
| 46 51 | 
             
                | ReturnType<typeof setDataWasNotLoaded>;
         | 
| @@ -1,8 +1,10 @@ | |
| 1 1 | 
             
            import {FETCH_TENANTS, setSearchValue} from './tenants';
         | 
| 2 2 |  | 
| 3 | 
            +
            import {ValueOf} from '../../../types/common';
         | 
| 3 4 | 
             
            import type {TTenant} from '../../../types/api/tenant';
         | 
| 4 5 | 
             
            import type {IResponseError} from '../../../types/api/error';
         | 
| 5 6 | 
             
            import type {ApiRequestAction} from '../../utils';
         | 
| 7 | 
            +
            import {METRIC_STATUS} from './contants';
         | 
| 6 8 |  | 
| 7 9 | 
             
            export interface PreparedTenant extends TTenant {
         | 
| 8 10 | 
             
                backend: string | undefined;
         | 
| @@ -30,3 +32,5 @@ export type TenantsAction = | |
| 30 32 | 
             
            export interface TenantsStateSlice {
         | 
| 31 33 | 
             
                tenants: TenantsState;
         | 
| 32 34 | 
             
            }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            export type MetricStatus = ValueOf<typeof METRIC_STATUS>;
         |