258 lines
7.0 KiB
TypeScript
Raw Normal View History

import './Summary.styles.scss';
import * as Sentry from '@sentry/react';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import { usePageSize } from 'container/InfraMonitoringK8s/utils';
import { useGetMetricsList } from 'hooks/metricsExplorer/useGetMetricsList';
import { useGetMetricsTreeMap } from 'hooks/metricsExplorer/useGetMetricsTreeMap';
2025-03-21 00:28:15 +05:30
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { useCallback, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import { GlobalReducer } from 'types/reducer/globalTime';
import InspectModal from '../Inspect';
import MetricDetails from '../MetricDetails';
import MetricsSearch from './MetricsSearch';
import MetricsTable from './MetricsTable';
import MetricsTreemap from './MetricsTreemap';
import { OrderByPayload, TreemapViewType } from './types';
import {
convertNanoToMilliseconds,
formatDataForMetricsTable,
getMetricsListQuery,
} from './utils';
const DEFAULT_ORDER_BY: OrderByPayload = {
columnName: 'samples',
order: 'desc',
};
function Summary(): JSX.Element {
const { pageSize, setPageSize } = usePageSize('metricsExplorer');
const [currentPage, setCurrentPage] = useState(1);
const [orderBy, setOrderBy] = useState<OrderByPayload>(DEFAULT_ORDER_BY);
const [heatmapView, setHeatmapView] = useState<TreemapViewType>(
TreemapViewType.TIMESERIES,
);
const [isMetricDetailsOpen, setIsMetricDetailsOpen] = useState(false);
const [isInspectModalOpen, setIsInspectModalOpen] = useState(false);
const [selectedMetricName, setSelectedMetricName] = useState<string | null>(
null,
);
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
);
const { currentQuery, updateAllQueriesOperators } = useQueryBuilder();
const defaultQuery = useMemo(() => {
const query = updateAllQueriesOperators(
initialQueriesMap.metrics,
PANEL_TYPES.LIST,
DataSource.METRICS,
);
return {
...query,
builder: {
...query.builder,
queryData: [
{
...query.builder.queryData[0],
orderBy: [DEFAULT_ORDER_BY],
},
],
},
};
}, [updateAllQueriesOperators]);
useShareBuilderUrl(defaultQuery);
const queryFilters = useMemo(
() =>
currentQuery?.builder?.queryData[0]?.filters || {
items: [],
op: 'and',
},
[currentQuery],
);
const { handleChangeQueryData } = useQueryOperations({
index: 0,
query: currentQuery.builder.queryData[0],
entityVersion: '',
});
const metricsListQuery = useMemo(() => {
const baseQuery = getMetricsListQuery();
return {
...baseQuery,
limit: pageSize,
offset: (currentPage - 1) * pageSize,
filters: queryFilters,
start: convertNanoToMilliseconds(minTime),
end: convertNanoToMilliseconds(maxTime),
orderBy,
};
}, [queryFilters, minTime, maxTime, orderBy, pageSize, currentPage]);
const metricsTreemapQuery = useMemo(
() => ({
limit: 100,
filters: queryFilters,
treemap: heatmapView,
start: convertNanoToMilliseconds(minTime),
end: convertNanoToMilliseconds(maxTime),
}),
[queryFilters, heatmapView, minTime, maxTime],
);
const {
data: metricsData,
isLoading: isMetricsLoading,
isFetching: isMetricsFetching,
2025-03-19 17:31:36 +05:30
isError: isMetricsError,
} = useGetMetricsList(metricsListQuery, {
enabled: !!metricsListQuery && !isInspectModalOpen,
});
const isListViewError = useMemo(
() => isMetricsError || !!(metricsData && metricsData.statusCode !== 200),
[isMetricsError, metricsData],
);
const {
data: treeMapData,
isLoading: isTreeMapLoading,
isFetching: isTreeMapFetching,
2025-03-19 17:31:36 +05:30
isError: isTreeMapError,
} = useGetMetricsTreeMap(metricsTreemapQuery, {
enabled: !!metricsTreemapQuery && !isInspectModalOpen,
});
const isProportionViewError = useMemo(
() => isTreeMapError || treeMapData?.statusCode !== 200,
[isTreeMapError, treeMapData],
);
const handleFilterChange = useCallback(
(value: TagFilter) => {
handleChangeQueryData('filters', value);
setCurrentPage(1);
},
[handleChangeQueryData],
);
const updatedCurrentQuery = useMemo(
() => ({
...currentQuery,
builder: {
...currentQuery.builder,
queryData: [
{
...currentQuery.builder.queryData[0],
aggregateOperator: 'noop',
aggregateAttribute: {
...currentQuery.builder.queryData[0].aggregateAttribute,
},
},
],
},
}),
[currentQuery],
);
const searchQuery = updatedCurrentQuery?.builder?.queryData[0] || null;
const onPaginationChange = (page: number, pageSize: number): void => {
setCurrentPage(page);
setPageSize(pageSize);
};
const formattedMetricsData = useMemo(
() => formatDataForMetricsTable(metricsData?.payload?.data?.metrics || []),
[metricsData],
);
const openMetricDetails = (metricName: string): void => {
setSelectedMetricName(metricName);
setIsMetricDetailsOpen(true);
};
const closeMetricDetails = (): void => {
setSelectedMetricName(null);
setIsMetricDetailsOpen(false);
};
const openInspectModal = (metricName: string): void => {
setSelectedMetricName(metricName);
setIsInspectModalOpen(true);
setIsMetricDetailsOpen(false);
};
const closeInspectModal = (): void => {
handleChangeQueryData('filters', {
items: [],
op: 'AND',
});
setIsInspectModalOpen(false);
setSelectedMetricName(null);
};
return (
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
<div className="metrics-explorer-summary-tab">
<MetricsSearch
query={searchQuery}
onChange={handleFilterChange}
heatmapView={heatmapView}
setHeatmapView={setHeatmapView}
/>
<MetricsTreemap
data={treeMapData?.payload}
isLoading={isTreeMapLoading || isTreeMapFetching}
isError={isProportionViewError}
viewType={heatmapView}
openMetricDetails={openMetricDetails}
/>
<MetricsTable
isLoading={isMetricsLoading || isMetricsFetching}
isError={isListViewError}
data={formattedMetricsData}
pageSize={pageSize}
currentPage={currentPage}
onPaginationChange={onPaginationChange}
setOrderBy={setOrderBy}
totalCount={metricsData?.payload?.data?.total || 0}
openMetricDetails={openMetricDetails}
/>
</div>
{isMetricDetailsOpen && (
<MetricDetails
isOpen={isMetricDetailsOpen}
onClose={closeMetricDetails}
metricName={selectedMetricName}
isModalTimeSelection={false}
openInspectModal={openInspectModal}
/>
)}
{isInspectModalOpen && (
<InspectModal
isOpen={isInspectModalOpen}
onClose={closeInspectModal}
metricName={selectedMetricName}
/>
)}
</Sentry.ErrorBoundary>
);
}
export default Summary;