From 3d3dd985492fb5f20531c41488b797d20ccabb6a Mon Sep 17 00:00:00 2001 From: Amlan Kumar Nandy <45410599+amlannandy@users.noreply.github.com> Date: Wed, 19 Mar 2025 17:31:36 +0530 Subject: [PATCH] chore: metrics explorer fixes (#7362) --- .../getMetricsListFilterKeys.ts | 10 +++++ .../Explorer/EmptyMetricsSearch.tsx | 16 +++++++ .../Explorer/Explorer.styles.scss | 28 ++++++++++--- .../MetricsExplorer/Explorer/Explorer.tsx | 20 +++------ .../MetricsExplorer/Explorer/TimeSeries.tsx | 12 +++++- .../MetricDetails/AllAttributes.tsx | 41 ++++++++---------- .../MetricDetails/MetricDetails.tsx | 42 +++++++------------ .../MetricsExplorer/Summary/MetricsTable.tsx | 5 ++- .../Summary/MetricsTreemap.tsx | 11 ++++- .../MetricsExplorer/Summary/Summary.tsx | 4 ++ .../MetricsExplorer/Summary/types.ts | 2 + frontend/src/container/SideNav/menuItems.tsx | 3 +- .../TimeSeriesView/TimeSeriesView.tsx | 11 ++++- .../useGetMetricsListFilterKeys.ts | 5 ++- .../queryBuilder/useFetchKeysAndValues.ts | 14 +++++-- 15 files changed, 145 insertions(+), 79 deletions(-) create mode 100644 frontend/src/container/MetricsExplorer/Explorer/EmptyMetricsSearch.tsx diff --git a/frontend/src/api/metricsExplorer/getMetricsListFilterKeys.ts b/frontend/src/api/metricsExplorer/getMetricsListFilterKeys.ts index ce37f35935..4fb15ab65c 100644 --- a/frontend/src/api/metricsExplorer/getMetricsListFilterKeys.ts +++ b/frontend/src/api/metricsExplorer/getMetricsListFilterKeys.ts @@ -12,12 +12,22 @@ export interface MetricsListFilterKeysResponse { }; } +export interface GetMetricsListFilterKeysParams { + searchText: string; + limit?: number; +} + export const getMetricsListFilterKeys = async ( + params: GetMetricsListFilterKeysParams, signal?: AbortSignal, headers?: Record, ): Promise | ErrorResponse> => { try { const response = await axios.get('/metrics/filters/keys', { + params: { + searchText: params.searchText, + limit: params.limit, + }, signal, headers, }); diff --git a/frontend/src/container/MetricsExplorer/Explorer/EmptyMetricsSearch.tsx b/frontend/src/container/MetricsExplorer/Explorer/EmptyMetricsSearch.tsx new file mode 100644 index 0000000000..66962c7e97 --- /dev/null +++ b/frontend/src/container/MetricsExplorer/Explorer/EmptyMetricsSearch.tsx @@ -0,0 +1,16 @@ +import { Typography } from 'antd'; +import { Empty } from 'antd/lib'; + +export default function EmptyMetricsSearch(): JSX.Element { + return ( +
+ + Please build and run query to see the result + + } + /> +
+ ); +} diff --git a/frontend/src/container/MetricsExplorer/Explorer/Explorer.styles.scss b/frontend/src/container/MetricsExplorer/Explorer/Explorer.styles.scss index 8e0836fcb7..b2b70ee034 100644 --- a/frontend/src/container/MetricsExplorer/Explorer/Explorer.styles.scss +++ b/frontend/src/container/MetricsExplorer/Explorer/Explorer.styles.scss @@ -22,7 +22,11 @@ .query-section { max-height: 450px; - overflow-y: scroll; + overflow-y: auto; + + .rc-virtual-list-holder { + height: 150px; + } } .explore-tabs { @@ -51,17 +55,31 @@ } .explore-content { + .ant-space { + margin-top: 10px; + margin-bottom: 20px; + } + + .empty-metrics-search { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + } + .time-series-container { display: flex; gap: 10px; width: 100%; height: fit-content; overflow-y: scroll; + } - .time-series-view { - min-width: 100%; - width: 100%; - } + .time-series-view { + min-width: 100%; + width: 100%; } .related-metrics-container { diff --git a/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx b/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx index bba15b9476..3bfc8fb37e 100644 --- a/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx +++ b/frontend/src/container/MetricsExplorer/Explorer/Explorer.tsx @@ -23,7 +23,6 @@ import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToD import { v4 as uuid } from 'uuid'; import QuerySection from './QuerySection'; -import RelatedMetrics from './RelatedMetrics'; import TimeSeries from './TimeSeries'; import { ExplorerTabs } from './types'; @@ -51,15 +50,6 @@ function Explorer(): JSX.Element { const handleToggleShowOneChartPerQuery = (): void => toggleShowOneChartPerQuery(!showOneChartPerQuery); - const metricNames = useMemo(() => { - if (!stagedQuery || stagedQuery.builder.queryData.length === 0) { - return []; - } - return stagedQuery.builder.queryData.map( - (query) => query.aggregateAttribute.key, - ); - }, [stagedQuery]); - const exportDefaultQuery = useMemo( () => updateAllQueriesOperators( @@ -159,7 +149,8 @@ function Explorer(): JSX.Element { > Time series - + */}
{selectedTab === ExplorerTabs.TIME_SERIES && ( )} - {selectedTab === ExplorerTabs.RELATED_METRICS && ( + {/* TODO: Enable once we have resolved all related metrics issues */} + {/* {selectedTab === ExplorerTabs.RELATED_METRICS && ( - )} + )} */}
(''); + const queries = useQueries( queryPayloads.map((payload, index) => ({ queryKey: [ @@ -98,12 +101,17 @@ function TimeSeries({ showOneChartPerQuery }: TimeSeriesProps): JSX.Element { [showOneChartPerQuery, queries], ); + const onUnitChangeHandler = (value: string): void => { + setYAxisUnit(value); + }; + return (
+ {responseData.map((datapoint, index) => (
diff --git a/frontend/src/container/MetricsExplorer/MetricDetails/AllAttributes.tsx b/frontend/src/container/MetricsExplorer/MetricDetails/AllAttributes.tsx index 0a0f5e46f5..b300c28791 100644 --- a/frontend/src/container/MetricsExplorer/MetricDetails/AllAttributes.tsx +++ b/frontend/src/container/MetricsExplorer/MetricDetails/AllAttributes.tsx @@ -1,36 +1,30 @@ import { Button, Collapse, Input, Typography } from 'antd'; import { ColumnsType } from 'antd/es/table'; import { ResizeTable } from 'components/ResizeTable'; -import ROUTES from 'constants/routes'; import { DataType } from 'container/LogDetailedView/TableView'; -import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { Search } from 'lucide-react'; -import { useCallback, useMemo, useState } from 'react'; +import { useMemo, useState } from 'react'; import { AllAttributesProps } from './types'; -import { getMetricDetailsQuery } from './utils'; -function AllAttributes({ - attributes, - metricName, -}: AllAttributesProps): JSX.Element { +function AllAttributes({ attributes }: AllAttributesProps): JSX.Element { const [searchString, setSearchString] = useState(''); const [activeKey, setActiveKey] = useState( 'all-attributes', ); - const { safeNavigate } = useSafeNavigate(); + // const { safeNavigate } = useSafeNavigate(); - const goToMetricsExploreWithAppliedAttribute = useCallback( - (key: string, value: string) => { - const compositeQuery = getMetricDetailsQuery(metricName, { key, value }); - const encodedCompositeQuery = JSON.stringify(compositeQuery); - safeNavigate( - `${ROUTES.METRICS_EXPLORER_EXPLORER}?compositeQuery=${encodedCompositeQuery}`, - ); - }, - [metricName, safeNavigate], - ); + // const goToMetricsExploreWithAppliedAttribute = useCallback( + // (key: string, value: string) => { + // const compositeQuery = getMetricDetailsQuery(metricName, { key, value }); + // const encodedCompositeQuery = JSON.stringify(compositeQuery); + // safeNavigate( + // `${ROUTES.METRICS_EXPLORER_EXPLORER}?compositeQuery=${encodedCompositeQuery}`, + // ); + // }, + // [metricName, safeNavigate], + // ); const filteredAttributes = useMemo( () => @@ -87,9 +81,10 @@ function AllAttributes({ @@ -98,7 +93,7 @@ function AllAttributes({ ), }, ], - [goToMetricsExploreWithAppliedAttribute], + [], ); const items = useMemo( diff --git a/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx b/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx index 395b49c268..8473cd68b6 100644 --- a/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx +++ b/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx @@ -2,21 +2,11 @@ import './MetricDetails.styles.scss'; import '../Summary/Summary.styles.scss'; import { Color } from '@signozhq/design-tokens'; -import { - Button, - Divider, - Drawer, - Empty, - Skeleton, - Tooltip, - Typography, -} from 'antd'; -import ROUTES from 'constants/routes'; +import { Divider, Drawer, Empty, Skeleton, Tooltip, Typography } from 'antd'; import { useGetMetricDetails } from 'hooks/metricsExplorer/useGetMetricDetails'; import { useIsDarkMode } from 'hooks/useDarkMode'; -import { useSafeNavigate } from 'hooks/useSafeNavigate'; -import { Compass, X } from 'lucide-react'; -import { useCallback, useMemo } from 'react'; +import { X } from 'lucide-react'; +import { useMemo } from 'react'; import { formatNumberIntoHumanReadableFormat } from '../Summary/utils'; import AllAttributes from './AllAttributes'; @@ -26,7 +16,6 @@ import { MetricDetailsProps } from './types'; import { formatNumberToCompactFormat, formatTimestampToReadableDate, - getMetricDetailsQuery, } from './utils'; function MetricDetails({ @@ -35,7 +24,7 @@ function MetricDetails({ metricName, }: MetricDetailsProps): JSX.Element { const isDarkMode = useIsDarkMode(); - const { safeNavigate } = useSafeNavigate(); + // const { safeNavigate } = useSafeNavigate(); const { data, @@ -72,15 +61,15 @@ function MetricDetails({ ); }, [metric]); - const goToMetricsExplorerwithSelectedMetric = useCallback(() => { - if (metricName) { - const compositeQuery = getMetricDetailsQuery(metricName); - const encodedCompositeQuery = JSON.stringify(compositeQuery); - safeNavigate( - `${ROUTES.METRICS_EXPLORER_EXPLORER}?compositeQuery=${encodedCompositeQuery}`, - ); - } - }, [metricName, safeNavigate]); + // const goToMetricsExplorerwithSelectedMetric = useCallback(() => { + // if (metricName) { + // const compositeQuery = getMetricDetailsQuery(metricName); + // const encodedCompositeQuery = JSON.stringify(compositeQuery); + // safeNavigate( + // `${ROUTES.METRICS_EXPLORER_EXPLORER}?compositeQuery=${encodedCompositeQuery}`, + // ); + // } + // }, [metricName, safeNavigate]); const isMetricDetailsError = metricDetailsError || !metric; @@ -93,7 +82,8 @@ function MetricDetails({ {metric?.name}
- + */} } placement="right" diff --git a/frontend/src/container/MetricsExplorer/Summary/MetricsTable.tsx b/frontend/src/container/MetricsExplorer/Summary/MetricsTable.tsx index cb950f9a2f..d103fc99de 100644 --- a/frontend/src/container/MetricsExplorer/Summary/MetricsTable.tsx +++ b/frontend/src/container/MetricsExplorer/Summary/MetricsTable.tsx @@ -16,6 +16,7 @@ import { metricsTableColumns } from './utils'; function MetricsTable({ isLoading, + isError, data, pageSize, currentPage, @@ -76,7 +77,9 @@ function MetricsTable({ className="empty-state-svg" /> - This query had no results. Edit your query and try again! + {isError + ? 'Error fetching metrics. If the problem persists, please contact support.' + : 'This query had no results. Edit your query and try again!'} ), diff --git a/frontend/src/container/MetricsExplorer/Summary/MetricsTreemap.tsx b/frontend/src/container/MetricsExplorer/Summary/MetricsTreemap.tsx index 6b659d84de..1618200431 100644 --- a/frontend/src/container/MetricsExplorer/Summary/MetricsTreemap.tsx +++ b/frontend/src/container/MetricsExplorer/Summary/MetricsTreemap.tsx @@ -22,6 +22,7 @@ function MetricsTreemap({ viewType, data, isLoading, + isError, openMetricDetails, }: MetricsTreemapProps): JSX.Element { const { width: windowWidth } = useWindowSize(); @@ -60,7 +61,6 @@ function MetricsTreemap({ if ( !data || !data.data || - data?.status === 'error' || (data?.status === 'success' && !data?.data?.[viewType]) ) { return ( @@ -71,6 +71,15 @@ function MetricsTreemap({ ); } + if (data?.status === 'error' || isError) { + return ( + + ); + } + return (
diff --git a/frontend/src/container/MetricsExplorer/Summary/Summary.tsx b/frontend/src/container/MetricsExplorer/Summary/Summary.tsx index 3fd8c23e16..30a8fdc1d8 100644 --- a/frontend/src/container/MetricsExplorer/Summary/Summary.tsx +++ b/frontend/src/container/MetricsExplorer/Summary/Summary.tsx @@ -87,6 +87,7 @@ function Summary(): JSX.Element { data: metricsData, isLoading: isMetricsLoading, isFetching: isMetricsFetching, + isError: isMetricsError, } = useGetMetricsList(metricsListQuery, { enabled: !!metricsListQuery, }); @@ -95,6 +96,7 @@ function Summary(): JSX.Element { data: treeMapData, isLoading: isTreeMapLoading, isFetching: isTreeMapFetching, + isError: isTreeMapError, } = useGetMetricsTreeMap(metricsTreemapQuery, { enabled: !!metricsTreemapQuery, }); @@ -160,11 +162,13 @@ function Summary(): JSX.Element { void; } diff --git a/frontend/src/container/SideNav/menuItems.tsx b/frontend/src/container/SideNav/menuItems.tsx index 3d05075093..47800d9d3b 100644 --- a/frontend/src/container/SideNav/menuItems.tsx +++ b/frontend/src/container/SideNav/menuItems.tsx @@ -8,6 +8,7 @@ import { Cloudy, DraftingCompass, FileKey2, + HardDrive, Home, Layers2, LayoutGrid, @@ -88,7 +89,7 @@ const menuItems: SidebarItem[] = [ { key: ROUTES.APPLICATION, label: 'Services', - icon: , + icon: , }, { key: ROUTES.TRACES_EXPLORER, diff --git a/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx b/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx index 68871d80b4..4a351b4419 100644 --- a/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx +++ b/frontend/src/container/TimeSeriesView/TimeSeriesView.tsx @@ -6,6 +6,7 @@ import { QueryParams } from 'constants/query'; import EmptyLogsSearch from 'container/EmptyLogsSearch/EmptyLogsSearch'; import LogsError from 'container/LogsError/LogsError'; import { LogsLoading } from 'container/LogsLoading/LogsLoading'; +import EmptyMetricsSearch from 'container/MetricsExplorer/Explorer/EmptyMetricsSearch'; import { MetricsLoading } from 'container/MetricsExplorer/MetricsLoading/MetricsLoading'; import NoLogs from 'container/NoLogs/NoLogs'; import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config'; @@ -187,7 +188,15 @@ function TimeSeriesView({ chartData[0]?.length === 0 && !isLoading && !isError && - !isFilterApplied && } + !isFilterApplied && + dataSource !== DataSource.METRICS && } + + {chartData && + chartData[0] && + chartData[0]?.length === 0 && + !isLoading && + !isError && + dataSource === DataSource.METRICS && } {!isLoading && !isError && diff --git a/frontend/src/hooks/metricsExplorer/useGetMetricsListFilterKeys.ts b/frontend/src/hooks/metricsExplorer/useGetMetricsListFilterKeys.ts index 62c124791a..5347645ce6 100644 --- a/frontend/src/hooks/metricsExplorer/useGetMetricsListFilterKeys.ts +++ b/frontend/src/hooks/metricsExplorer/useGetMetricsListFilterKeys.ts @@ -1,5 +1,6 @@ import { getMetricsListFilterKeys, + GetMetricsListFilterKeysParams, MetricsListFilterKeysResponse, } from 'api/metricsExplorer/getMetricsListFilterKeys'; import { REACT_QUERY_KEY } from 'constants/reactQueryKeys'; @@ -8,6 +9,7 @@ import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query'; import { ErrorResponse, SuccessResponse } from 'types/api'; type UseGetMetricsListFilterKeys = ( + params: GetMetricsListFilterKeysParams, options?: UseQueryOptions< SuccessResponse | ErrorResponse, Error @@ -19,6 +21,7 @@ type UseGetMetricsListFilterKeys = ( >; export const useGetMetricsListFilterKeys: UseGetMetricsListFilterKeys = ( + params, options, headers, ) => { @@ -38,7 +41,7 @@ export const useGetMetricsListFilterKeys: UseGetMetricsListFilterKeys = ( SuccessResponse | ErrorResponse, Error >({ - queryFn: ({ signal }) => getMetricsListFilterKeys(signal, headers), + queryFn: ({ signal }) => getMetricsListFilterKeys(params, signal, headers), ...options, queryKey, }); diff --git a/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts b/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts index 1953b67b62..b566f4330a 100644 --- a/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts +++ b/frontend/src/hooks/queryBuilder/useFetchKeysAndValues.ts @@ -129,7 +129,7 @@ export const useFetchKeysAndValues = ( }, { queryKey: [searchParams], - enabled: isQueryEnabled && !shouldUseSuggestions, + enabled: isMetricsExplorer ? false : isQueryEnabled && !shouldUseSuggestions, }, isInfraMonitoring, // isInfraMonitoring entity, // infraMonitoringEntity @@ -155,9 +155,15 @@ export const useFetchKeysAndValues = ( data: metricsListFilterKeysData, isFetching: isFetchingMetricsListFilterKeys, status: fetchingMetricsListFilterKeysStatus, - } = useGetMetricsListFilterKeys({ - enabled: isMetricsExplorer && isQueryEnabled && !shouldUseSuggestions, - }); + } = useGetMetricsListFilterKeys( + { + searchText: searchKey, + }, + { + enabled: isMetricsExplorer && isQueryEnabled && !shouldUseSuggestions, + queryKey: [searchKey], + }, + ); function isAttributeValuesResponse( payload: any,