mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-16 09:46:08 +08:00
chore: summary view fixes
This commit is contained in:
parent
61b2f8cb31
commit
f713040b9c
@ -10,24 +10,21 @@ import {
|
||||
} from 'antd';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { useGetMetricsListFilterValues } from 'hooks/metricsExplorer/useGetMetricsListFilterValues';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
||||
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||
import { Search } from 'lucide-react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom-v5-compat';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
import { COMPOSITE_QUERY_KEY } from './constants';
|
||||
import { SUMMARY_FILTERS_KEY } from './constants';
|
||||
|
||||
function MetricNameSearch(): JSX.Element {
|
||||
const { currentQuery } = useQueryBuilder();
|
||||
const { handleChangeQueryData } = useQueryOperations({
|
||||
index: 0,
|
||||
query: currentQuery.builder.queryData[0],
|
||||
entityVersion: '',
|
||||
});
|
||||
const [, setSearchParams] = useSearchParams();
|
||||
function MetricNameSearch({
|
||||
queryFilters,
|
||||
}: {
|
||||
queryFilters: TagFilter;
|
||||
}): JSX.Element {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
|
||||
const [searchString, setSearchString] = useState<string>('');
|
||||
@ -70,9 +67,9 @@ function MetricNameSearch(): JSX.Element {
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(selectedMetricName: string): void => {
|
||||
const newFilter = {
|
||||
const newFilters = {
|
||||
items: [
|
||||
...currentQuery.builder.queryData[0].filters.items,
|
||||
...queryFilters.items,
|
||||
{
|
||||
id: 'metric_name',
|
||||
op: 'CONTAINS',
|
||||
@ -84,27 +81,15 @@ function MetricNameSearch(): JSX.Element {
|
||||
value: selectedMetricName,
|
||||
},
|
||||
],
|
||||
op: 'AND',
|
||||
op: 'and',
|
||||
};
|
||||
const compositeQuery = {
|
||||
...currentQuery,
|
||||
builder: {
|
||||
...currentQuery.builder,
|
||||
queryData: [
|
||||
{
|
||||
...currentQuery.builder.queryData[0],
|
||||
filters: newFilter,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
handleChangeQueryData('filters', newFilter);
|
||||
setSearchParams({
|
||||
[COMPOSITE_QUERY_KEY]: JSON.stringify(compositeQuery),
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[SUMMARY_FILTERS_KEY]: JSON.stringify(newFilters),
|
||||
});
|
||||
setIsPopoverOpen(false);
|
||||
},
|
||||
[currentQuery, handleChangeQueryData, setSearchParams],
|
||||
[queryFilters.items, setSearchParams, searchParams],
|
||||
);
|
||||
|
||||
const metricNameFilterValues = useMemo(
|
||||
@ -198,7 +183,7 @@ function MetricNameSearch(): JSX.Element {
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
const value = e.target.value.trim().toLowerCase();
|
||||
const value = e.target.value.trim();
|
||||
setSearchString(value);
|
||||
debouncedUpdate(value);
|
||||
},
|
||||
|
@ -1,26 +1,23 @@
|
||||
import { Button, Menu, Popover, Tooltip } from 'antd';
|
||||
import { MetricType } from 'api/metricsExplorer/getMetricsList';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
||||
import { Search } from 'lucide-react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom-v5-compat';
|
||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
import {
|
||||
COMPOSITE_QUERY_KEY,
|
||||
METRIC_TYPE_LABEL_MAP,
|
||||
METRIC_TYPE_VALUES_MAP,
|
||||
SUMMARY_FILTERS_KEY,
|
||||
} from './constants';
|
||||
|
||||
function MetricTypeSearch(): JSX.Element {
|
||||
const { currentQuery } = useQueryBuilder();
|
||||
const { handleChangeQueryData } = useQueryOperations({
|
||||
index: 0,
|
||||
query: currentQuery.builder.queryData[0],
|
||||
entityVersion: '',
|
||||
});
|
||||
function MetricTypeSearch({
|
||||
queryFilters,
|
||||
}: {
|
||||
queryFilters: TagFilter;
|
||||
}): JSX.Element {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
const [, setSearchParams] = useSearchParams();
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
|
||||
|
||||
const menuItems = useMemo(
|
||||
@ -40,9 +37,9 @@ function MetricTypeSearch(): JSX.Element {
|
||||
const handleSelect = useCallback(
|
||||
(selectedMetricType: string): void => {
|
||||
if (selectedMetricType !== 'all') {
|
||||
const newFilter = {
|
||||
const newFilters = {
|
||||
items: [
|
||||
...currentQuery.builder.queryData[0].filters.items,
|
||||
...queryFilters.items,
|
||||
{
|
||||
id: 'metric_type',
|
||||
op: '=',
|
||||
@ -56,49 +53,23 @@ function MetricTypeSearch(): JSX.Element {
|
||||
],
|
||||
op: 'AND',
|
||||
};
|
||||
const compositeQuery = {
|
||||
...currentQuery,
|
||||
builder: {
|
||||
...currentQuery.builder,
|
||||
queryData: [
|
||||
{
|
||||
...currentQuery.builder.queryData[0],
|
||||
filters: newFilter,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
handleChangeQueryData('filters', newFilter);
|
||||
setSearchParams({
|
||||
[COMPOSITE_QUERY_KEY]: JSON.stringify(compositeQuery),
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[SUMMARY_FILTERS_KEY]: JSON.stringify(newFilters),
|
||||
});
|
||||
} else {
|
||||
const newFilter = {
|
||||
items: currentQuery.builder.queryData[0].filters.items.filter(
|
||||
(item) => item.id !== 'metric_type',
|
||||
),
|
||||
const newFilters = {
|
||||
items: queryFilters.items.filter((item) => item.id !== 'metric_type'),
|
||||
op: 'AND',
|
||||
};
|
||||
const compositeQuery = {
|
||||
...currentQuery,
|
||||
builder: {
|
||||
...currentQuery.builder,
|
||||
queryData: [
|
||||
{
|
||||
...currentQuery.builder.queryData[0],
|
||||
filters: newFilter,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
handleChangeQueryData('filters', newFilter);
|
||||
setSearchParams({
|
||||
[COMPOSITE_QUERY_KEY]: JSON.stringify(compositeQuery),
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[SUMMARY_FILTERS_KEY]: JSON.stringify(newFilters),
|
||||
});
|
||||
}
|
||||
setIsPopoverOpen(false);
|
||||
},
|
||||
[currentQuery, handleChangeQueryData, setSearchParams],
|
||||
[queryFilters.items, setSearchParams, searchParams],
|
||||
);
|
||||
|
||||
const menu = (
|
||||
|
@ -12,7 +12,7 @@ import { Info } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { MetricsListItemRowData, MetricsTableProps } from './types';
|
||||
import { metricsTableColumns } from './utils';
|
||||
import { getMetricsTableColumns } from './utils';
|
||||
|
||||
function MetricsTable({
|
||||
isLoading,
|
||||
@ -24,6 +24,7 @@ function MetricsTable({
|
||||
setOrderBy,
|
||||
totalCount,
|
||||
openMetricDetails,
|
||||
queryFilters,
|
||||
}: MetricsTableProps): JSX.Element {
|
||||
const handleTableChange: TableProps<MetricsListItemRowData>['onChange'] = useCallback(
|
||||
(
|
||||
@ -74,7 +75,7 @@ function MetricsTable({
|
||||
),
|
||||
}}
|
||||
dataSource={data}
|
||||
columns={metricsTableColumns}
|
||||
columns={getMetricsTableColumns(queryFilters)}
|
||||
locale={{
|
||||
emptyText: isLoading ? null : (
|
||||
<div
|
||||
|
@ -1,29 +1,25 @@
|
||||
import './Summary.styles.scss';
|
||||
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { initialQueriesMap } from 'constants/queryBuilder';
|
||||
import { usePageSize } from 'container/InfraMonitoringK8s/utils';
|
||||
import { useGetMetricsList } from 'hooks/metricsExplorer/useGetMetricsList';
|
||||
import { useGetMetricsTreeMap } from 'hooks/metricsExplorer/useGetMetricsTreeMap';
|
||||
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 { useSearchParams } from 'react-router-dom-v5-compat';
|
||||
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 {
|
||||
COMPOSITE_QUERY_KEY,
|
||||
IS_INSPECT_MODAL_OPEN_KEY,
|
||||
IS_METRIC_DETAILS_OPEN_KEY,
|
||||
SELECTED_METRIC_NAME_KEY,
|
||||
SUMMARY_FILTERS_KEY,
|
||||
} from './constants';
|
||||
import MetricsSearch from './MetricsSearch';
|
||||
import MetricsTable from './MetricsTable';
|
||||
@ -63,57 +59,25 @@ function Summary(): JSX.Element {
|
||||
(state) => state.globalTime,
|
||||
);
|
||||
|
||||
const { currentQuery, updateAllQueriesOperators } = useQueryBuilder();
|
||||
|
||||
const defaultQuery = useMemo(() => {
|
||||
const query = updateAllQueriesOperators(
|
||||
initialQueriesMap.metrics,
|
||||
PANEL_TYPES.LIST,
|
||||
DataSource.METRICS,
|
||||
);
|
||||
|
||||
const queryFilters: TagFilter = useMemo(() => {
|
||||
const encodedFilters = searchParams.get(SUMMARY_FILTERS_KEY);
|
||||
if (encodedFilters) {
|
||||
return JSON.parse(encodedFilters);
|
||||
}
|
||||
return {
|
||||
...query,
|
||||
builder: {
|
||||
...query.builder,
|
||||
queryData: [
|
||||
{
|
||||
...query.builder.queryData[0],
|
||||
orderBy: [DEFAULT_ORDER_BY],
|
||||
},
|
||||
],
|
||||
},
|
||||
items: [],
|
||||
op: 'AND',
|
||||
};
|
||||
}, [updateAllQueriesOperators]);
|
||||
|
||||
useShareBuilderUrl(defaultQuery);
|
||||
}, [searchParams]);
|
||||
|
||||
// This is used to avoid the filters from being serialized with the id
|
||||
const currentQueryFiltersString = useMemo(() => {
|
||||
const filters = currentQuery?.builder?.queryData[0]?.filters;
|
||||
if (!filters) return '';
|
||||
const queryFiltersWithoutId = useMemo(() => {
|
||||
const filtersWithoutId = {
|
||||
...filters,
|
||||
items: filters.items.map(({ id, ...rest }) => rest),
|
||||
...queryFilters,
|
||||
items: queryFilters.items.map(({ id, ...rest }) => rest),
|
||||
};
|
||||
return JSON.stringify(filtersWithoutId);
|
||||
}, [currentQuery]);
|
||||
|
||||
const queryFilters = useMemo(
|
||||
() =>
|
||||
currentQuery?.builder?.queryData[0]?.filters || {
|
||||
items: [],
|
||||
op: 'and',
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[currentQueryFiltersString],
|
||||
);
|
||||
|
||||
const { handleChangeQueryData } = useQueryOperations({
|
||||
index: 0,
|
||||
query: currentQuery.builder.queryData[0],
|
||||
entityVersion: '',
|
||||
});
|
||||
}, [queryFilters]);
|
||||
|
||||
const metricsListQuery = useMemo(() => {
|
||||
const baseQuery = getMetricsListQuery();
|
||||
@ -146,6 +110,15 @@ function Summary(): JSX.Element {
|
||||
isError: isMetricsError,
|
||||
} = useGetMetricsList(metricsListQuery, {
|
||||
enabled: !!metricsListQuery && !isInspectModalOpen,
|
||||
queryKey: [
|
||||
'metricsList',
|
||||
queryFiltersWithoutId,
|
||||
orderBy,
|
||||
pageSize,
|
||||
currentPage,
|
||||
minTime,
|
||||
maxTime,
|
||||
],
|
||||
});
|
||||
|
||||
const isListViewError = useMemo(
|
||||
@ -160,6 +133,13 @@ function Summary(): JSX.Element {
|
||||
isError: isTreeMapError,
|
||||
} = useGetMetricsTreeMap(metricsTreemapQuery, {
|
||||
enabled: !!metricsTreemapQuery && !isInspectModalOpen,
|
||||
queryKey: [
|
||||
'metricsTreemap',
|
||||
queryFiltersWithoutId,
|
||||
heatmapView,
|
||||
minTime,
|
||||
maxTime,
|
||||
],
|
||||
});
|
||||
|
||||
const isProportionViewError = useMemo(
|
||||
@ -169,48 +149,23 @@ function Summary(): JSX.Element {
|
||||
|
||||
const handleFilterChange = useCallback(
|
||||
(value: TagFilter) => {
|
||||
handleChangeQueryData('filters', value);
|
||||
const compositeQuery = {
|
||||
...currentQuery,
|
||||
builder: {
|
||||
...currentQuery.builder,
|
||||
queryData: [
|
||||
{
|
||||
...currentQuery.builder.queryData[0],
|
||||
filters: value,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
setSearchParams({
|
||||
[COMPOSITE_QUERY_KEY]: JSON.stringify(compositeQuery),
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[SUMMARY_FILTERS_KEY]: JSON.stringify(value),
|
||||
});
|
||||
setCurrentPage(1);
|
||||
},
|
||||
[handleChangeQueryData, currentQuery, setSearchParams],
|
||||
[setSearchParams, searchParams],
|
||||
);
|
||||
|
||||
const updatedCurrentQuery = useMemo(
|
||||
const searchQuery = useMemo(
|
||||
() => ({
|
||||
...currentQuery,
|
||||
builder: {
|
||||
...currentQuery.builder,
|
||||
queryData: [
|
||||
{
|
||||
...currentQuery.builder.queryData[0],
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: {
|
||||
...currentQuery.builder.queryData[0].aggregateAttribute,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
...initialQueriesMap.metrics.builder.queryData[0],
|
||||
filters: queryFilters,
|
||||
}),
|
||||
[currentQuery],
|
||||
[queryFilters],
|
||||
);
|
||||
|
||||
const searchQuery = updatedCurrentQuery?.builder?.queryData[0] || null;
|
||||
|
||||
const onPaginationChange = (page: number, pageSize: number): void => {
|
||||
setCurrentPage(page);
|
||||
setPageSize(pageSize);
|
||||
@ -225,6 +180,7 @@ function Summary(): JSX.Element {
|
||||
setSelectedMetricName(metricName);
|
||||
setIsMetricDetailsOpen(true);
|
||||
setSearchParams({
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[IS_METRIC_DETAILS_OPEN_KEY]: 'true',
|
||||
[SELECTED_METRIC_NAME_KEY]: metricName,
|
||||
});
|
||||
@ -234,6 +190,7 @@ function Summary(): JSX.Element {
|
||||
setSelectedMetricName(null);
|
||||
setIsMetricDetailsOpen(false);
|
||||
setSearchParams({
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[IS_METRIC_DETAILS_OPEN_KEY]: 'false',
|
||||
[SELECTED_METRIC_NAME_KEY]: '',
|
||||
});
|
||||
@ -244,19 +201,17 @@ function Summary(): JSX.Element {
|
||||
setIsInspectModalOpen(true);
|
||||
setIsMetricDetailsOpen(false);
|
||||
setSearchParams({
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[IS_INSPECT_MODAL_OPEN_KEY]: 'true',
|
||||
[SELECTED_METRIC_NAME_KEY]: metricName,
|
||||
});
|
||||
};
|
||||
|
||||
const closeInspectModal = (): void => {
|
||||
handleChangeQueryData('filters', {
|
||||
items: [],
|
||||
op: 'AND',
|
||||
});
|
||||
setIsInspectModalOpen(false);
|
||||
setSelectedMetricName(null);
|
||||
setSearchParams({
|
||||
...Object.fromEntries(searchParams.entries()),
|
||||
[IS_INSPECT_MODAL_OPEN_KEY]: 'false',
|
||||
[SELECTED_METRIC_NAME_KEY]: '',
|
||||
});
|
||||
@ -284,6 +239,7 @@ function Summary(): JSX.Element {
|
||||
setOrderBy={setOrderBy}
|
||||
totalCount={metricsData?.payload?.data?.total || 0}
|
||||
openMetricDetails={openMetricDetails}
|
||||
queryFilters={queryFilters}
|
||||
/>
|
||||
</div>
|
||||
{isMetricDetailsOpen && (
|
||||
|
@ -36,4 +36,4 @@ export const METRIC_TYPE_VALUES_MAP = {
|
||||
export const IS_METRIC_DETAILS_OPEN_KEY = 'isMetricDetailsOpen';
|
||||
export const IS_INSPECT_MODAL_OPEN_KEY = 'isInspectModalOpen';
|
||||
export const SELECTED_METRIC_NAME_KEY = 'selectedMetricName';
|
||||
export const COMPOSITE_QUERY_KEY = 'compositeQuery';
|
||||
export const SUMMARY_FILTERS_KEY = 'summaryFilters';
|
||||
|
@ -15,6 +15,7 @@ export interface MetricsTableProps {
|
||||
setOrderBy: Dispatch<SetStateAction<OrderByPayload>>;
|
||||
totalCount: number;
|
||||
openMetricDetails: (metricName: string) => void;
|
||||
queryFilters: TagFilter;
|
||||
}
|
||||
|
||||
export interface MetricsSearchProps {
|
||||
|
@ -18,18 +18,21 @@ import {
|
||||
Gauge,
|
||||
} from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
import { METRIC_TYPE_LABEL_MAP } from './constants';
|
||||
import MetricNameSearch from './MetricNameSearch';
|
||||
import MetricTypeSearch from './MetricTypeSearch';
|
||||
import { MetricsListItemRowData, TreemapTile, TreemapViewType } from './types';
|
||||
|
||||
export const metricsTableColumns: ColumnType<MetricsListItemRowData>[] = [
|
||||
export const getMetricsTableColumns = (
|
||||
queryFilters: TagFilter,
|
||||
): ColumnType<MetricsListItemRowData>[] => [
|
||||
{
|
||||
title: (
|
||||
<div className="metric-name-column-header">
|
||||
<span className="metric-name-column-header-text">METRIC</span>
|
||||
<MetricNameSearch />
|
||||
<MetricNameSearch queryFilters={queryFilters} />
|
||||
</div>
|
||||
),
|
||||
dataIndex: 'metric_name',
|
||||
@ -51,7 +54,7 @@ export const metricsTableColumns: ColumnType<MetricsListItemRowData>[] = [
|
||||
title: (
|
||||
<div className="metric-type-column-header">
|
||||
<span className="metric-type-column-header-text">TYPE</span>
|
||||
<MetricTypeSearch />
|
||||
<MetricTypeSearch queryFilters={queryFilters} />
|
||||
</div>
|
||||
),
|
||||
dataIndex: 'metric_type',
|
||||
|
@ -2,8 +2,13 @@ import './MetricsExplorerPage.styles.scss';
|
||||
|
||||
import RouteTab from 'components/RouteTab';
|
||||
import { TabRoutes } from 'components/RouteTab/types';
|
||||
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||
import history from 'lib/history';
|
||||
import { useMemo } from 'react';
|
||||
import { useLocation } from 'react-use';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import { Explorer, Summary, Views } from './constants';
|
||||
|
||||
@ -12,6 +17,20 @@ function MetricsExplorerPage(): JSX.Element {
|
||||
|
||||
const routes: TabRoutes[] = [Summary, Explorer, Views];
|
||||
|
||||
const { updateAllQueriesOperators } = useQueryBuilder();
|
||||
|
||||
const defaultQuery = useMemo(
|
||||
() =>
|
||||
updateAllQueriesOperators(
|
||||
initialQueriesMap[DataSource.METRICS],
|
||||
PANEL_TYPES.LIST,
|
||||
DataSource.METRICS,
|
||||
),
|
||||
[updateAllQueriesOperators],
|
||||
);
|
||||
|
||||
useShareBuilderUrl(defaultQuery);
|
||||
|
||||
return (
|
||||
<div className="metrics-explorer-page">
|
||||
<RouteTab routes={routes} activeKey={pathname} history={history} />
|
||||
|
Loading…
x
Reference in New Issue
Block a user