chore: infra monitoring bug fixes (#6795)

This commit is contained in:
Amlan Kumar Nandy 2025-01-18 16:25:50 +05:30 committed by GitHub
parent 16e61b45ac
commit 5c45e1f7b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 338 additions and 281 deletions

View File

@ -1,4 +1,4 @@
import { ApiBaseInstance } from 'api';
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
@ -47,7 +47,7 @@ export const getK8sNodesList = async (
headers?: Record<string, string>,
): Promise<SuccessResponse<K8sNodesListResponse> | ErrorResponse> => {
try {
const response = await ApiBaseInstance.post('/nodes/list', props, {
const response = await axios.post('/nodes/list', props, {
signal,
headers,
});

View File

@ -1,4 +1,4 @@
import { ApiBaseInstance } from 'api';
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
@ -75,7 +75,7 @@ export const getK8sPodsList = async (
headers?: Record<string, string>,
): Promise<SuccessResponse<K8sPodsListResponse> | ErrorResponse> => {
try {
const response = await ApiBaseInstance.post('/pods/list', props, {
const response = await axios.post('/pods/list', props, {
signal,
headers,
});

View File

@ -39,10 +39,6 @@
.ant-collapse-header {
border-bottom: 1px solid var(--bg-slate-400);
padding: 12px 8px;
&[aria-expanded='true'] {
background: var(--bg-ink-400);
}
}
.ant-collapse-content-box {
@ -271,8 +267,6 @@
.group-by-label {
min-width: max-content;
color: var(--bg-vanilla-100, #c0c1c3);
font-size: 13px;
font-style: normal;
font-weight: 400;
@ -282,7 +276,6 @@
border-radius: 2px 0px 0px 2px;
border: 1px solid var(--bg-slate-400, #1d212d);
border-right: none;
background: var(--bg-ink-100, #16181d);
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
@ -488,7 +481,7 @@
.expanded-table-container {
border: 1px solid var(--bg-ink-400);
overflow-x: auto;
padding-left: 16px;
padding-left: 48px;
&::-webkit-scrollbar {
width: 0.1rem;
@ -710,8 +703,34 @@
}
.ant-table-cell {
min-width: 170px !important;
max-width: 170px !important;
min-width: 140px !important;
max-width: 140px !important;
}
.ant-table-cell {
&:has(.pod-name-header) {
min-width: 250px !important;
max-width: 250px !important;
}
}
.ant-table-cell {
&:has(.med-col) {
min-width: 180px !important;
max-width: 180px !important;
}
}
.expanded-k8s-list-table {
.ant-table-cell {
min-width: 180px !important;
max-width: 180px !important;
}
.ant-table-row-expand-icon-cell {
min-width: 30px !important;
max-width: 30px !important;
}
}
.ant-table-row-expand-icon-cell {
@ -808,6 +827,24 @@
}
.lightMode {
.infra-monitoring-container {
.k8s-list-table {
.ant-table-expanded-row {
&:hover {
background: var(--bg-vanilla-100) !important;
}
.ant-table-cell {
background: var(--bg-vanilla-100) !important;
}
.ant-table .ant-table-thead > tr > th {
padding: 4px 16px !important;
}
}
}
}
.event-content-container {
.ant-table {
background: var(--bg-vanilla-100);
@ -831,4 +868,11 @@
}
}
}
.entity-group-header {
.ant-tag {
background-color: var(--bg-vanilla-300) !important;
color: var(--bg-slate-400) !important;
}
}
}

View File

@ -9,7 +9,7 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
import { Container, Workflow } from 'lucide-react';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { useCallback, useState } from 'react';
import { useState } from 'react';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import {
@ -24,6 +24,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
const [showFilters, setShowFilters] = useState(true);
const [selectedCategory, setSelectedCategory] = useState(K8sCategories.PODS);
const [quickFiltersLastUpdated, setQuickFiltersLastUpdated] = useState(-1);
const { currentQuery } = useQueryBuilder();
@ -37,14 +38,12 @@ export default function InfraMonitoringK8s(): JSX.Element {
entityVersion: '',
});
const handleFilterChange = useCallback(
(query: Query): void => {
const handleFilterChange = (query: Query): void => {
// update the current query with the new filters
// in infra monitoring k8s, we are using only one query, hence updating the 0th index of queryData
handleChangeQueryData('filters', query.builder.queryData[0].filters);
},
[handleChangeQueryData],
);
setQuickFiltersLastUpdated(Date.now());
};
const items: CollapseProps['items'] = [
{
@ -262,6 +261,8 @@ export default function InfraMonitoringK8s(): JSX.Element {
const handleCategoryChange = (key: string | string[]): void => {
if (Array.isArray(key) && key.length > 0) {
setSelectedCategory(key[0] as string);
// Reset filters
handleChangeQueryData('filters', { items: [], op: 'and' });
}
};
@ -302,6 +303,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
<K8sPodLists
isFiltersVisible={showFilters}
handleFilterVisibilityChange={handleFilterVisibilityChange}
quickFiltersLastUpdated={quickFiltersLastUpdated}
/>
)}
@ -309,6 +311,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
<K8sNodesList
isFiltersVisible={showFilters}
handleFilterVisibilityChange={handleFilterVisibilityChange}
quickFiltersLastUpdated={quickFiltersLastUpdated}
/>
)}
</div>

View File

@ -7,7 +7,7 @@ import { Button, Input } from 'antd';
import { GripVertical, TableColumnsSplit, X } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { IPodColumn } from '../utils';
import { IEntityColumn } from '../utils';
function K8sFiltersSidePanel({
defaultAddedColumns,
@ -17,12 +17,12 @@ function K8sFiltersSidePanel({
onAddColumn = () => {},
onRemoveColumn = () => {},
}: {
defaultAddedColumns: IPodColumn[];
defaultAddedColumns: IEntityColumn[];
onClose: () => void;
addedColumns?: IPodColumn[];
availableColumns?: IPodColumn[];
onAddColumn?: (column: IPodColumn) => void;
onRemoveColumn?: (column: IPodColumn) => void;
addedColumns?: IEntityColumn[];
availableColumns?: IEntityColumn[];
onAddColumn?: (column: IEntityColumn) => void;
onRemoveColumn?: (column: IEntityColumn) => void;
}): JSX.Element {
const [searchValue, setSearchValue] = useState('');
const sidePanelRef = useRef<HTMLDivElement>(null);

View File

@ -12,7 +12,7 @@ import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { K8sCategory } from './constants';
import K8sFiltersSidePanel from './K8sFiltersSidePanel/K8sFiltersSidePanel';
import { IPodColumn } from './utils';
import { IEntityColumn } from './utils';
interface K8sHeaderProps {
selectedGroupBy: BaseAutocompleteData[];
@ -20,11 +20,11 @@ interface K8sHeaderProps {
isLoadingGroupByFilters: boolean;
handleFiltersChange: (value: IBuilderQuery['filters']) => void;
handleGroupByChange: (value: IBuilderQuery['groupBy']) => void;
defaultAddedColumns: IPodColumn[];
addedColumns?: IPodColumn[];
availableColumns?: IPodColumn[];
onAddColumn?: (column: IPodColumn) => void;
onRemoveColumn?: (column: IPodColumn) => void;
defaultAddedColumns: IEntityColumn[];
addedColumns?: IEntityColumn[];
availableColumns?: IEntityColumn[];
onAddColumn?: (column: IEntityColumn) => void;
onRemoveColumn?: (column: IEntityColumn) => void;
handleFilterVisibilityChange: () => void;
isFiltersVisible: boolean;
entity: K8sCategory;

View File

@ -45,9 +45,11 @@ import {
function K8sNodesList({
isFiltersVisible,
handleFilterVisibilityChange,
quickFiltersLastUpdated,
}: {
isFiltersVisible: boolean;
handleFilterVisibilityChange: () => void;
quickFiltersLastUpdated: number;
}): JSX.Element {
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
@ -60,7 +62,7 @@ function K8sNodesList({
const [orderBy, setOrderBy] = useState<{
columnName: string;
order: 'asc' | 'desc';
} | null>(null);
} | null>({ columnName: 'cpu', order: 'desc' });
const [selectedNodeUID, setselectedNodeUID] = useState<string | null>(null);
@ -76,12 +78,28 @@ function K8sNodesList({
{ value: string; label: string }[]
>([]);
const { currentQuery } = useQueryBuilder();
const queryFilters = useMemo(
() =>
currentQuery?.builder?.queryData[0]?.filters || {
items: [],
op: 'and',
},
[currentQuery?.builder?.queryData],
);
// Reset pagination every time quick filters are changed
useEffect(() => {
setCurrentPage(1);
}, [quickFiltersLastUpdated]);
const createFiltersForSelectedRowData = (
selectedRowData: K8sNodesRowData,
groupBy: IBuilderQuery['groupBy'],
): IBuilderQuery['filters'] => {
const baseFilters: IBuilderQuery['filters'] = {
items: [],
items: [...queryFilters.items],
op: 'and',
};
@ -120,6 +138,7 @@ function K8sNodesList({
end: Math.floor(maxTime / 1000000),
orderBy,
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [minTime, maxTime, orderBy, selectedRowData, groupBy]);
const {
@ -133,8 +152,6 @@ function K8sNodesList({
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
});
const { currentQuery } = useQueryBuilder();
const {
data: groupByFiltersData,
isLoading: isLoadingGroupByFilters,
@ -153,15 +170,6 @@ function K8sNodesList({
K8sCategory.NODES,
);
const queryFilters = useMemo(
() =>
currentQuery?.builder?.queryData[0]?.filters || {
items: [],
op: 'and',
},
[currentQuery?.builder?.queryData],
);
const query = useMemo(() => {
const baseQuery = getK8sNodesListQuery();
const queryPayload = {
@ -308,6 +316,7 @@ function K8sNodesList({
) : (
<div className="expanded-table">
<Table
className="expanded-table-view"
columns={nestedColumns as ColumnType<K8sNodesRowData>[]}
dataSource={formattedGroupedByNodesData}
pagination={false}
@ -382,18 +391,6 @@ function K8sNodesList({
setselectedNodeUID(null);
};
const showsNodesTable =
!isError &&
!isLoading &&
!isFetching &&
!(formattedNodesData.length === 0 && queryFilters.items.length > 0);
const showNoFilteredNodesMessage =
!isFetching &&
!isLoading &&
formattedNodesData.length === 0 &&
queryFilters.items.length > 0;
const handleGroupByChange = useCallback(
(value: IBuilderQuery['groupBy']) => {
const groupBy = [];
@ -442,25 +439,6 @@ function K8sNodesList({
/>
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
{showNoFilteredNodesMessage && (
<div className="no-filtered-hosts-message-container">
<div className="no-filtered-hosts-message-content">
<img
src="/Icons/emptyState.svg"
alt="thinking-emoji"
className="empty-state-svg"
/>
<Typography.Text className="no-filtered-hosts-message">
This query had no results. Edit your query and try again!
</Typography.Text>
</div>
</div>
)}
{(isFetching || isLoading) && <LoadingContainer />}
{showsNodesTable && (
<Table
className="k8s-list-table nodes-list-table"
dataSource={isFetching || isLoading ? [] : formattedNodesData}
@ -477,6 +455,24 @@ function K8sNodesList({
spinning: isFetching || isLoading,
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
}}
locale={{
emptyText:
isFetching || isLoading ? null : (
<div className="no-filtered-hosts-message-container">
<div className="no-filtered-hosts-message-content">
<img
src="/Icons/emptyState.svg"
alt="thinking-emoji"
className="empty-state-svg"
/>
<Typography.Text className="no-filtered-hosts-message">
This query had no results. Edit your query and try again!
</Typography.Text>
</div>
</div>
),
}}
tableLayout="fixed"
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
@ -489,7 +485,7 @@ function K8sNodesList({
expandedRowKeys,
}}
/>
)}
<NodeDetails
node={selectedNodeData}
isModalTimeSelection

View File

@ -155,6 +155,7 @@ export default function Events({
id: event.data.id,
key: event.data.id,
resources_string: event.data.resources_string,
attributes_string: event.data.attributes_string,
}),
);
@ -174,7 +175,9 @@ export default function Events({
}, [eventsData]);
const handleExpandRow = (record: EventDataType): JSX.Element => (
<EventContents data={record.resources_string} />
<EventContents
data={{ ...record.attributes_string, ...record.resources_string }}
/>
);
const handlePrev = (): void => {

View File

@ -12,6 +12,7 @@ import {
initialQueryState,
} from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import { filterDuplicateFilters } from 'container/InfraMonitoringK8s/entityDetailUtils';
import {
CustomTimeType,
Time,
@ -97,22 +98,9 @@ function NodeDetails({
op: '=',
value: node?.meta.k8s_node_name || '',
},
{
id: uuidv4(),
key: {
key: QUERY_KEYS.K8S_CLUSTER_NAME,
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
id: 'k8s_node_name--string--resource--false',
},
op: '=',
value: node?.meta.k8s_cluster_name || '',
},
],
}),
[node?.meta.k8s_node_name, node?.meta.k8s_cluster_name],
[node?.meta.k8s_node_name],
);
const initialEventsFilters = useMemo(
@ -239,11 +227,13 @@ function NodeDetails({
return {
op: 'AND',
items: [
items: filterDuplicateFilters(
[
...primaryFilters,
...newFilters,
...(paginationFilter ? [paginationFilter] : []),
].filter((item): item is TagFilterItem => item !== undefined),
),
};
});
},
@ -266,12 +256,14 @@ function NodeDetails({
return {
op: 'AND',
items: [
items: filterDuplicateFilters(
[
...primaryFilters,
...value.items.filter(
(item) => item.key?.key !== QUERY_KEYS.K8S_NODE_NAME,
),
].filter((item): item is TagFilterItem => item !== undefined),
),
};
});
},

View File

@ -64,7 +64,7 @@ export interface K8sNodesRowData {
const nodeGroupColumnConfig = {
title: (
<div className="column-header node-group-header">
<div className="column-header entity-group-header">
<Group size={14} /> NODE GROUP
</div>
),
@ -74,6 +74,7 @@ const nodeGroupColumnConfig = {
width: 150,
align: 'left',
sorter: false,
className: 'column entity-group-header',
};
export const getK8sNodesListQuery = (): K8sNodesListPayload => ({
@ -86,7 +87,7 @@ export const getK8sNodesListQuery = (): K8sNodesListPayload => ({
const columnsConfig = [
{
title: <div className="column-header-left">Node Name</div>,
title: <div className="column-header-left name-header">Node Name</div>,
dataIndex: 'nodeName',
key: 'nodeName',
ellipsis: true,
@ -95,7 +96,7 @@ const columnsConfig = [
align: 'left',
},
{
title: <div className="column-header-left">Cluster Name</div>,
title: <div className="column-header-left name-header">Cluster Name</div>,
dataIndex: 'clusterName',
key: 'clusterName',
ellipsis: true,

View File

@ -15,6 +15,7 @@ import get from 'api/browser/localstorage/get';
import set from 'api/browser/localstorage/set';
import logEvent from 'api/common/logEvent';
import { K8sPodsListPayload } from 'api/infraMonitoring/getK8sPodsList';
import classNames from 'classnames';
import { useGetK8sPodsList } from 'hooks/infraMonitoring/useGetK8sPodsList';
import { useGetAggregateKeys } from 'hooks/queryBuilder/useGetAggregateKeys';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
@ -38,7 +39,7 @@ import {
formatDataForTable,
getK8sPodsListColumns,
getK8sPodsListQuery,
IPodColumn,
IEntityColumn,
K8sPodsRowData,
} from '../utils';
import PodDetails from './PodDetails/PodDetails';
@ -47,9 +48,11 @@ import PodDetails from './PodDetails/PodDetails';
function K8sPodsList({
isFiltersVisible,
handleFilterVisibilityChange,
quickFiltersLastUpdated,
}: {
isFiltersVisible: boolean;
handleFilterVisibilityChange: () => void;
quickFiltersLastUpdated: number;
}): JSX.Element {
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
@ -57,9 +60,9 @@ function K8sPodsList({
const [currentPage, setCurrentPage] = useState(1);
const [addedColumns, setAddedColumns] = useState<IPodColumn[]>([]);
const [addedColumns, setAddedColumns] = useState<IEntityColumn[]>([]);
const [availableColumns, setAvailableColumns] = useState<IPodColumn[]>(
const [availableColumns, setAvailableColumns] = useState<IEntityColumn[]>(
defaultAvailableColumns,
);
@ -104,6 +107,11 @@ function K8sPodsList({
K8sCategory.PODS, // infraMonitoringEntity
);
// Reset pagination every time quick filters are changed
useEffect(() => {
setCurrentPage(1);
}, [quickFiltersLastUpdated]);
useEffect(() => {
const addedColumns = JSON.parse(get('k8sPodsAddedColumns') ?? '[]');
@ -124,7 +132,7 @@ function K8sPodsList({
const [orderBy, setOrderBy] = useState<{
columnName: string;
order: 'asc' | 'desc';
} | null>(null);
} | null>({ columnName: 'cpu', order: 'desc' });
const [selectedPodUID, setSelectedPodUID] = useState<string | null>(null);
@ -162,7 +170,7 @@ function K8sPodsList({
selectedRowData: K8sPodsRowData,
): IBuilderQuery['filters'] => {
const baseFilters: IBuilderQuery['filters'] = {
items: [],
items: [...query.filters.items],
op: 'and',
};
@ -201,6 +209,7 @@ function K8sPodsList({
end: Math.floor(maxTime / 1000000),
orderBy,
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [minTime, maxTime, orderBy, selectedRowData]);
const {
@ -338,20 +347,8 @@ function K8sPodsList({
setSelectedPodUID(null);
};
const showPodsTable =
!isError &&
!isLoading &&
!isFetching &&
!(formattedPodsData.length === 0 && queryFilters.items.length > 0);
const showNoFilteredPodsMessage =
!isFetching &&
!isLoading &&
formattedPodsData.length === 0 &&
queryFilters.items.length > 0;
const handleAddColumn = useCallback(
(column: IPodColumn): void => {
(column: IEntityColumn): void => {
setAddedColumns((prev) => [...prev, column]);
setAvailableColumns((prev) => prev.filter((c) => c.value !== column.value));
@ -378,7 +375,7 @@ function K8sPodsList({
}, [groupByFiltersData]);
const handleRemoveColumn = useCallback(
(column: IPodColumn): void => {
(column: IEntityColumn): void => {
setAddedColumns((prev) => prev.filter((c) => c.value !== column.value));
setAvailableColumns((prev) => [...prev, column]);
@ -505,7 +502,26 @@ function K8sPodsList({
/>
{isError && <Typography>{data?.error || 'Something went wrong'}</Typography>}
{showNoFilteredPodsMessage && (
<Table
className={classNames('k8s-list-table', {
'expanded-k8s-list-table': isGroupedByAttribute,
})}
dataSource={isFetching || isLoading ? [] : formattedPodsData}
columns={columns}
pagination={{
current: currentPage,
pageSize,
total: totalCount,
showSizeChanger: false,
hideOnSinglePage: true,
}}
loading={{
spinning: isFetching || isLoading,
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
}}
locale={{
emptyText:
isFetching || isLoading ? null : (
<div className="no-filtered-hosts-message-container">
<div className="no-filtered-hosts-message-content">
<img
@ -519,25 +535,7 @@ function K8sPodsList({
</Typography.Text>
</div>
</div>
)}
{(isFetching || isLoading) && <LoadingContainer />}
{showPodsTable && (
<Table
className="k8s-list-table"
dataSource={isFetching || isLoading ? [] : formattedPodsData}
columns={columns}
pagination={{
current: currentPage,
pageSize,
total: totalCount,
showSizeChanger: false,
hideOnSinglePage: true,
}}
loading={{
spinning: isFetching || isLoading,
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
),
}}
scroll={{ x: true }}
tableLayout="fixed"
@ -552,7 +550,6 @@ function K8sPodsList({
expandedRowKeys,
}}
/>
)}
{selectedPodData && (
<PodDetails

View File

@ -155,6 +155,7 @@ export default function Events({
id: event.data.id,
key: event.data.id,
resources_string: event.data.resources_string,
attributes_string: event.data.attributes_string,
}),
);
@ -174,7 +175,9 @@ export default function Events({
}, [eventsData]);
const handleExpandRow = (record: EventDataType): JSX.Element => (
<EventContents data={record.resources_string} />
<EventContents
data={{ ...record.attributes_string, ...record.resources_string }}
/>
);
const handlePrev = (): void => {

View File

@ -13,6 +13,7 @@ import {
initialQueryState,
} from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import { filterDuplicateFilters } from 'container/InfraMonitoringK8s/entityDetailUtils';
import {
CustomTimeType,
Time,
@ -50,7 +51,7 @@ import { PodDetailProps } from './PodDetail.interfaces';
import PodLogsDetailedView from './PodLogs/PodLogsDetailedView';
import PodTraces from './PodTraces/PodTraces';
const TimeRangeOffset = 1000000;
const TimeRangeOffset = 1000000000;
// eslint-disable-next-line sonarjs/cognitive-complexity
function PodDetails({
@ -101,19 +102,6 @@ function PodDetails({
op: '=',
value: pod?.meta.k8s_pod_name || '',
},
{
id: uuidv4(),
key: {
key: QUERY_KEYS.K8S_CLUSTER_NAME,
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
id: 'k8s_pod_name--string--resource--false',
},
op: '=',
value: pod?.meta.k8s_cluster_name || '',
},
{
id: uuidv4(),
key: {
@ -129,11 +117,7 @@ function PodDetails({
},
],
}),
[
pod?.meta.k8s_cluster_name,
pod?.meta.k8s_namespace_name,
pod?.meta.k8s_pod_name,
],
[pod?.meta.k8s_namespace_name, pod?.meta.k8s_pod_name],
);
const initialEventsFilters = useMemo(
@ -262,11 +246,13 @@ function PodDetails({
return {
op: 'AND',
items: [
items: filterDuplicateFilters(
[
...primaryFilters,
...newFilters,
...(paginationFilter ? [paginationFilter] : []),
].filter((item): item is TagFilterItem => item !== undefined),
),
};
});
},
@ -291,12 +277,14 @@ function PodDetails({
return {
op: 'AND',
items: [
items: filterDuplicateFilters(
[
...primaryFilters,
...value.items.filter(
(item) => item.key?.key !== QUERY_KEYS.K8S_POD_NAME,
),
].filter((item): item is TagFilterItem => item !== undefined),
),
};
});
},

View File

@ -78,8 +78,6 @@ function PodTraces({
[currentQuery],
);
console.log({ updatedCurrentQuery });
const query = updatedCurrentQuery?.builder?.queryData[0] || null;
const { queryData: paginationQueryData } = useUrlQueryData<Pagination>(

View File

@ -100,7 +100,13 @@ export function getStrokeColorForLimitUtilization(value: number): string {
export const getProgressBarText = (percent: number): React.ReactNode =>
`${percent}%`;
export function EntityProgressBar({ value }: { value: number }): JSX.Element {
export function EntityProgressBar({
value,
type,
}: {
value: number;
type: 'request' | 'limit';
}): JSX.Element {
const percentage = Number((value * 100).toFixed(1));
return (
@ -110,7 +116,11 @@ export function EntityProgressBar({ value }: { value: number }): JSX.Element {
strokeLinecap="butt"
size="small"
status="normal"
strokeColor={getStrokeColorForLimitUtilization(value)}
strokeColor={
type === 'limit'
? getStrokeColorForLimitUtilization(value)
: getStrokeColorForRequestUtilization(value)
}
className="progress-bar"
showInfo={false}
/>

View File

@ -150,6 +150,8 @@ export const PodsQuickFiltersConfig: IQuickFiltersConfig[] = [
isColumn: false,
isJSON: false,
},
aggregateOperator: 'noop',
aggregateAttribute: 'k8s_pod_cpu_utilization',
dataSource: DataSource.METRICS,
defaultOpen: false,
},

View File

@ -0,0 +1,18 @@
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
export const filterDuplicateFilters = (
filters: TagFilterItem[],
): TagFilterItem[] => {
const uniqueFilters = [];
const seenIds = new Set();
// eslint-disable-next-line no-restricted-syntax
for (const filter of filters) {
if (!seenIds.has(filter.id)) {
seenIds.add(filter.id);
uniqueFilters.push(filter);
}
}
return uniqueFilters;
};

View File

@ -26,16 +26,9 @@ export interface IEntityColumn {
canRemove: boolean;
}
export interface IPodColumn {
label: string;
value: string;
id: string;
canRemove: boolean;
}
const columnProgressBarClassName = 'column-progress-bar';
export const defaultAddedColumns: IPodColumn[] = [
export const defaultAddedColumns: IEntityColumn[] = [
{
label: 'Pod name',
value: 'podName',
@ -78,12 +71,13 @@ export const defaultAddedColumns: IPodColumn[] = [
id: 'memory',
canRemove: false,
},
{
label: 'Restarts',
value: 'restarts',
id: 'restarts',
canRemove: false,
},
// TODO - Re-enable the column once backend issue is fixed
// {
// label: 'Restarts',
// value: 'restarts',
// id: 'restarts',
// canRemove: false,
// },
];
export const defaultAvailableColumns = [
@ -131,7 +125,7 @@ export const getK8sPodsListQuery = (): K8sPodsListPayload => ({
const podGroupColumnConfig = {
title: (
<div className="column-header pod-group-header">
<div className="column-header entity-group-header">
<Group size={14} /> POD GROUP
</div>
),
@ -140,7 +134,7 @@ const podGroupColumnConfig = {
ellipsis: true,
width: 180,
sorter: false,
className: 'column column-pod-group',
className: 'column entity-group-header',
};
export const dummyColumnConfig = {
@ -160,11 +154,11 @@ const columnsConfig = [
key: 'podName',
width: 180,
ellipsis: true,
sorter: true,
sorter: false,
className: 'column column-pod-name',
},
{
title: <div className="column-header">CPU Req Usage (%)</div>,
title: <div className="column-header med-col">CPU Req Usage (%)</div>,
dataIndex: 'cpu_request',
key: 'cpu_request',
width: 180,
@ -174,7 +168,7 @@ const columnsConfig = [
className: `column ${columnProgressBarClassName}`,
},
{
title: <div className="column-header">CPU Limit Usage (%)</div>,
title: <div className="column-header med-col">CPU Limit Usage (%)</div>,
dataIndex: 'cpu_limit',
key: 'cpu_limit',
width: 120,
@ -192,7 +186,7 @@ const columnsConfig = [
className: `column ${columnProgressBarClassName}`,
},
{
title: <div className="column-header">Mem Req Usage (%)</div>,
title: <div className="column-heade med-col">Mem Req Usage (%)</div>,
dataIndex: 'memory_request',
key: 'memory_request',
width: 120,
@ -201,7 +195,7 @@ const columnsConfig = [
className: `column ${columnProgressBarClassName}`,
},
{
title: <div className="column-header">Mem Limit Usage (%)</div>,
title: <div className="column-header med-col">Mem Limit Usage (%)</div>,
dataIndex: 'memory_limit',
key: 'memory_limit',
width: 120,
@ -219,20 +213,21 @@ const columnsConfig = [
align: 'left',
className: `column ${columnProgressBarClassName}`,
},
{
title: (
<div className="column-header">
<Tooltip title="Container Restarts">Restarts</Tooltip>
</div>
),
dataIndex: 'restarts',
key: 'restarts',
width: 40,
ellipsis: true,
sorter: true,
align: 'left',
className: `column ${columnProgressBarClassName}`,
},
// TODO - Re-enable the column once backend issue is fixed
// {
// title: (
// <div className="column-header">
// <Tooltip title="Container Restarts">Restarts</Tooltip>
// </div>
// ),
// dataIndex: 'restarts',
// key: 'restarts',
// width: 40,
// ellipsis: true,
// sorter: true,
// align: 'left',
// className: `column ${columnProgressBarClassName}`,
// },
];
export const namespaceColumnConfig = {
@ -251,7 +246,7 @@ export const nodeColumnConfig = {
dataIndex: 'node',
key: 'node',
width: 100,
sorter: true,
sorter: false,
ellipsis: true,
align: 'left',
className: 'column column-node',
@ -262,7 +257,7 @@ export const clusterColumnConfig = {
dataIndex: 'cluster',
key: 'cluster',
width: 100,
sorter: true,
sorter: false,
ellipsis: true,
align: 'left',
className: 'column column-cluster',
@ -275,7 +270,7 @@ export const columnConfigMap = {
};
export const getK8sPodsListColumns = (
addedColumns: IPodColumn[],
addedColumns: IEntityColumn[],
groupBy: IBuilderQuery['groupBy'],
): ColumnType<K8sPodsRowData>[] => {
const updatedColumnsConfig = [...columnsConfig];
@ -341,7 +336,7 @@ export const formatDataForTable = (
attribute="CPU Request"
>
<div className="progress-container">
<EntityProgressBar value={pod.podCPURequest} />
<EntityProgressBar value={pod.podCPURequest} type="request" />
</div>
</ValidateColumnValueWrapper>
),
@ -352,7 +347,7 @@ export const formatDataForTable = (
attribute="CPU Limit"
>
<div className="progress-container">
<EntityProgressBar value={pod.podCPULimit} />
<EntityProgressBar value={pod.podCPULimit} type="limit" />
</div>
</ValidateColumnValueWrapper>
),
@ -368,7 +363,7 @@ export const formatDataForTable = (
attribute="Memory Request"
>
<div className="progress-container">
<EntityProgressBar value={pod.podMemoryRequest} />
<EntityProgressBar value={pod.podMemoryRequest} type="request" />
</div>
</ValidateColumnValueWrapper>
),
@ -379,7 +374,7 @@ export const formatDataForTable = (
attribute="Memory Limit"
>
<div className="progress-container">
<EntityProgressBar value={pod.podMemoryLimit} />
<EntityProgressBar value={pod.podMemoryLimit} type="limit" />
</div>
</ValidateColumnValueWrapper>
),

View File

@ -95,6 +95,7 @@ function QueryBuilderSearch({
isMulti,
isFetching,
setSearchKey,
setSearchValue,
searchKey,
key,
exampleQueries,
@ -145,7 +146,11 @@ function QueryBuilderSearch({
const tagEditHandler = (value: string): void => {
updateTag(value);
if (isInfraMonitoring) {
setSearchValue(value);
} else {
handleSearch(value);
}
};
const isDisabled = !!searchValue;

View File

@ -153,6 +153,7 @@ export const useAutoComplete = (
isMulti,
isFetching,
setSearchKey,
setSearchValue,
searchKey,
key,
exampleQueries,
@ -172,6 +173,7 @@ interface IAutoComplete {
isMulti: boolean;
isFetching: boolean;
setSearchKey: (value: string) => void;
setSearchValue: (value: string) => void;
searchKey: string;
key: string;
exampleQueries: TagFilter[];

View File

@ -5,12 +5,12 @@ import { TabRoutes } from 'components/RouteTab/types';
import history from 'lib/history';
import { useLocation } from 'react-use';
import { Hosts } from './constants';
import { Hosts, Kubernetes } from './constants';
export default function InfrastructureMonitoringPage(): JSX.Element {
const { pathname } = useLocation();
const routes: TabRoutes[] = [Hosts];
const routes: TabRoutes[] = [Hosts, Kubernetes];
return (
<div className="infra-monitoring-module-container">