From 1822f355b2b510811037a836e44970f12bcee1b2 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Fri, 12 Sep 2025 19:09:52 +0300 Subject: [PATCH 1/2] fix: write network info for tenant same as for cluster --- .../MetricsTabs/CommonMetricsTabs.tsx | 89 ----------- .../MetricsTabs/DedicatedMetricsTabs.tsx | 70 --------- .../MetricsTabs/MetricsTabs.tsx | 53 ++++--- .../MetricsTabs/ServerlessPlaceholderTabs.tsx | 32 ---- .../MetricsTabs/components/CpuTab.tsx | 44 ++++++ .../MetricsTabs/components/MemoryTab.tsx | 33 ++++ .../MetricsTabs/components/NetworkTab.tsx | 49 ++++++ .../MetricsTabs/components/PlaceholderTab.tsx | 22 +++ .../MetricsTabs/components/StorageTab.tsx | 65 ++++++++ .../TabCard/ServerlessTabCard.tsx | 38 +++++ .../TenantOverview/TabCard/TabCard.tsx | 142 ------------------ .../TenantOverview/TabCard/UsageTabCard.tsx | 79 ++++++++++ .../TabCard/UtilizationTabCard.tsx | 83 ++++++++++ .../TenantOverview/TenantOverview.tsx | 6 +- src/store/reducers/tenants/utils.ts | 21 ++- 15 files changed, 459 insertions(+), 367 deletions(-) delete mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/CommonMetricsTabs.tsx delete mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/DedicatedMetricsTabs.tsx delete mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/ServerlessPlaceholderTabs.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/CpuTab.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/MemoryTab.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/NetworkTab.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/PlaceholderTab.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/StorageTab.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/TabCard/ServerlessTabCard.tsx delete mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/TabCard/TabCard.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx create mode 100644 src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/CommonMetricsTabs.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/CommonMetricsTabs.tsx deleted file mode 100644 index 39cf5213bc..0000000000 --- a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/CommonMetricsTabs.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import {Link} from 'react-router-dom'; - -import {TENANT_METRICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants'; -import type {TenantMetricsTab} from '../../../../../store/reducers/tenant/types'; -import type {ETenantType} from '../../../../../types/api/tenant'; -import {cn} from '../../../../../utils/cn'; -import { - formatCoresLegend, - formatStorageLegend, -} from '../../../../../utils/metrics/formatMetricLegend'; -import {TabCard} from '../TabCard/TabCard'; -import i18n from '../i18n'; - -const b = cn('tenant-metrics-tabs'); - -interface CommonMetricsTabsProps { - activeTab: TenantMetricsTab; - tabLinks: Record; - cpu: {totalUsed: number; totalLimit: number}; - storage: {totalUsed: number; totalLimit: number}; - storageGroupsCount?: number; - databaseType?: ETenantType; -} - -export function CommonMetricsTabs({ - activeTab, - tabLinks, - cpu, - storage, - storageGroupsCount, - databaseType, -}: CommonMetricsTabsProps) { - const isServerless = databaseType === 'Serverless'; - - return ( - <> -
- - - -
-
- - - -
- - ); -} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/DedicatedMetricsTabs.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/DedicatedMetricsTabs.tsx deleted file mode 100644 index 21e0da39bb..0000000000 --- a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/DedicatedMetricsTabs.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import {Link} from 'react-router-dom'; - -import {TENANT_METRICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants'; -import type {TenantMetricsTab} from '../../../../../store/reducers/tenant/types'; -import {cn} from '../../../../../utils/cn'; -import { - formatSpeedLegend, - formatStorageLegend, -} from '../../../../../utils/metrics/formatMetricLegend'; -import {TabCard} from '../TabCard/TabCard'; -import i18n from '../i18n'; - -const b = cn('tenant-metrics-tabs'); - -interface DedicatedMetricsTabsProps { - activeTab: TenantMetricsTab; - tabLinks: Record; - memory: {totalUsed: number; totalLimit: number}; - network: {totalUsed: number; totalLimit: number} | null; - showNetwork: boolean; -} - -export function DedicatedMetricsTabs({ - activeTab, - tabLinks, - memory, - network, - showNetwork, -}: DedicatedMetricsTabsProps) { - return ( - <> -
- - - -
- {showNetwork && network && ( -
- - - -
- )} - - ); -} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx index 8a780224e5..11a8e1da5f 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx @@ -19,9 +19,11 @@ import {calculateMetricAggregates} from '../../../../../utils/metrics'; // no direct legend formatters needed here – handled in subcomponents import {TenantTabsGroups, getTenantPath} from '../../../TenantPages'; -import {CommonMetricsTabs} from './CommonMetricsTabs'; -import {DedicatedMetricsTabs} from './DedicatedMetricsTabs'; -import {ServerlessPlaceholderTabs} from './ServerlessPlaceholderTabs'; +import {CpuTab} from './components/CpuTab'; +import {MemoryTab} from './components/MemoryTab'; +import {NetworkTab} from './components/NetworkTab'; +import {PlaceholderTab} from './components/PlaceholderTab'; +import {StorageTab} from './components/StorageTab'; import './MetricsTabs.scss'; @@ -32,7 +34,8 @@ interface MetricsTabsProps { memoryStats?: TenantMetricStats[]; blobStorageStats?: TenantStorageStats[]; tabletStorageStats?: TenantStorageStats[]; - networkStats?: TenantMetricStats[]; + networkUtilization?: number; + networkThroughput?: number; storageGroupsCount?: number; databaseType?: ETenantType; activeTab: TenantMetricsTab; @@ -43,7 +46,8 @@ export function MetricsTabs({ memoryStats, blobStorageStats, tabletStorageStats, - networkStats, + networkUtilization, + networkThroughput, storageGroupsCount, databaseType, activeTab, @@ -88,12 +92,8 @@ export function MetricsTabs({ // Calculate memory metrics using utility const memoryMetrics = useMemo(() => calculateMetricAggregates(memoryStats), [memoryStats]); - // Calculate network metrics using utility + // Pass raw network values; DedicatedMetricsTabs computes percent and legend const [showNetworkUtilization] = useSetting(SHOW_NETWORK_UTILIZATION); - const networkMetrics = useMemo( - () => (networkStats ? calculateMetricAggregates(networkStats) : null), - [networkStats], - ); // card variant is handled within subcomponents @@ -101,29 +101,42 @@ export function MetricsTabs({ return ( - + {isServerless ? ( - + ) : ( - + )} + {isServerless || !showNetworkUtilization ? ( + + ) : ( + )} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/ServerlessPlaceholderTabs.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/ServerlessPlaceholderTabs.tsx deleted file mode 100644 index 6eb3428e3c..0000000000 --- a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/ServerlessPlaceholderTabs.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; - -import {cn} from '../../../../../utils/cn'; -import {NON_BREAKING_SPACE} from '../../../../../utils/constants'; -import {TabCard} from '../TabCard/TabCard'; - -import './MetricsTabs.scss'; - -const b = cn('tenant-metrics-tabs'); - -interface ServerlessPlaceholderTabsProps { - count?: number; -} - -export const ServerlessPlaceholderTabs: React.FC = React.memo( - ({count = 2}) => { - const items = React.useMemo(() => Array.from({length: count}, (_, i) => i), [count]); - - return items.map((idx) => ( -
-
- -
-
- )); - }, -); diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/CpuTab.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/CpuTab.tsx new file mode 100644 index 0000000000..dc039abd73 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/CpuTab.tsx @@ -0,0 +1,44 @@ +import {Link} from 'react-router-dom'; + +import {cn} from '../../../../../../utils/cn'; +import {formatCoresLegend} from '../../../../../../utils/metrics/formatMetricLegend'; +import {ServerlessTabCard} from '../../TabCard/ServerlessTabCard'; +import {UsageTabCard} from '../../TabCard/UsageTabCard'; +import i18n from '../../i18n'; + +import '../MetricsTabs.scss'; + +const b = cn('tenant-metrics-tabs'); + +interface CpuTabProps { + to: string; + active: boolean; + isServerless: boolean; + cpu: {totalUsed: number; totalLimit: number}; +} + +export function CpuTab({to, active, isServerless, cpu}: CpuTabProps) { + return ( +
+ + {isServerless ? ( + + ) : ( + + )} + +
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/MemoryTab.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/MemoryTab.tsx new file mode 100644 index 0000000000..7985726a37 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/MemoryTab.tsx @@ -0,0 +1,33 @@ +import {Link} from 'react-router-dom'; + +import {cn} from '../../../../../../utils/cn'; +import {formatStorageLegend} from '../../../../../../utils/metrics/formatMetricLegend'; +import {UsageTabCard} from '../../TabCard/UsageTabCard'; +import i18n from '../../i18n'; + +import '../MetricsTabs.scss'; + +const b = cn('tenant-metrics-tabs'); + +interface MemoryTabProps { + to: string; + active: boolean; + memory: {totalUsed: number; totalLimit: number}; +} + +export function MemoryTab({to, active, memory}: MemoryTabProps) { + return ( +
+ + + +
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/NetworkTab.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/NetworkTab.tsx new file mode 100644 index 0000000000..7f6d4a9778 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/NetworkTab.tsx @@ -0,0 +1,49 @@ +import {Link} from 'react-router-dom'; + +import {formatBytes} from '../../../../../../utils/bytesParsers/formatBytes'; +import {cn} from '../../../../../../utils/cn'; +import {UtilizationTabCard} from '../../TabCard/UtilizationTabCard'; +import i18n from '../../i18n'; + +import {PlaceholderTab} from './PlaceholderTab'; + +import '../MetricsTabs.scss'; + +const b = cn('tenant-metrics-tabs'); + +interface NetworkTabProps { + to: string; + active: boolean; + networkUtilization?: number; + networkThroughput?: number; +} + +export function NetworkTab({to, active, networkUtilization, networkThroughput}: NetworkTabProps) { + const canShow = + networkUtilization !== undefined && + networkThroughput !== undefined && + isFinite(networkUtilization) && + isFinite(networkThroughput) && + networkThroughput > 0; + + if (!canShow) { + return ; + } + + const fillPercent = networkUtilization * 100; + const legendText = formatBytes({value: networkThroughput, withSpeedLabel: true}); + + return ( +
+ + + +
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/PlaceholderTab.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/PlaceholderTab.tsx new file mode 100644 index 0000000000..b1b13cc1e1 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/PlaceholderTab.tsx @@ -0,0 +1,22 @@ +import {cn} from '../../../../../../utils/cn'; +import {NON_BREAKING_SPACE} from '../../../../../../utils/constants'; +import {ServerlessTabCard} from '../../TabCard/ServerlessTabCard'; + +import '../MetricsTabs.scss'; + +const b = cn('tenant-metrics-tabs'); + +export function PlaceholderTab() { + return ( +
+
+ +
+
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/StorageTab.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/StorageTab.tsx new file mode 100644 index 0000000000..431b00fea4 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/components/StorageTab.tsx @@ -0,0 +1,65 @@ +import {Link} from 'react-router-dom'; + +import {cn} from '../../../../../../utils/cn'; +import {formatStorageLegend} from '../../../../../../utils/metrics/formatMetricLegend'; +import {ServerlessTabCard} from '../../TabCard/ServerlessTabCard'; +import {UsageTabCard} from '../../TabCard/UsageTabCard'; +import i18n from '../../i18n'; + +import '../MetricsTabs.scss'; + +const b = cn('tenant-metrics-tabs'); + +interface StorageTabProps { + to: string; + active: boolean; + isServerless: boolean; + storage: {totalUsed: number; totalLimit: number}; + storageGroupsCount?: number; +} + +export function StorageTab({ + to, + active, + isServerless, + storage, + storageGroupsCount, +}: StorageTabProps) { + const text = + storageGroupsCount === undefined || isServerless + ? i18n('cards.storage-label') + : i18n('context_storage-groups', {count: storageGroupsCount}); + return ( +
+ + {isServerless ? ( + + ) : ( + + )} + +
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/ServerlessTabCard.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/ServerlessTabCard.tsx new file mode 100644 index 0000000000..31f7d12d64 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/ServerlessTabCard.tsx @@ -0,0 +1,38 @@ +import {Card} from '@gravity-ui/uikit'; + +import {DoughnutMetrics} from '../../../../../components/DoughnutMetrics/DoughnutMetrics'; +import {cn} from '../../../../../utils/cn'; + +import './TabCard.scss'; + +const b = cn('tenant-tab-card'); + +interface ServerlessTabCardProps { + text: string; + active?: boolean; + helpText?: string; + subtitle?: string; +} + +export function ServerlessTabCard({text, active, helpText, subtitle}: ServerlessTabCardProps) { + return ( +
+ +
+ + {text} + + {subtitle ? ( + + {subtitle} + + ) : null} +
+
+
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/TabCard.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/TabCard.tsx deleted file mode 100644 index ee30d0f347..0000000000 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/TabCard.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import React, {useMemo} from 'react'; - -import {Card, Flex} from '@gravity-ui/uikit'; - -import {DoughnutMetrics} from '../../../../../components/DoughnutMetrics/DoughnutMetrics'; -import {getDiagramValues} from '../../../../../containers/Cluster/ClusterOverview/utils'; -import type {ETenantType} from '../../../../../types/api/tenant'; -import {cn} from '../../../../../utils/cn'; - -import './TabCard.scss'; - -const b = cn('tenant-tab-card'); - -interface TabCardBaseProps { - text: string; - active?: boolean; - helpText?: string; - subtitle?: string; -} - -interface TabCardDefaultProps extends TabCardBaseProps { - databaseType?: Exclude; - value: number; - limit: number; - legendFormatter: (params: {value: number; capacity: number}) => string; -} - -interface TabCardServerlessProps extends TabCardBaseProps { - databaseType: 'Serverless'; -} - -type TabCardProps = TabCardDefaultProps | TabCardServerlessProps; - -function isServerlessProps(props: TabCardProps): props is TabCardServerlessProps { - return props.databaseType === 'Serverless'; -} - -function TabCardContainer({active, children}: {active?: boolean; children: React.ReactNode}) { - return ( -
- - {children} - -
- ); -} - -const TabCardDefaultContent = React.memo(function TabCardDefaultContent({ - text, - value, - limit, - helpText, - legendFormatter, -}: { - text: string; - value: number; - limit: number; - helpText?: string; - legendFormatter: (params: {value: number; capacity: number}) => string; -}) { - const diagram = useMemo( - () => getDiagramValues({value, capacity: limit, legendFormatter}), - [value, limit, legendFormatter], - ); - - const {status, percents, legend, fill} = diagram; - - return ( - - - {percents} - -
- {legend} - - {text} - -
-
- ); -}); - -const TabCardServerlessContent = React.memo(function TabCardServerlessContent({ - text, - helpText, - subtitle, -}: { - text: string; - helpText?: string; - subtitle?: string; -}) { - return ( -
- - {text} - - {subtitle ? ( - - {subtitle} - - ) : null} -
- ); -}); - -export function TabCard(props: TabCardProps) { - const {active} = props; - - return ( - - {isServerlessProps(props) ? ( - - ) : ( - - )} - - ); -} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx new file mode 100644 index 0000000000..ab7b6469e1 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx @@ -0,0 +1,79 @@ +import React from 'react'; + +import {Card, Flex} from '@gravity-ui/uikit'; + +import {DoughnutMetrics} from '../../../../../components/DoughnutMetrics/DoughnutMetrics'; +import {getDiagramValues} from '../../../../../containers/Cluster/ClusterOverview/utils'; +import type {ETenantType} from '../../../../../types/api/tenant'; +import {cn} from '../../../../../utils/cn'; + +import './TabCard.scss'; + +const b = cn('tenant-tab-card'); + +interface UsageTabCardProps { + text: string; + active?: boolean; + helpText?: string; + subtitle?: string; + databaseType?: Exclude; + value: number; + limit: number; + legendFormatter: (params: {value: number; capacity: number}) => string; +} + +function UsageCardContainer({active, children}: {active?: boolean; children: React.ReactNode}) { + return ( +
+ + {children} + +
+ ); +} + +export function UsageTabCard({ + text, + value, + limit, + helpText, + legendFormatter, + active, +}: UsageTabCardProps) { + const diagram = React.useMemo( + () => getDiagramValues({value, capacity: limit, legendFormatter}), + [value, limit, legendFormatter], + ); + + const {status, percents, legend, fill} = diagram; + + return ( + + + + {percents} + +
+ {legend} + + {text} + +
+
+
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx new file mode 100644 index 0000000000..70ee8da3d9 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx @@ -0,0 +1,83 @@ +import React from 'react'; + +import {Card, Flex} from '@gravity-ui/uikit'; + +import {DoughnutMetrics} from '../../../../../components/DoughnutMetrics/DoughnutMetrics'; +import {calculateBaseDiagramValues} from '../../../../../containers/Cluster/ClusterOverview/utils'; +import type {ETenantType} from '../../../../../types/api/tenant'; +import {cn} from '../../../../../utils/cn'; + +import './TabCard.scss'; + +const b = cn('tenant-tab-card'); + +interface UtilizationTabCardProps { + text: string; + active?: boolean; + helpText?: string; + subtitle?: string; + databaseType?: Exclude; + fillPercent: number; // 0..100 + legendText: string; +} + +function UtilizationCardContainer({ + active, + children, +}: { + active?: boolean; + children: React.ReactNode; +}) { + return ( +
+ + {children} + +
+ ); +} + +export function UtilizationTabCard({ + text, + fillPercent, + helpText, + legendText, + active, +}: UtilizationTabCardProps) { + const {status, percents, fill} = React.useMemo( + () => calculateBaseDiagramValues({fillWidth: fillPercent}), + [fillPercent], + ); + + return ( + + + + {percents} + +
+ + {legendText} + + + {text} + +
+
+
+ ); +} diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx index e6997c3811..34e52464f1 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx @@ -99,7 +99,8 @@ export function TenantOverview({ memoryStats, blobStorageStats, tabletStorageStats, - networkStats, + networkUtilization, + networkThroughput, } = calculateTenantMetrics(tenantData); const storageMetrics = { @@ -211,7 +212,8 @@ export function TenantOverview({ memoryStats={memoryStats} blobStorageStats={blobStorageStats} tabletStorageStats={tabletStorageStats} - networkStats={networkStats} + networkUtilization={networkUtilization} + networkThroughput={networkThroughput} storageGroupsCount={ tenantData.StorageGroups ? Number(tenantData.StorageGroups) diff --git a/src/store/reducers/tenants/utils.ts b/src/store/reducers/tenants/utils.ts index 503a53c99c..60448c9cc1 100644 --- a/src/store/reducers/tenants/utils.ts +++ b/src/store/reducers/tenants/utils.ts @@ -148,17 +148,13 @@ export const calculateTenantMetrics = (tenant: TTenant = {}) => { }, ]; - const isNetworkStatsAvailabe = !isNil(NetworkUtilization) && !isNil(NetworkWriteThroughput); - const networkThroughput = safeParseNumber(NetworkWriteThroughput); - const usedNetwork = safeParseNumber(NetworkUtilization) * networkThroughput; - const networkStats: TenantMetricStats[] | undefined = isNetworkStatsAvailabe - ? [ - { - used: usedNetwork, - limit: networkThroughput, - }, - ] - : undefined; + // Expose raw network utilization and throughput for consumers. + const networkUtilization = isNil(NetworkUtilization) + ? undefined + : safeParseNumber(NetworkUtilization); + const networkThroughput = isNil(NetworkWriteThroughput) + ? undefined + : safeParseNumber(NetworkWriteThroughput); return { memory, @@ -173,7 +169,8 @@ export const calculateTenantMetrics = (tenant: TTenant = {}) => { memoryStats, blobStorageStats, tabletStorageStats, - networkStats, + networkUtilization, + networkThroughput, }; }; From 022becd6004f5a3c688b7df77a82710be764a933 Mon Sep 17 00:00:00 2001 From: Anton Standrik Date: Fri, 12 Sep 2025 19:17:57 +0300 Subject: [PATCH 2/2] fix: some nanofixes --- .../MetricsTabs/MetricsTabs.tsx | 30 ++++++++++++------- .../TenantOverview/TabCard/UsageTabCard.tsx | 3 -- .../TabCard/UtilizationTabCard.tsx | 3 -- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx index 11a8e1da5f..963d9ea65a 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/MetricsTabs/MetricsTabs.tsx @@ -99,6 +99,25 @@ export function MetricsTabs({ const isServerless = databaseType === 'Serverless'; + const renderNetworkTab = () => { + if (!showNetworkUtilization) { + return null; + } + + if (isServerless) { + return ; + } + + return ( + + ); + }; + return ( )} - {isServerless || !showNetworkUtilization ? ( - - ) : ( - - )} + {renderNetworkTab()} ); } diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx index ab7b6469e1..8f7cd9eb30 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UsageTabCard.tsx @@ -4,7 +4,6 @@ import {Card, Flex} from '@gravity-ui/uikit'; import {DoughnutMetrics} from '../../../../../components/DoughnutMetrics/DoughnutMetrics'; import {getDiagramValues} from '../../../../../containers/Cluster/ClusterOverview/utils'; -import type {ETenantType} from '../../../../../types/api/tenant'; import {cn} from '../../../../../utils/cn'; import './TabCard.scss'; @@ -15,8 +14,6 @@ interface UsageTabCardProps { text: string; active?: boolean; helpText?: string; - subtitle?: string; - databaseType?: Exclude; value: number; limit: number; legendFormatter: (params: {value: number; capacity: number}) => string; diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx index 70ee8da3d9..1ed3dcd3bb 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TabCard/UtilizationTabCard.tsx @@ -4,7 +4,6 @@ import {Card, Flex} from '@gravity-ui/uikit'; import {DoughnutMetrics} from '../../../../../components/DoughnutMetrics/DoughnutMetrics'; import {calculateBaseDiagramValues} from '../../../../../containers/Cluster/ClusterOverview/utils'; -import type {ETenantType} from '../../../../../types/api/tenant'; import {cn} from '../../../../../utils/cn'; import './TabCard.scss'; @@ -15,8 +14,6 @@ interface UtilizationTabCardProps { text: string; active?: boolean; helpText?: string; - subtitle?: string; - databaseType?: Exclude; fillPercent: number; // 0..100 legendText: string; }