From bd54eabcb7c0f7e39e8c761a4c2c47cb70779a47 Mon Sep 17 00:00:00 2001 From: mufazalov Date: Sun, 6 Oct 2024 15:01:17 +0300 Subject: [PATCH 1/2] refactor: use the same nodes columns in all tables --- .../NodeHostWrapper/NodeHostWrapper.tsx | 10 +- .../TabletsStatistic/TabletsStatistic.tsx | 11 +- src/components/nodesColumns/columns.tsx | 231 ++++++++++++++ src/components/nodesColumns/constants.ts | 75 +++++ .../nodesColumns}/i18n/en.json | 6 +- .../nodesColumns}/i18n/index.ts | 2 +- src/components/nodesColumns/types.ts | 11 + src/containers/Nodes/Nodes.tsx | 2 +- src/containers/Nodes/PaginatedNodes.tsx | 2 +- src/containers/Nodes/columns/columns.tsx | 290 ++---------------- src/containers/Nodes/columns/constants.ts | 75 +---- src/containers/Nodes/columns/hooks.ts | 6 +- src/containers/Nodes/columns/types.ts | 13 - .../Storage/StorageNodes/columns/columns.tsx | 135 +++----- .../Storage/StorageNodes/columns/constants.ts | 34 +- .../Storage/StorageNodes/columns/hooks.ts | 8 +- .../Storage/StorageNodes/columns/i18n/en.json | 7 - .../Storage/StorageNodes/columns/types.ts | 9 +- src/containers/Storage/utils/index.ts | 2 +- .../TenantCpu/TopNodesByCpu.tsx | 34 +- .../TenantCpu/TopNodesByLoad.tsx | 35 ++- .../TenantMemory/TopNodesByMemory.tsx | 41 ++- .../Diagnostics/TenantOverview/i18n/en.json | 4 +- src/store/reducers/nodes/types.ts | 12 +- src/store/reducers/nodes/utils.ts | 6 - src/utils/nodes.ts | 21 +- 26 files changed, 556 insertions(+), 526 deletions(-) create mode 100644 src/components/nodesColumns/columns.tsx create mode 100644 src/components/nodesColumns/constants.ts rename src/{containers/Nodes/columns => components/nodesColumns}/i18n/en.json (78%) rename src/{containers/Nodes/columns => components/nodesColumns}/i18n/index.ts (68%) create mode 100644 src/components/nodesColumns/types.ts delete mode 100644 src/containers/Nodes/columns/types.ts diff --git a/src/components/NodeHostWrapper/NodeHostWrapper.tsx b/src/components/NodeHostWrapper/NodeHostWrapper.tsx index e3ce1a4fcb..08f2a29a59 100644 --- a/src/components/NodeHostWrapper/NodeHostWrapper.tsx +++ b/src/components/NodeHostWrapper/NodeHostWrapper.tsx @@ -1,8 +1,8 @@ import {PopoverBehavior} from '@gravity-ui/uikit'; import {getDefaultNodePath} from '../../containers/Node/NodePages'; -import type {NodesPreparedEntity} from '../../store/reducers/nodes/types'; import type {NodeAddress} from '../../types/additionalProps'; +import type {TSystemStateInfo} from '../../types/api/nodes'; import {createDeveloperUILinkWithNodeId} from '../../utils/developerUI/developerUI'; import {isUnavailableNode} from '../../utils/nodes'; import {CellWithPopover} from '../CellWithPopover/CellWithPopover'; @@ -10,8 +10,14 @@ import {DeveloperUILinkButton} from '../DeveloperUILinkButton/DeveloperUILinkBut import {EntityStatus} from '../EntityStatus/EntityStatus'; import {NodeEndpointsTooltipContent} from '../TooltipsContent'; +export type NodeHostData = NodeAddress & + Pick & { + NodeId: string | number; + TenantName?: string; + }; + interface NodeHostWrapperProps { - node: NodesPreparedEntity; + node: NodeHostData; getNodeRef?: (node?: NodeAddress) => string | null; database?: string; } diff --git a/src/components/TabletsStatistic/TabletsStatistic.tsx b/src/components/TabletsStatistic/TabletsStatistic.tsx index e3c87a1bb8..42d0c0a573 100644 --- a/src/components/TabletsStatistic/TabletsStatistic.tsx +++ b/src/components/TabletsStatistic/TabletsStatistic.tsx @@ -26,18 +26,23 @@ const prepareTablets = (tablets: TTabletStateInfo[]) => { interface TabletsStatisticProps { tablets: TTabletStateInfo[]; - path: string | undefined; + tenantName: string | undefined; nodeId: string | number; backend?: string; } -export const TabletsStatistic = ({tablets = [], path, nodeId, backend}: TabletsStatisticProps) => { +export const TabletsStatistic = ({ + tablets = [], + tenantName, + nodeId, + backend, +}: TabletsStatisticProps) => { const renderTabletInfo = (item: ReturnType[number], index: number) => { const tabletsPath = createHref( routes.node, {id: nodeId, activeTab: TABLETS}, { - tenantName: path, + tenantName, backend, }, ); diff --git a/src/components/nodesColumns/columns.tsx b/src/components/nodesColumns/columns.tsx new file mode 100644 index 0000000000..7f654a437f --- /dev/null +++ b/src/components/nodesColumns/columns.tsx @@ -0,0 +1,231 @@ +import DataTable from '@gravity-ui/react-data-table'; + +import {getLoadSeverityForNode} from '../../store/reducers/nodes/utils'; +import type {TPoolStats} from '../../types/api/nodes'; +import type {TTabletStateInfo} from '../../types/api/tablet'; +import {EMPTY_DATA_PLACEHOLDER} from '../../utils/constants'; +import {formatStorageValuesToGb} from '../../utils/dataFormatters/dataFormatters'; +import {CellWithPopover} from '../CellWithPopover/CellWithPopover'; +import {NodeHostWrapper} from '../NodeHostWrapper/NodeHostWrapper'; +import type {NodeHostData} from '../NodeHostWrapper/NodeHostWrapper'; +import {PoolsGraph} from '../PoolsGraph/PoolsGraph'; +import {ProgressViewer} from '../ProgressViewer/ProgressViewer'; +import {TabletsStatistic} from '../TabletsStatistic'; +import {UsageLabel} from '../UsageLabel/UsageLabel'; + +import {NODES_COLUMNS_IDS, NODES_COLUMNS_TITLES} from './constants'; +import type {Column, GetNodesColumnsParams} from './types'; + +export function getNodeIdColumn(): Column { + return { + name: NODES_COLUMNS_IDS.NodeId, + header: '#', + width: 80, + render: ({row}) => row.NodeId, + align: DataTable.RIGHT, + }; +} +export function getHostColumn({ + getNodeRef, + database, +}: GetNodesColumnsParams): Column { + return { + name: NODES_COLUMNS_IDS.Host, + header: NODES_COLUMNS_TITLES.Host, + render: ({row}) => { + return ; + }, + width: 350, + align: DataTable.LEFT, + }; +} +export function getNodeNameColumn(): Column { + return { + name: NODES_COLUMNS_IDS.NodeName, + header: NODES_COLUMNS_TITLES.NodeName, + align: DataTable.LEFT, + render: ({row}) => row.NodeName || EMPTY_DATA_PLACEHOLDER, + width: 200, + }; +} +export function getDataCenterColumn(): Column { + return { + name: NODES_COLUMNS_IDS.DC, + header: NODES_COLUMNS_TITLES.DC, + align: DataTable.LEFT, + render: ({row}) => row.DC || EMPTY_DATA_PLACEHOLDER, + width: 60, + }; +} +export function getRackColumn(): Column { + return { + name: NODES_COLUMNS_IDS.Rack, + header: NODES_COLUMNS_TITLES.Rack, + align: DataTable.LEFT, + render: ({row}) => row.Rack || EMPTY_DATA_PLACEHOLDER, + width: 100, + }; +} +export function getVersionColumn(): Column { + return { + name: NODES_COLUMNS_IDS.Version, + header: NODES_COLUMNS_TITLES.Version, + width: 200, + align: DataTable.LEFT, + render: ({row}) => { + return {row.Version}; + }, + }; +} +export function getUptimeColumn(): Column { + return { + name: NODES_COLUMNS_IDS.Uptime, + header: NODES_COLUMNS_TITLES.Uptime, + sortAccessor: ({StartTime}) => (StartTime ? -StartTime : 0), + render: ({row}) => row.Uptime, + align: DataTable.RIGHT, + width: 110, + }; +} +export function getMemoryColumn< + T extends {MemoryUsed?: string; MemoryLimit?: string}, +>(): Column { + return { + name: NODES_COLUMNS_IDS.Memory, + header: NODES_COLUMNS_TITLES.Memory, + sortAccessor: ({MemoryUsed = 0}) => Number(MemoryUsed), + defaultOrder: DataTable.DESCENDING, + render: ({row}) => ( + + ), + align: DataTable.LEFT, + width: 140, + resizeMinWidth: 140, + }; +} +export function getSharedCacheUsageColumn< + T extends {SharedCacheUsed?: string | number; SharedCacheLimit?: string | number}, +>(): Column { + return { + name: NODES_COLUMNS_IDS.SharedCacheUsage, + header: NODES_COLUMNS_TITLES.SharedCacheUsage, + render: ({row}) => ( + + ), + align: DataTable.LEFT, + width: 140, + resizeMinWidth: 140, + }; +} +export function getCpuColumn(): Column { + return { + name: NODES_COLUMNS_IDS.CPU, + header: NODES_COLUMNS_TITLES.CPU, + sortAccessor: ({PoolStats = []}) => Math.max(...PoolStats.map(({Usage}) => Number(Usage))), + defaultOrder: DataTable.DESCENDING, + render: ({row}) => + row.PoolStats ? : EMPTY_DATA_PLACEHOLDER, + align: DataTable.LEFT, + width: 80, + resizeMinWidth: 60, + }; +} +export function getLoadAverageColumn(): Column { + return { + name: NODES_COLUMNS_IDS.LoadAverage, + header: NODES_COLUMNS_TITLES.LoadAverage, + sortAccessor: ({LoadAveragePercents = []}) => LoadAveragePercents[0], + defaultOrder: DataTable.DESCENDING, + render: ({row}) => ( + 0 + ? row.LoadAveragePercents[0] + : undefined + } + percents={true} + colorizeProgress={true} + capacity={100} + /> + ), + align: DataTable.LEFT, + width: 140, + resizeMinWidth: 140, + }; +} +// The same as loadAverage, but more compact +export function getLoadColumn(): Column { + return { + name: NODES_COLUMNS_IDS.Load, + header: NODES_COLUMNS_TITLES.Load, + sortAccessor: ({LoadAveragePercents = []}) => LoadAveragePercents[0], + defaultOrder: DataTable.DESCENDING, + render: ({row}) => + row.LoadAveragePercents && row.LoadAveragePercents.length > 0 ? ( + + ) : ( + EMPTY_DATA_PLACEHOLDER + ), + align: DataTable.LEFT, + width: 80, + resizeMinWidth: 70, + }; +} +export function getSessionsColumn(): Column { + return { + name: NODES_COLUMNS_IDS.TotalSessions, + header: NODES_COLUMNS_TITLES.TotalSessions, + render: ({row}) => row.TotalSessions ?? EMPTY_DATA_PLACEHOLDER, + align: DataTable.RIGHT, + width: 100, + }; +} +export function getTabletsColumn< + T extends { + TenantName?: string; + NodeId: string | number; + Tablets?: TTabletStateInfo[]; + }, +>({database}: GetNodesColumnsParams): Column { + return { + name: NODES_COLUMNS_IDS.Tablets, + header: NODES_COLUMNS_TITLES.Tablets, + width: 500, + resizeMinWidth: 500, + render: ({row}) => { + return row.Tablets ? ( + + ) : ( + EMPTY_DATA_PLACEHOLDER + ); + }, + align: DataTable.LEFT, + sortable: false, + }; +} +export function getMissingDisksColumn(): Column { + return { + name: NODES_COLUMNS_IDS.Missing, + header: NODES_COLUMNS_TITLES.Missing, + render: ({row}) => row.Missing, + align: DataTable.CENTER, + defaultOrder: DataTable.DESCENDING, + }; +} diff --git a/src/components/nodesColumns/constants.ts b/src/components/nodesColumns/constants.ts new file mode 100644 index 0000000000..587de24513 --- /dev/null +++ b/src/components/nodesColumns/constants.ts @@ -0,0 +1,75 @@ +import type {ValueOf} from '../../types/common'; + +import i18n from './i18n'; + +export const NODES_COLUMNS_WIDTH_LS_KEY = 'nodesTableColumnsWidth'; + +export const NODES_COLUMNS_IDS = { + NodeId: 'NodeId', + Host: 'Host', + NodeName: 'NodeName', + DC: 'DC', + Rack: 'Rack', + Version: 'Version', + Uptime: 'Uptime', + Memory: 'Memory', + CPU: 'CPU', + LoadAverage: 'LoadAverage', + Load: 'Load', + SharedCacheUsage: 'SharedCacheUsage', + TotalSessions: 'TotalSessions', + Missing: 'Missing', + Tablets: 'Tablets', +} as const; + +export type NodesColumnId = ValueOf; + +// This code is running when module is initialized and correct language may not be set yet +// get functions guarantee that i18n fields will be inited on render with current render language +export const NODES_COLUMNS_TITLES = { + get NodeId() { + return i18n('node-id'); + }, + get Host() { + return i18n('host'); + }, + get NodeName() { + return i18n('node-name'); + }, + get DC() { + return i18n('dc'); + }, + get Rack() { + return i18n('rack'); + }, + get Version() { + return i18n('version'); + }, + get Uptime() { + return i18n('uptime'); + }, + get Memory() { + return i18n('memory'); + }, + get CPU() { + return i18n('cpu'); + }, + get LoadAverage() { + return i18n('load-average'); + }, + get Load() { + return i18n('load'); + }, + get SharedCacheUsage() { + return i18n('caches'); + }, + get TotalSessions() { + return i18n('sessions'); + }, + get Missing() { + return i18n('missing'); + }, + get Tablets() { + return i18n('tablets'); + }, +} as const satisfies Record; diff --git a/src/containers/Nodes/columns/i18n/en.json b/src/components/nodesColumns/i18n/en.json similarity index 78% rename from src/containers/Nodes/columns/i18n/en.json rename to src/components/nodesColumns/i18n/en.json index 2aa13bc36a..b9e9cd0734 100644 --- a/src/containers/Nodes/columns/i18n/en.json +++ b/src/components/nodesColumns/i18n/en.json @@ -1,5 +1,5 @@ { - "node-id": "Node Id", + "node-id": "Node ID", "host": "Host", "node-name": "Node Name", "dc": "DC", @@ -11,7 +11,7 @@ "tablets": "Tablets", "load-average": "Load Average", "load": "Load", - "process": "Process", "caches": "Caches", - "sessions": "Sessions" + "sessions": "Sessions", + "missing": "Missing" } diff --git a/src/containers/Nodes/columns/i18n/index.ts b/src/components/nodesColumns/i18n/index.ts similarity index 68% rename from src/containers/Nodes/columns/i18n/index.ts rename to src/components/nodesColumns/i18n/index.ts index c940bc45dc..0adfd03af7 100644 --- a/src/containers/Nodes/columns/i18n/index.ts +++ b/src/components/nodesColumns/i18n/index.ts @@ -1,4 +1,4 @@ -import {registerKeysets} from '../../../../utils/i18n'; +import {registerKeysets} from '../../../utils/i18n'; import en from './en.json'; diff --git a/src/components/nodesColumns/types.ts b/src/components/nodesColumns/types.ts new file mode 100644 index 0000000000..8bf42cd9e9 --- /dev/null +++ b/src/components/nodesColumns/types.ts @@ -0,0 +1,11 @@ +import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; + +import type {GetNodeRefFunc} from '../../types/additionalProps'; +import type {Column as PaginatedTableColumn} from '../PaginatedTable'; + +export type Column = PaginatedTableColumn & DataTableColumn; + +export interface GetNodesColumnsParams { + getNodeRef?: GetNodeRefFunc; + database?: string; +} diff --git a/src/containers/Nodes/Nodes.tsx b/src/containers/Nodes/Nodes.tsx index aa2f0e8a34..ebd7781609 100644 --- a/src/containers/Nodes/Nodes.tsx +++ b/src/containers/Nodes/Nodes.tsx @@ -14,6 +14,7 @@ import {ResizeableDataTable} from '../../components/ResizeableDataTable/Resizeab import {Search} from '../../components/Search'; import {TableWithControlsLayout} from '../../components/TableWithControlsLayout/TableWithControlsLayout'; import {UptimeFilter} from '../../components/UptimeFIlter'; +import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../components/nodesColumns/constants'; import {nodesApi} from '../../store/reducers/nodes/nodes'; import {filterNodes} from '../../store/reducers/nodes/selectors'; import type {NodesSortParams} from '../../store/reducers/nodes/types'; @@ -38,7 +39,6 @@ import { nodesUptimeFilterValuesSchema, } from '../../utils/nodes'; -import {NODES_COLUMNS_WIDTH_LS_KEY} from './columns/constants'; import {useNodesSelectedColumns} from './columns/hooks'; import i18n from './i18n'; diff --git a/src/containers/Nodes/PaginatedNodes.tsx b/src/containers/Nodes/PaginatedNodes.tsx index 125c88d251..de3c02c7c5 100644 --- a/src/containers/Nodes/PaginatedNodes.tsx +++ b/src/containers/Nodes/PaginatedNodes.tsx @@ -16,6 +16,7 @@ import type { import {ProblemFilter} from '../../components/ProblemFilter'; import {Search} from '../../components/Search'; import {UptimeFilter} from '../../components/UptimeFIlter'; +import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../components/nodesColumns/constants'; import type {NodesPreparedEntity} from '../../store/reducers/nodes/types'; import { ProblemFilterValues, @@ -32,7 +33,6 @@ import { nodesUptimeFilterValuesSchema, } from '../../utils/nodes'; -import {NODES_COLUMNS_WIDTH_LS_KEY} from './columns/constants'; import {useNodesSelectedColumns} from './columns/hooks'; import {getNodes} from './getNodes'; import i18n from './i18n'; diff --git a/src/containers/Nodes/columns/columns.tsx b/src/containers/Nodes/columns/columns.tsx index 071d824171..d81ef40576 100644 --- a/src/containers/Nodes/columns/columns.tsx +++ b/src/containers/Nodes/columns/columns.tsx @@ -1,274 +1,36 @@ -import DataTable from '@gravity-ui/react-data-table'; -import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; - -import {CellWithPopover} from '../../../components/CellWithPopover/CellWithPopover'; -import {NodeHostWrapper} from '../../../components/NodeHostWrapper/NodeHostWrapper'; -import {PoolsGraph} from '../../../components/PoolsGraph/PoolsGraph'; -import {ProgressViewer} from '../../../components/ProgressViewer/ProgressViewer'; -import {TabletsStatistic} from '../../../components/TabletsStatistic'; -import {UsageLabel} from '../../../components/UsageLabel/UsageLabel'; +import { + getCpuColumn, + getDataCenterColumn, + getHostColumn, + getLoadAverageColumn, + getMemoryColumn, + getNodeIdColumn, + getNodeNameColumn, + getRackColumn, + getTabletsColumn, + getUptimeColumn, + getVersionColumn, +} from '../../../components/nodesColumns/columns'; +import type {Column, GetNodesColumnsParams} from '../../../components/nodesColumns/types'; import type {NodesPreparedEntity} from '../../../store/reducers/nodes/types'; -import {getLoadSeverityForNode} from '../../../store/reducers/nodes/utils'; -import type {GetNodeRefFunc} from '../../../types/additionalProps'; -import {EMPTY_DATA_PLACEHOLDER} from '../../../utils/constants'; -import {formatStorageValuesToGb} from '../../../utils/dataFormatters/dataFormatters'; import {isSortableNodesProperty} from '../../../utils/nodes'; -import {NODES_COLUMNS_IDS, NODES_COLUMNS_TITLES} from './constants'; -import type {GetNodesColumnsProps, NodesColumn} from './types'; - -const nodeIdColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.NodeId, - header: '#', - width: 80, - render: ({row}) => row.NodeId, - align: DataTable.RIGHT, - sortable: false, -}; - -const getHostColumn = (getNodeRef?: GetNodeRefFunc, database?: string): NodesColumn => ({ - name: NODES_COLUMNS_IDS.Host, - header: NODES_COLUMNS_TITLES.Host, - render: ({row}) => { - return ; - }, - width: 350, - align: DataTable.LEFT, - sortable: false, -}); -const nodeNameColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.NodeName, - header: NODES_COLUMNS_TITLES.NodeName, - align: DataTable.LEFT, - render: ({row}) => row.NodeName || EMPTY_DATA_PLACEHOLDER, - width: 200, -}; - -const getHostColumnWithUndefinedWidth = ( - getNodeRef?: GetNodeRefFunc, -): DataTableColumn => { - return {...getHostColumn(getNodeRef), width: undefined}; -}; - -const dataCenterColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.DC, - header: NODES_COLUMNS_TITLES.DC, - align: DataTable.LEFT, - render: ({row}) => row.DC || EMPTY_DATA_PLACEHOLDER, - width: 60, -}; - -const rackColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.Rack, - header: NODES_COLUMNS_TITLES.Rack, - align: DataTable.LEFT, - render: ({row}) => (row.Rack ? row.Rack : '—'), - width: 80, -}; - -const versionColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.Version, - header: NODES_COLUMNS_TITLES.Version, - width: 200, - align: DataTable.LEFT, - render: ({row}) => { - return {row.Version}; - }, - sortable: false, -}; - -const uptimeColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.Uptime, - header: NODES_COLUMNS_TITLES.Uptime, - sortAccessor: ({StartTime}) => StartTime && -StartTime, - render: ({row}) => row.Uptime, - align: DataTable.RIGHT, - width: 110, - sortable: false, -}; - -const memoryColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.Memory, - header: NODES_COLUMNS_TITLES.Memory, - sortAccessor: ({MemoryUsed = 0}) => Number(MemoryUsed), - defaultOrder: DataTable.DESCENDING, - render: ({row}) => ( - - ), - align: DataTable.RIGHT, - width: 120, -}; - -const cpuColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.CPU, - header: NODES_COLUMNS_TITLES.CPU, - sortAccessor: ({PoolStats = []}) => Math.max(...PoolStats.map(({Usage}) => Number(Usage))), - defaultOrder: DataTable.DESCENDING, - render: ({row}) => (row.PoolStats ? : '—'), - align: DataTable.LEFT, - width: 80, - resizeMinWidth: 60, - sortable: false, -}; - -const loadAverageColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.LoadAverage, - header: NODES_COLUMNS_TITLES.LoadAverage, - sortAccessor: ({LoadAveragePercents = []}) => LoadAveragePercents[0], - defaultOrder: DataTable.DESCENDING, - render: ({row}) => ( - 0 - ? row.LoadAveragePercents[0] - : undefined - } - percents={true} - colorizeProgress={true} - capacity={100} - /> - ), - align: DataTable.LEFT, - width: 140, - resizeMinWidth: 140, - sortable: false, -}; - -const getTabletsColumn = (tabletsPath?: string): NodesColumn => ({ - name: NODES_COLUMNS_IDS.Tablets, - header: NODES_COLUMNS_TITLES.Tablets, - width: 500, - resizeMinWidth: 500, - render: ({row}) => { - return row.Tablets ? ( - - ) : ( - '—' - ); - }, - align: DataTable.LEFT, - sortable: false, -}); - -const topNodesLoadAverageColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.TopNodesLoadAverage, - header: NODES_COLUMNS_TITLES.TopNodesLoadAverage, - render: ({row}) => - row.LoadAveragePercents && row.LoadAveragePercents.length > 0 ? ( - - ) : ( - '—' - ), - align: DataTable.LEFT, - width: 80, - resizeMinWidth: 70, - sortable: false, -}; - -const topNodesMemoryColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.TopNodesMemory, - header: NODES_COLUMNS_TITLES.TopNodesMemory, - render: ({row}) => ( - - ), - align: DataTable.LEFT, - width: 140, - resizeMinWidth: 140, - sortable: false, -}; - -const sharedCacheUsageColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.SharedCacheUsage, - header: NODES_COLUMNS_TITLES.SharedCacheUsage, - render: ({row}) => ( - - ), - align: DataTable.LEFT, - width: 140, - resizeMinWidth: 140, - sortable: false, -}; - -const sessionsColumn: NodesColumn = { - name: NODES_COLUMNS_IDS.TotalSessions, - header: NODES_COLUMNS_TITLES.TotalSessions, - render: ({row}) => row.TotalSessions ?? '—', - align: DataTable.RIGHT, - width: 100, - sortable: false, -}; - -export function getNodesColumns({database, getNodeRef}: GetNodesColumnsProps): NodesColumn[] { +export function getNodesColumns(params: GetNodesColumnsParams): Column[] { const columns = [ - nodeIdColumn, - getHostColumn(getNodeRef, database), - nodeNameColumn, - dataCenterColumn, - rackColumn, - versionColumn, - uptimeColumn, - memoryColumn, - cpuColumn, - loadAverageColumn, - getTabletsColumn(database), + getNodeIdColumn(), + getHostColumn(params), + getNodeNameColumn(), + getDataCenterColumn(), + getRackColumn(), + getVersionColumn(), + getUptimeColumn(), + getMemoryColumn(), + getCpuColumn(), + getLoadAverageColumn(), + getTabletsColumn(params), ]; return columns.map((column) => { return {...column, sortable: isSortableNodesProperty(column.name)}; }); } - -export function getTopNodesByLoadColumns( - getNodeRef?: GetNodeRefFunc, -): DataTableColumn[] { - return [ - topNodesLoadAverageColumn, - nodeIdColumn, - getHostColumnWithUndefinedWidth(getNodeRef), - versionColumn, - ]; -} - -export function getTopNodesByCpuColumns( - getNodeRef?: GetNodeRefFunc, -): DataTableColumn[] { - return [cpuColumn, nodeIdColumn, getHostColumnWithUndefinedWidth(getNodeRef)]; -} - -export function getTopNodesByMemoryColumns({ - database, - getNodeRef, -}: GetNodesColumnsProps): NodesColumn[] { - return [ - nodeIdColumn, - getHostColumn(getNodeRef, database), - uptimeColumn, - topNodesLoadAverageColumn, - topNodesMemoryColumn, - sharedCacheUsageColumn, - sessionsColumn, - getTabletsColumn(database), - ]; -} diff --git a/src/containers/Nodes/columns/constants.ts b/src/containers/Nodes/columns/constants.ts index 8553c210e9..5ebff16cca 100644 --- a/src/containers/Nodes/columns/constants.ts +++ b/src/containers/Nodes/columns/constants.ts @@ -1,30 +1,7 @@ -import type {ValueOf} from '../../../types/common'; +import type {NodesColumnId} from '../../../components/nodesColumns/constants'; -import i18n from './i18n'; - -export const NODES_COLUMNS_WIDTH_LS_KEY = 'nodesTableColumnsWidth'; export const NODES_TABLE_SELECTED_COLUMNS_LS_KEY = 'nodesTableSelectedColumns'; -export const NODES_COLUMNS_IDS = { - NodeId: 'NodeId', - Host: 'Host', - NodeName: 'NodeName', - DC: 'DC', - Rack: 'Rack', - Version: 'Version', - Uptime: 'Uptime', - Memory: 'Memory', - CPU: 'CPU', - LoadAverage: 'LoadAverage', - Tablets: 'Tablets', - TopNodesLoadAverage: 'TopNodesLoadAverage', - TopNodesMemory: 'TopNodesMemory', - SharedCacheUsage: 'SharedCacheUsage', - TotalSessions: 'TotalSessions', -} as const; - -type NodesColumnId = ValueOf; - export const DEFAULT_NODES_COLUMNS: NodesColumnId[] = [ 'NodeId', 'Host', @@ -39,53 +16,3 @@ export const DEFAULT_NODES_COLUMNS: NodesColumnId[] = [ ]; export const REQUIRED_NODES_COLUMNS: NodesColumnId[] = ['NodeId']; - -// This code is running when module is initialized and correct language may not be set yet -// get functions guarantee that i18n fields will be inited on render with current render language -export const NODES_COLUMNS_TITLES = { - get NodeId() { - return i18n('node-id'); - }, - get Host() { - return i18n('host'); - }, - get NodeName() { - return i18n('node-name'); - }, - get DC() { - return i18n('dc'); - }, - get Rack() { - return i18n('rack'); - }, - get Version() { - return i18n('version'); - }, - get Uptime() { - return i18n('uptime'); - }, - get Memory() { - return i18n('memory'); - }, - get CPU() { - return i18n('cpu'); - }, - get LoadAverage() { - return i18n('load-average'); - }, - get Tablets() { - return i18n('tablets'); - }, - get TopNodesLoadAverage() { - return i18n('load'); - }, - get TopNodesMemory() { - return i18n('process'); - }, - get SharedCacheUsage() { - return i18n('caches'); - }, - get TotalSessions() { - return i18n('sessions'); - }, -} as const satisfies Record; diff --git a/src/containers/Nodes/columns/hooks.ts b/src/containers/Nodes/columns/hooks.ts index 90bb10a58c..fde6a8167b 100644 --- a/src/containers/Nodes/columns/hooks.ts +++ b/src/containers/Nodes/columns/hooks.ts @@ -1,17 +1,17 @@ import React from 'react'; +import {NODES_COLUMNS_TITLES} from '../../../components/nodesColumns/constants'; +import type {GetNodesColumnsParams} from '../../../components/nodesColumns/types'; import {useSelectedColumns} from '../../../utils/hooks/useSelectedColumns'; import {getNodesColumns} from './columns'; import { DEFAULT_NODES_COLUMNS, - NODES_COLUMNS_TITLES, NODES_TABLE_SELECTED_COLUMNS_LS_KEY, REQUIRED_NODES_COLUMNS, } from './constants'; -import type {GetNodesColumnsProps} from './types'; -export function useNodesSelectedColumns(params: GetNodesColumnsProps) { +export function useNodesSelectedColumns(params: GetNodesColumnsParams) { const columns = React.useMemo(() => { return getNodesColumns(params); }, [params]); diff --git a/src/containers/Nodes/columns/types.ts b/src/containers/Nodes/columns/types.ts deleted file mode 100644 index 6b81651590..0000000000 --- a/src/containers/Nodes/columns/types.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; - -import type {Column as PaginatedTableColumn} from '../../../components/PaginatedTable'; -import type {NodesPreparedEntity} from '../../../store/reducers/nodes/types'; -import type {GetNodeRefFunc} from '../../../types/additionalProps'; - -export interface GetNodesColumnsProps { - database?: string; - getNodeRef?: GetNodeRefFunc; -} - -export type NodesColumn = PaginatedTableColumn & - DataTableColumn; diff --git a/src/containers/Storage/StorageNodes/columns/columns.tsx b/src/containers/Storage/StorageNodes/columns/columns.tsx index 8c41f0bb54..54dc981522 100644 --- a/src/containers/Storage/StorageNodes/columns/columns.tsx +++ b/src/containers/Storage/StorageNodes/columns/columns.tsx @@ -1,8 +1,15 @@ import DataTable from '@gravity-ui/react-data-table'; -import {NodeHostWrapper} from '../../../../components/NodeHostWrapper/NodeHostWrapper'; +import { + getDataCenterColumn, + getHostColumn, + getMissingDisksColumn, + getNodeIdColumn, + getRackColumn, + getUptimeColumn, +} from '../../../../components/nodesColumns/columns'; +import type {PreparedStorageNode} from '../../../../store/reducers/storage/types'; import {cn} from '../../../../utils/cn'; -import {EMPTY_DATA_PLACEHOLDER} from '../../../../utils/constants'; import {isSortableNodesProperty} from '../../../../utils/nodes'; import {PDisk} from '../../PDisk/PDisk'; @@ -13,95 +20,53 @@ import './StorageNodesColumns.scss'; const b = cn('ydb-storage-nodes-columns'); -const getStorageNodesColumns = ({ - additionalNodesProps, +const getPDisksColumn = ({viewContext}: GetStorageNodesColumnsParams): StorageNodesColumn => { + return { + name: STORAGE_NODES_COLUMNS_IDS.PDisks, + header: STORAGE_NODES_COLUMNS_TITLES.PDisks, + className: b('pdisks-column'), + render: ({row}) => { + return ( +
+ {row.PDisks?.map((pDisk) => { + const vDisks = row.VDisks?.filter( + (vdisk) => vdisk.PDiskId === pDisk.PDiskId, + ); + + return ( +
+ +
+ ); + })} +
+ ); + }, + align: DataTable.CENTER, + sortable: false, + width: 900, + resizeable: false, + }; +}; + +export const getStorageNodesColumns = ({ database, + additionalNodesProps, viewContext, -}: GetStorageNodesColumnsParams) => { +}: GetStorageNodesColumnsParams): StorageNodesColumn[] => { const getNodeRef = additionalNodesProps?.getNodeRef; - const columns: StorageNodesColumn[] = [ - { - name: STORAGE_NODES_COLUMNS_IDS.NodeId, - header: STORAGE_NODES_COLUMNS_TITLES.NodeId, - width: 100, - align: DataTable.RIGHT, - render: ({row}) => row.NodeId, - }, - { - name: STORAGE_NODES_COLUMNS_IDS.Host, - header: STORAGE_NODES_COLUMNS_TITLES.Host, - width: 350, - render: ({row}) => { - return ; - }, - align: DataTable.LEFT, - }, - { - name: STORAGE_NODES_COLUMNS_IDS.DC, - header: STORAGE_NODES_COLUMNS_TITLES.DC, - width: 100, - render: ({row}) => row.DC || EMPTY_DATA_PLACEHOLDER, - align: DataTable.LEFT, - }, - { - name: STORAGE_NODES_COLUMNS_IDS.Rack, - header: STORAGE_NODES_COLUMNS_TITLES.Rack, - width: 100, - render: ({row}) => row.Rack || '—', - align: DataTable.LEFT, - }, - { - name: STORAGE_NODES_COLUMNS_IDS.Uptime, - header: STORAGE_NODES_COLUMNS_TITLES.Uptime, - width: 130, - sortAccessor: ({StartTime}) => (StartTime ? -StartTime : 0), - align: DataTable.RIGHT, - render: ({row}) => row.Uptime, - }, - { - name: STORAGE_NODES_COLUMNS_IDS.Missing, - header: STORAGE_NODES_COLUMNS_TITLES.Missing, - width: 100, - align: DataTable.CENTER, - defaultOrder: DataTable.DESCENDING, - render: ({row}) => row.Missing, - }, - { - name: STORAGE_NODES_COLUMNS_IDS.PDisks, - header: STORAGE_NODES_COLUMNS_TITLES.PDisks, - className: b('pdisks-column'), - render: ({row}) => { - return ( -
- {row.PDisks?.map((pDisk) => { - const vDisks = row.VDisks?.filter( - (vdisk) => vdisk.PDiskId === pDisk.PDiskId, - ); - - return ( -
- -
- ); - })} -
- ); - }, - align: DataTable.CENTER, - sortable: false, - width: 900, - resizeable: false, - }, + const columns = [ + getNodeIdColumn(), + getHostColumn({getNodeRef, database}), + getDataCenterColumn(), + getRackColumn(), + getUptimeColumn(), + getMissingDisksColumn(), + getPDisksColumn({viewContext}), ]; - return columns; -}; - -export const getPreparedStorageNodesColumns = (params: GetStorageNodesColumnsParams) => { - const rawColumns = getStorageNodesColumns(params); - - const sortableColumns = rawColumns.map((column) => ({ + const sortableColumns = columns.map((column) => ({ ...column, sortable: isSortableNodesProperty(column.name), })); diff --git a/src/containers/Storage/StorageNodes/columns/constants.ts b/src/containers/Storage/StorageNodes/columns/constants.ts index 39763085b6..b506f4b8e7 100644 --- a/src/containers/Storage/StorageNodes/columns/constants.ts +++ b/src/containers/Storage/StorageNodes/columns/constants.ts @@ -1,6 +1,10 @@ import type {SelectOption} from '@gravity-ui/uikit'; import {z} from 'zod'; +import { + NODES_COLUMNS_IDS as BASE_NODES_COLUMNS_IDS, + NODES_COLUMNS_TITLES as BASE_NODES_COLUMNS_TITLES, +} from '../../../../components/nodesColumns/constants'; import type {NodesGroupByField} from '../../../../types/api/nodes'; import type {ValueOf} from '../../../../types/common'; @@ -10,14 +14,8 @@ export const STORAGE_NODES_COLUMNS_WIDTH_LS_KEY = 'storageNodesColumnsWidth'; export const STORAGE_NODES_SELECTED_COLUMNS_LS_KEY = 'storageNodesSelectedColumns'; export const STORAGE_NODES_COLUMNS_IDS = { - NodeId: 'NodeId', - Host: 'Host', - DC: 'DC', - Rack: 'Rack', - Version: 'Version', - Uptime: 'Uptime', + ...BASE_NODES_COLUMNS_IDS, PDisks: 'PDisks', - Missing: 'Missing', DiskSpaceUsage: 'DiskSpaceUsage', } as const; @@ -36,30 +34,10 @@ export const REQUIRED_STORAGE_NODES_COLUMNS: StorageNodesColumnId[] = ['NodeId'] // This code is running when module is initialized and correct language may not be set yet // get functions guarantee that i18n fields will be inited on render with current render language export const STORAGE_NODES_COLUMNS_TITLES = { - get NodeId() { - return i18n('nodes-id'); - }, - get Host() { - return i18n('host'); - }, - get DC() { - return i18n('dc'); - }, - get Rack() { - return i18n('rack'); - }, - get Version() { - return i18n('version'); - }, - get Uptime() { - return i18n('uptime'); - }, + ...BASE_NODES_COLUMNS_TITLES, get PDisks() { return i18n('pdisks'); }, - get Missing() { - return i18n('missing'); - }, get DiskSpaceUsage() { return i18n('disk-space-usage'); }, diff --git a/src/containers/Storage/StorageNodes/columns/hooks.ts b/src/containers/Storage/StorageNodes/columns/hooks.ts index 1dc8415b71..694238e1ea 100644 --- a/src/containers/Storage/StorageNodes/columns/hooks.ts +++ b/src/containers/Storage/StorageNodes/columns/hooks.ts @@ -3,7 +3,7 @@ import React from 'react'; import {VISIBLE_ENTITIES} from '../../../../store/reducers/storage/constants'; import {useSelectedColumns} from '../../../../utils/hooks/useSelectedColumns'; -import {getPreparedStorageNodesColumns} from './columns'; +import {getStorageNodesColumns} from './columns'; import { DEFAULT_STORAGE_NODES_COLUMNS, REQUIRED_STORAGE_NODES_COLUMNS, @@ -20,11 +20,7 @@ export function useStorageNodesSelectedColumns({ viewContext, }: GetStorageNodesColumnsParams) { const columns = React.useMemo(() => { - return getPreparedStorageNodesColumns({ - database, - additionalNodesProps, - viewContext, - }); + return getStorageNodesColumns({database, additionalNodesProps, viewContext}); }, [database, additionalNodesProps, viewContext]); const requiredColumns = React.useMemo(() => { diff --git a/src/containers/Storage/StorageNodes/columns/i18n/en.json b/src/containers/Storage/StorageNodes/columns/i18n/en.json index 9817b28a29..c0d0c1bd75 100644 --- a/src/containers/Storage/StorageNodes/columns/i18n/en.json +++ b/src/containers/Storage/StorageNodes/columns/i18n/en.json @@ -1,11 +1,4 @@ { - "nodes-id": "Node ID", - "host": "Host", - "dc": "DC", - "rack": "Rack", - "version": "Version", - "uptime": "Uptime", - "missing": "Missing", "disk-space-usage": "Disk space usage", "pdisks": "PDisks" } diff --git a/src/containers/Storage/StorageNodes/columns/types.ts b/src/containers/Storage/StorageNodes/columns/types.ts index 14f0bbe1d0..960a337997 100644 --- a/src/containers/Storage/StorageNodes/columns/types.ts +++ b/src/containers/Storage/StorageNodes/columns/types.ts @@ -1,15 +1,12 @@ -import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; - -import type {Column as PaginatedTableColumn} from '../../../../components/PaginatedTable'; +import type {Column} from '../../../../components/nodesColumns/types'; import type {PreparedStorageNode, VisibleEntities} from '../../../../store/reducers/storage/types'; import type {AdditionalNodesProps} from '../../../../types/additionalProps'; import type {StorageViewContext} from '../../types'; -export type StorageNodesColumn = PaginatedTableColumn & - DataTableColumn; +export type StorageNodesColumn = Column; export interface GetStorageNodesColumnsParams { - additionalNodesProps: AdditionalNodesProps | undefined; + additionalNodesProps?: AdditionalNodesProps | undefined; visibleEntities?: VisibleEntities; database?: string; viewContext: StorageViewContext; diff --git a/src/containers/Storage/utils/index.ts b/src/containers/Storage/utils/index.ts index 5105d0a82e..fb76c9d8f3 100644 --- a/src/containers/Storage/utils/index.ts +++ b/src/containers/Storage/utils/index.ts @@ -1,5 +1,6 @@ import {ASCENDING, DESCENDING} from '@gravity-ui/react-data-table/build/esm/lib/constants'; +import {NODES_COLUMNS_IDS} from '../../../components/nodesColumns/constants'; import type {NodesSortParams} from '../../../store/reducers/nodes/types'; import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants'; import type { @@ -10,7 +11,6 @@ import type { import {valueIsDefined} from '../../../utils'; import type {PreparedVDisk} from '../../../utils/disks/types'; import {generateEvaluator} from '../../../utils/generateEvaluator'; -import {NODES_COLUMNS_IDS} from '../../Nodes/columns/constants'; import {STORAGE_GROUPS_COLUMNS_IDS} from '../StorageGroups/columns/constants'; import type {StorageViewContext} from '../types'; diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx index de0987cf35..892a5cb6fd 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx @@ -1,15 +1,40 @@ +import type {Column} from '@gravity-ui/react-data-table'; + +import { + getCpuColumn, + getHostColumn, + getNodeIdColumn, +} from '../../../../../components/nodesColumns/columns'; +import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../../../../components/nodesColumns/constants'; +import type {GetNodesColumnsParams} from '../../../../../components/nodesColumns/types'; import {nodesApi} from '../../../../../store/reducers/nodes/nodes'; +import type {NodesPreparedEntity} from '../../../../../store/reducers/nodes/types'; import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants'; import type {AdditionalNodesProps} from '../../../../../types/additionalProps'; import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../../utils/constants'; import {useAutoRefreshInterval, useSearchQuery} from '../../../../../utils/hooks'; -import {getTopNodesByCpuColumns} from '../../../../Nodes/columns/columns'; -import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../../../Nodes/columns/constants'; import {TenantTabsGroups, getTenantPath} from '../../../TenantPages'; import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout'; import {getSectionTitle} from '../getSectionTitle'; import i18n from '../i18n'; +export function getTopNodesByCpuColumns( + params: GetNodesColumnsParams, +): Column[] { + const hostColumn = {...getHostColumn(params), width: undefined}; + + const columns = [ + getCpuColumn(), + getNodeIdColumn(), + hostColumn, + ]; + + return columns.map((column) => ({ + ...column, + sortable: false, + })); +} + interface TopNodesByCpuProps { tenantName: string; additionalNodesProps?: AdditionalNodesProps; @@ -19,7 +44,10 @@ export function TopNodesByCpu({tenantName, additionalNodesProps}: TopNodesByCpuP const query = useSearchQuery(); const [autoRefreshInterval] = useAutoRefreshInterval(); - const columns = getTopNodesByCpuColumns(additionalNodesProps?.getNodeRef); + const columns = getTopNodesByCpuColumns({ + getNodeRef: additionalNodesProps?.getNodeRef, + database: tenantName, + }); const {currentData, isFetching, error} = nodesApi.useGetNodesQuery( { diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx index 05a25da1c0..4d4a030e77 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx @@ -1,15 +1,41 @@ +import { + getHostColumn, + getLoadColumn, + getNodeIdColumn, + getVersionColumn, +} from '../../../../../components/nodesColumns/columns'; +import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../../../../components/nodesColumns/constants'; +import type {Column, GetNodesColumnsParams} from '../../../../../components/nodesColumns/types'; import {nodesApi} from '../../../../../store/reducers/nodes/nodes'; +import type {NodesPreparedEntity} from '../../../../../store/reducers/nodes/types'; import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants'; import type {AdditionalNodesProps} from '../../../../../types/additionalProps'; import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../../utils/constants'; import {useAutoRefreshInterval, useSearchQuery} from '../../../../../utils/hooks'; -import {getTopNodesByLoadColumns} from '../../../../Nodes/columns/columns'; -import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../../../Nodes/columns/constants'; import {TenantTabsGroups, getTenantPath} from '../../../TenantPages'; import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout'; import {getSectionTitle} from '../getSectionTitle'; import i18n from '../i18n'; +function getTopNodesByLoadColumns(params: GetNodesColumnsParams): Column[] { + const hostColumn = { + ...getHostColumn(params), + width: undefined, + }; + + const columns = [ + getLoadColumn(), + getNodeIdColumn(), + hostColumn, + getVersionColumn(), + ]; + + return columns.map((column) => ({ + ...column, + sortable: false, + })); +} + interface TopNodesByLoadProps { tenantName: string; additionalNodesProps?: AdditionalNodesProps; @@ -19,7 +45,10 @@ export function TopNodesByLoad({tenantName, additionalNodesProps}: TopNodesByLoa const query = useSearchQuery(); const [autoRefreshInterval] = useAutoRefreshInterval(); - const columns = getTopNodesByLoadColumns(additionalNodesProps?.getNodeRef); + const columns = getTopNodesByLoadColumns({ + getNodeRef: additionalNodesProps?.getNodeRef, + database: tenantName, + }); const {currentData, isFetching, error} = nodesApi.useGetNodesQuery( { diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx index 719639b61e..c6fb6b6915 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx +++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx @@ -1,15 +1,51 @@ +import type {Column} from '@gravity-ui/react-data-table'; + +import { + getHostColumn, + getLoadColumn, + getMemoryColumn, + getNodeIdColumn, + getSessionsColumn, + getSharedCacheUsageColumn, + getTabletsColumn, + getUptimeColumn, +} from '../../../../../components/nodesColumns/columns'; +import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../../../../components/nodesColumns/constants'; +import type {GetNodesColumnsParams} from '../../../../../components/nodesColumns/types'; import {nodesApi} from '../../../../../store/reducers/nodes/nodes'; +import type {NodesPreparedEntity} from '../../../../../store/reducers/nodes/types'; import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants'; import type {AdditionalNodesProps} from '../../../../../types/additionalProps'; import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../../utils/constants'; import {useAutoRefreshInterval, useSearchQuery} from '../../../../../utils/hooks'; -import {getTopNodesByMemoryColumns} from '../../../../Nodes/columns/columns'; -import {NODES_COLUMNS_WIDTH_LS_KEY} from '../../../../Nodes/columns/constants'; import {TenantTabsGroups, getTenantPath} from '../../../TenantPages'; import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout'; import {getSectionTitle} from '../getSectionTitle'; import i18n from '../i18n'; +function getTopNodesByMemoryColumns(params: GetNodesColumnsParams): Column[] { + const memoryColumn = { + ...getMemoryColumn(), + header: i18n('column-header.process'), + }; + + const columns = [ + getNodeIdColumn(), + getHostColumn(params), + getUptimeColumn(), + getLoadColumn(), + memoryColumn, + getSharedCacheUsageColumn(), + getSessionsColumn(), + getTabletsColumn(params), + ]; + + return columns.map((column) => ({ + ...column, + sortable: false, + })); +} + interface TopNodesByMemoryProps { tenantName: string; additionalNodesProps?: AdditionalNodesProps; @@ -21,6 +57,7 @@ export function TopNodesByMemory({tenantName, additionalNodesProps}: TopNodesByM const [autoRefreshInterval] = useAutoRefreshInterval(); const columns = getTopNodesByMemoryColumns({ getNodeRef: additionalNodesProps?.getNodeRef, + database: tenantName, }); const {currentData, isFetching, error} = nodesApi.useGetNodesQuery( diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json b/src/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json index 137d247ead..996c1722f4 100644 --- a/src/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +++ b/src/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json @@ -36,5 +36,7 @@ "storage.db-storage-title": "Database storage", "storage.db-storage-description": "Size of data stored in distributed storage with all overheads for redundancy", - "executed-last-hour": "executed in the last hour" + "executed-last-hour": "executed in the last hour", + + "column-header.process": "Process" } diff --git a/src/store/reducers/nodes/types.ts b/src/store/reducers/nodes/types.ts index 924e488c33..95f1a119e1 100644 --- a/src/store/reducers/nodes/types.ts +++ b/src/store/reducers/nodes/types.ts @@ -3,20 +3,15 @@ import type {OrderType} from '@gravity-ui/react-data-table'; import type {EFlag} from '../../../types/api/enums'; import type {NodesSortValue, TEndpoint, TPoolStats} from '../../../types/api/nodes'; import type {TTabletStateInfo as TFullTabletStateInfo} from '../../../types/api/tablet'; -import type {NodesUptimeFilterValues} from '../../../utils/nodes'; +import type {NodesUptimeFilterValues, PreparedNodeSystemState} from '../../../utils/nodes'; import type {ProblemFilterValue} from '../settings/types'; -// Since nodes from different endpoints can have different types, -// This type describes fields, that are expected by tables with nodes -export interface NodesPreparedEntity { +export interface NodesPreparedEntity extends PreparedNodeSystemState { NodeId: number; Host?: string; NodeName?: string; SystemState?: EFlag; - DC?: string; - Rack?: string; Version?: string; - TenantName?: string; StartTime?: string; Uptime: string; @@ -26,9 +21,6 @@ export interface NodesPreparedEntity { MemoryUsedInAlloc?: string; MemoryLimit?: string; - SharedCacheUsed?: string; - SharedCacheLimit?: string | number; - PoolStats?: TPoolStats[]; LoadAverage?: number[]; LoadAveragePercents?: number[]; diff --git a/src/store/reducers/nodes/utils.ts b/src/store/reducers/nodes/utils.ts index 273b4ed8e1..452d3b612e 100644 --- a/src/store/reducers/nodes/utils.ts +++ b/src/store/reducers/nodes/utils.ts @@ -8,16 +8,10 @@ export const prepareNodesData = (data: TNodesInfo): NodesHandledResponse => { const rawNodes = data.Nodes || []; const preparedNodes = rawNodes.map((node) => { - // 0 limit means that limit is not set, so it should be undefined - const sharedCacheLimit = Number(node.SystemState.SharedCacheStats?.LimitBytes) || undefined; - return { ...prepareNodeSystemState(node.SystemState), Tablets: node.Tablets, NodeId: node.NodeId, - TenantName: node.SystemState?.Tenants?.[0], - SharedCacheUsed: node.SystemState.SharedCacheStats?.UsedBytes, - SharedCacheLimit: sharedCacheLimit, }; }); diff --git a/src/utils/nodes.ts b/src/utils/nodes.ts index 5438da16b6..7ee61283f9 100644 --- a/src/utils/nodes.ts +++ b/src/utils/nodes.ts @@ -1,6 +1,5 @@ import {z} from 'zod'; -import type {NodesPreparedEntity} from '../store/reducers/nodes/types'; import {ProblemFilterValues} from '../store/reducers/settings/settings'; import type {ProblemFilterValue} from '../store/reducers/settings/types'; import {EFlag} from '../types/api/enums'; @@ -27,8 +26,11 @@ export const NodesUptimeFilterTitles = { [NodesUptimeFilterValues.SmallUptime]: 'Uptime < 1h', }; -export const isUnavailableNode = (node: NodesPreparedEntity | TSystemStateInfo) => - !node.SystemState || node.SystemState === EFlag.Grey; +export const isUnavailableNode = < + T extends Pick = Pick, +>( + node: T, +) => !node.SystemState || node.SystemState === EFlag.Grey; export const prepareNodeHostsMap = (nodesList?: TNodeInfo[]) => { return nodesList?.reduce((nodeHosts, node) => { @@ -56,6 +58,9 @@ export interface PreparedNodeSystemState extends TSystemStateInfo { DC?: string; LoadAveragePercents?: number[]; Uptime: string; + TenantName?: string; + SharedCacheLimit?: number; + SharedCacheUsed?: number; } export const prepareNodeSystemState = ( @@ -64,17 +69,27 @@ export const prepareNodeSystemState = ( // There is no Rack in Location field for din nodes const Rack = systemState.Location?.Rack || systemState.Rack; const DC = systemState.Location?.DataCenter || systemState.DataCenter; + const TenantName = systemState?.Tenants?.[0]; const Uptime = calcUptime(systemState.StartTime); const LoadAveragePercents = calculateLoadAveragePercents(systemState); + // 0 limit means that limit is not set, so it should be undefined + const SharedCacheLimit = Number(systemState.SharedCacheStats?.LimitBytes) || undefined; + const SharedCacheUsed = valueIsDefined(systemState.SharedCacheStats?.UsedBytes) + ? Number(systemState.SharedCacheStats?.UsedBytes) + : undefined; + return { ...systemState, Rack, DC, Uptime, LoadAveragePercents, + TenantName, + SharedCacheLimit, + SharedCacheUsed, }; }; From 47e0cc9075bcc4e554d634666cfe25a665d1af6b Mon Sep 17 00:00:00 2001 From: mufazalov Date: Mon, 7 Oct 2024 09:54:42 +0300 Subject: [PATCH 2/2] feat(StorageNodes): add columns --- src/containers/Storage/StorageNodes/columns/columns.tsx | 8 ++++++++ src/containers/Storage/StorageNodes/columns/constants.ts | 1 + 2 files changed, 9 insertions(+) diff --git a/src/containers/Storage/StorageNodes/columns/columns.tsx b/src/containers/Storage/StorageNodes/columns/columns.tsx index 54dc981522..5f85202a0b 100644 --- a/src/containers/Storage/StorageNodes/columns/columns.tsx +++ b/src/containers/Storage/StorageNodes/columns/columns.tsx @@ -1,12 +1,16 @@ import DataTable from '@gravity-ui/react-data-table'; import { + getCpuColumn, getDataCenterColumn, getHostColumn, + getMemoryColumn, getMissingDisksColumn, getNodeIdColumn, + getNodeNameColumn, getRackColumn, getUptimeColumn, + getVersionColumn, } from '../../../../components/nodesColumns/columns'; import type {PreparedStorageNode} from '../../../../store/reducers/storage/types'; import {cn} from '../../../../utils/cn'; @@ -58,9 +62,13 @@ export const getStorageNodesColumns = ({ const columns = [ getNodeIdColumn(), + getNodeNameColumn(), getHostColumn({getNodeRef, database}), getDataCenterColumn(), getRackColumn(), + getVersionColumn(), + getMemoryColumn(), + getCpuColumn(), getUptimeColumn(), getMissingDisksColumn(), getPDisksColumn({viewContext}), diff --git a/src/containers/Storage/StorageNodes/columns/constants.ts b/src/containers/Storage/StorageNodes/columns/constants.ts index b506f4b8e7..e57121fa47 100644 --- a/src/containers/Storage/StorageNodes/columns/constants.ts +++ b/src/containers/Storage/StorageNodes/columns/constants.ts @@ -26,6 +26,7 @@ export const DEFAULT_STORAGE_NODES_COLUMNS: StorageNodesColumnId[] = [ 'Host', 'DC', 'Rack', + 'CPU', 'Uptime', 'PDisks', ];