diff --git a/frontend/src/api/infra/getHostAttributeKeys.ts b/frontend/src/api/infra/getHostAttributeKeys.ts index 2cdaf14efc..1a34cd4479 100644 --- a/frontend/src/api/infra/getHostAttributeKeys.ts +++ b/frontend/src/api/infra/getHostAttributeKeys.ts @@ -19,6 +19,11 @@ export const getHostAttributeKeys = async ( data: IQueryAutocompleteResponse; }> = await ApiBaseInstance.get( `/${entity}/attribute_keys?dataSource=metrics&searchText=${searchText}`, + { + params: { + limit: 500, + }, + }, ); const payload: BaseAutocompleteData[] = diff --git a/frontend/src/api/infraMonitoring/getK8sNodesList.ts b/frontend/src/api/infraMonitoring/getK8sNodesList.ts new file mode 100644 index 0000000000..e3c411b1d0 --- /dev/null +++ b/frontend/src/api/infraMonitoring/getK8sNodesList.ts @@ -0,0 +1,65 @@ +import { ApiBaseInstance } from 'api'; +import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; +import { AxiosError } from 'axios'; +import { ErrorResponse, SuccessResponse } from 'types/api'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; + +export interface K8sNodesListPayload { + filters: TagFilter; + groupBy?: BaseAutocompleteData[]; + offset?: number; + limit?: number; + orderBy?: { + columnName: string; + order: 'asc' | 'desc'; + }; +} + +export interface K8sNodesData { + nodeUID: string; + nodeCPUUsage: number; + nodeCPUAllocatable: number; + nodeMemoryUsage: number; + nodeMemoryAllocatable: number; + meta: { + k8s_node_name: string; + k8s_node_uid: string; + k8s_cluster_name: string; + }; +} + +export interface K8sNodesListResponse { + status: string; + data: { + type: string; + records: K8sNodesData[]; + groups: null; + total: number; + sentAnyHostMetricsData: boolean; + isSendingK8SAgentMetrics: boolean; + }; +} + +export const getK8sNodesList = async ( + props: K8sNodesListPayload, + signal?: AbortSignal, + headers?: Record, +): Promise | ErrorResponse> => { + try { + const response = await ApiBaseInstance.post('/nodes/list', props, { + signal, + headers, + }); + + return { + statusCode: 200, + error: null, + message: 'Success', + payload: response.data, + params: props, + }; + } catch (error) { + return ErrorResponseHandler(error as AxiosError); + } +}; diff --git a/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss b/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss index bdb508058d..f2f0334e7f 100644 --- a/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss +++ b/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss @@ -325,13 +325,19 @@ .progress-container { display: flex; align-items: center; - flex-direction: column; + justify-content: center; + } + + .entity-progress-bar { + display: flex; + align-items: center; } .progress-bar { flex: 1; margin-right: 8px; margin-bottom: 0px; + min-width: 100px; } .clickable-row { @@ -482,7 +488,7 @@ .expanded-table-container { border: 1px solid var(--bg-ink-400); overflow-x: auto; - padding: 8px; + padding-left: 16px; &::-webkit-scrollbar { width: 0.1rem; @@ -702,3 +708,127 @@ } } } + +.ant-table-cell { + min-width: 170px !important; + max-width: 170px !important; +} + +.ant-table-row-expand-icon-cell { + min-width: 30px !important; + max-width: 30px !important; +} + +.event-content-container { + .ant-table { + background: var(--bg-ink-400); + + .ant-table-row:hover { + .ant-table-cell { + .value-field { + .action-btn { + display: flex; + position: absolute; + top: 50%; + right: 16px; + transform: translateY(-50%); + gap: 4px; + } + } + } + } + + .ant-table-cell { + border: 1px solid var(--bg-slate-500); + } + + .attribute-name { + .ant-btn { + &:hover { + background-color: none !important; + } + } + } + + .attribute-pin { + cursor: pointer; + + padding: 0; + vertical-align: middle; + text-align: center; + + .log-attribute-pin { + padding: 8px; + + display: flex; + justify-content: center; + align-items: center; + + .pin-attribute-icon { + border: none; + + &.pinned svg { + fill: var(--bg-robin-500); + } + } + } + } + + .value-field-container { + background: rgba(22, 25, 34, 0.4); + + .value-field { + font-family: 'Geist Mono'; + + position: relative; + } + + .action-btn { + display: none; + width: max-content; + position: absolute; + // padding: 0 16px; + right: 0; + + .filter-btn { + display: flex; + align-items: center; + border: none; + box-shadow: none; + border-radius: 2px; + background: var(--bg-slate-400); + padding: 2px 3px; + gap: 3px; + height: 18px; + width: 20px; + } + } + } + } +} + +.lightMode { + .event-content-container { + .ant-table { + background: var(--bg-vanilla-100); + } + + .ant-table-cell { + border: 1px solid var(--bg-vanilla-200); + } + + .value-field-container { + background: var(--bg-vanilla-300); + + &.attribute-pin { + background: var(--bg-vanilla-100); + } + + .action-btn { + .filter-btn { + background: var(--bg-vanilla-300); + } + } + } + } +} diff --git a/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.tsx b/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.tsx index edbbad1461..d639b327f5 100644 --- a/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.tsx +++ b/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.tsx @@ -7,40 +7,22 @@ import { Collapse, Tooltip, Typography } from 'antd'; import QuickFilters from 'components/QuickFilters/QuickFilters'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations'; -import { - ArrowUpDown, - Bolt, - Boxes, - Computer, - Container, - FilePenLine, - Group, - HardDrive, - PackageOpen, - Workflow, -} from 'lucide-react'; +import { Container, Workflow } from 'lucide-react'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { useCallback, useState } from 'react'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { - ClustersQuickFiltersConfig, - ContainersQuickFiltersConfig, - DaemonSetsQuickFiltersConfig, - DeploymentsQuickFiltersConfig, - JobsQuickFiltersConfig, K8sCategories, - NamespaceQuickFiltersConfig, NodesQuickFiltersConfig, PodsQuickFiltersConfig, - StatefulsetsQuickFiltersConfig, - VolumesQuickFiltersConfig, } from './constants'; +import K8sNodesList from './Nodes/K8sNodesList'; import K8sPodLists from './Pods/K8sPodLists'; import Volumes from './Volumes/Volumes'; export default function InfraMonitoringK8s(): JSX.Element { - const [showFilters, setShowFilters] = useState(false); + const [showFilters, setShowFilters] = useState(true); const [selectedCategory, setSelectedCategory] = useState(K8sCategories.PODS); @@ -106,175 +88,176 @@ export default function InfraMonitoringK8s(): JSX.Element { /> ), }, - { - label: ( -
-
- - Namespace -
-
- ), - key: K8sCategories.NAMESPACES, - showArrow: false, - children: ( - - ), - }, - { - label: ( -
-
- - Clusters -
-
- ), - key: K8sCategories.CLUSTERS, - showArrow: false, - children: ( - - ), - }, - { - label: ( -
-
- - Containers -
-
- ), - key: K8sCategories.CONTAINERS, - showArrow: false, - children: ( - - ), - }, - { - label: ( -
-
- - Volumes -
-
- ), - key: K8sCategories.VOLUMES, - showArrow: false, - children: ( - - ), - }, - { - label: ( -
-
- - Deployments -
-
- ), - key: K8sCategories.DEPLOYMENTS, - showArrow: false, - children: ( - - ), - }, - { - label: ( -
-
- - Jobs -
-
- ), - key: K8sCategories.JOBS, - showArrow: false, - children: ( - - ), - }, - { - label: ( -
-
- - DaemonSets -
-
- ), - key: K8sCategories.DAEMONSETS, - showArrow: false, - children: ( - - ), - }, - { - label: ( -
-
- - StatefulSets -
-
- ), - key: K8sCategories.STATEFULSETS, - showArrow: false, - children: ( - - ), - }, + // NOTE - Enabled these as we release new entities + // { + // label: ( + //
+ //
+ // + // Namespace + //
+ //
+ // ), + // key: K8sCategories.NAMESPACES, + // showArrow: false, + // children: ( + // + // ), + // }, + // { + // label: ( + //
+ //
+ // + // Clusters + //
+ //
+ // ), + // key: K8sCategories.CLUSTERS, + // showArrow: false, + // children: ( + // + // ), + // }, + // { + // label: ( + //
+ //
+ // + // Containers + //
+ //
+ // ), + // key: K8sCategories.CONTAINERS, + // showArrow: false, + // children: ( + // + // ), + // }, + // { + // label: ( + //
+ //
+ // + // Volumes + //
+ //
+ // ), + // key: K8sCategories.VOLUMES, + // showArrow: false, + // children: ( + // + // ), + // }, + // { + // label: ( + //
+ //
+ // + // Deployments + //
+ //
+ // ), + // key: K8sCategories.DEPLOYMENTS, + // showArrow: false, + // children: ( + // + // ), + // }, + // { + // label: ( + //
+ //
+ // + // Jobs + //
+ //
+ // ), + // key: K8sCategories.JOBS, + // showArrow: false, + // children: ( + // + // ), + // }, + // { + // label: ( + //
+ //
+ // + // DaemonSets + //
+ //
+ // ), + // key: K8sCategories.DAEMONSETS, + // showArrow: false, + // children: ( + // + // ), + // }, + // { + // label: ( + //
+ //
+ // + // StatefulSets + //
+ //
+ // ), + // key: K8sCategories.STATEFULSETS, + // showArrow: false, + // children: ( + // + // ), + // }, ]; const handleCategoryChange = (key: string | string[]): void => { @@ -323,6 +306,13 @@ export default function InfraMonitoringK8s(): JSX.Element { /> )} + {selectedCategory === K8sCategories.NODES && ( + + )} + {selectedCategory === K8sCategories.VOLUMES && } diff --git a/frontend/src/container/InfraMonitoringK8s/K8sFiltersSidePanel/K8sFiltersSidePanel.tsx b/frontend/src/container/InfraMonitoringK8s/K8sFiltersSidePanel/K8sFiltersSidePanel.tsx index 3b8beabb69..8062f338b0 100644 --- a/frontend/src/container/InfraMonitoringK8s/K8sFiltersSidePanel/K8sFiltersSidePanel.tsx +++ b/frontend/src/container/InfraMonitoringK8s/K8sFiltersSidePanel/K8sFiltersSidePanel.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/click-events-have-key-events */ import './K8sFiltersSidePanel.styles.scss'; @@ -8,20 +9,20 @@ import { useEffect, useRef, useState } from 'react'; import { IPodColumn } from '../utils'; -export default function K8sFiltersSidePanel({ +function K8sFiltersSidePanel({ defaultAddedColumns, onClose, - addedColumns, - availableColumns, - onAddColumn, - onRemoveColumn, + addedColumns = [], + availableColumns = [], + onAddColumn = () => {}, + onRemoveColumn = () => {}, }: { defaultAddedColumns: IPodColumn[]; onClose: () => void; - addedColumns: IPodColumn[]; - availableColumns: IPodColumn[]; - onAddColumn: (column: IPodColumn) => void; - onRemoveColumn: (column: IPodColumn) => void; + addedColumns?: IPodColumn[]; + availableColumns?: IPodColumn[]; + onAddColumn?: (column: IPodColumn) => void; + onRemoveColumn?: (column: IPodColumn) => void; }): JSX.Element { const [searchValue, setSearchValue] = useState(''); const sidePanelRef = useRef(null); @@ -117,3 +118,12 @@ export default function K8sFiltersSidePanel({ ); } + +K8sFiltersSidePanel.defaultProps = { + addedColumns: [], + availableColumns: [], + onAddColumn: () => {}, + onRemoveColumn: () => {}, +}; + +export default K8sFiltersSidePanel; diff --git a/frontend/src/container/InfraMonitoringK8s/K8sHeader.tsx b/frontend/src/container/InfraMonitoringK8s/K8sHeader.tsx index 25638f68cf..748cb205b3 100644 --- a/frontend/src/container/InfraMonitoringK8s/K8sHeader.tsx +++ b/frontend/src/container/InfraMonitoringK8s/K8sHeader.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ import './InfraMonitoringK8s.styles.scss'; import { Button, Select } from 'antd'; @@ -15,17 +16,18 @@ import { IPodColumn } from './utils'; interface K8sHeaderProps { selectedGroupBy: BaseAutocompleteData[]; - defaultAddedColumns: IPodColumn[]; groupByOptions: { value: string; label: string }[]; - addedColumns: IPodColumn[]; isLoadingGroupByFilters: boolean; - availableColumns: IPodColumn[]; handleFiltersChange: (value: IBuilderQuery['filters']) => void; handleGroupByChange: (value: IBuilderQuery['groupBy']) => void; - onAddColumn: (column: IPodColumn) => void; - onRemoveColumn: (column: IPodColumn) => void; + defaultAddedColumns: IPodColumn[]; + addedColumns?: IPodColumn[]; + availableColumns?: IPodColumn[]; + onAddColumn?: (column: IPodColumn) => void; + onRemoveColumn?: (column: IPodColumn) => void; handleFilterVisibilityChange: () => void; isFiltersVisible: boolean; + entity: K8sCategory; } function K8sHeader({ @@ -41,6 +43,7 @@ function K8sHeader({ onRemoveColumn, handleFilterVisibilityChange, isFiltersVisible, + entity, }: K8sHeaderProps): JSX.Element { const [isFiltersSidePanelOpen, setIsFiltersSidePanelOpen] = useState(false); @@ -96,7 +99,7 @@ function K8sHeader({ onChange={handleChangeTagFilters} isInfraMonitoring disableNavigationShortcuts - entity={K8sCategory.PODS} + entity={entity} /> @@ -127,7 +130,7 @@ function K8sHeader({