mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 12:05:53 +08:00
fix: query builder in metrics explorer picking up wrong datasource (#7676)
* fix: query builder in metrics explorer picking up wrong datasource * chore: add UTs --------- Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
parent
a9c09f33cb
commit
e6f69aa74c
@ -12,6 +12,7 @@ import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2';
|
|||||||
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
|
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
|
||||||
import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils';
|
import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
|
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||||
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||||
@ -57,6 +58,8 @@ function Explorer(): JSX.Element {
|
|||||||
[currentQuery, updateAllQueriesOperators],
|
[currentQuery, updateAllQueriesOperators],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useShareBuilderUrl(exportDefaultQuery);
|
||||||
|
|
||||||
const handleExport = useCallback(
|
const handleExport = useCallback(
|
||||||
(dashboard: Dashboard | null): void => {
|
(dashboard: Dashboard | null): void => {
|
||||||
if (!dashboard) return;
|
if (!dashboard) return;
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import * as useOptionsMenuHooks from 'container/OptionsMenu';
|
||||||
|
import * as useUpdateDashboardHooks from 'hooks/dashboard/useUpdateDashboard';
|
||||||
|
import * as useQueryBuilderHooks from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import store from 'store';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
|
import Explorer from '../Explorer';
|
||||||
|
|
||||||
|
jest.mock('react-router-dom', () => ({
|
||||||
|
...jest.requireActual('react-router-dom'),
|
||||||
|
useLocation: (): { pathname: string } => ({
|
||||||
|
pathname: `${ROUTES.METRICS_EXPLORER_EXPLORER}`,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
jest.mock('hooks/useSafeNavigate', () => ({
|
||||||
|
useSafeNavigate: (): any => ({
|
||||||
|
safeNavigate: jest.fn(),
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
jest.mock('hooks/useNotifications', () => ({
|
||||||
|
useNotifications: (): any => ({
|
||||||
|
notifications: {
|
||||||
|
error: jest.fn(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
jest.mock('uplot', () => {
|
||||||
|
const paths = {
|
||||||
|
spline: jest.fn(),
|
||||||
|
bars: jest.fn(),
|
||||||
|
};
|
||||||
|
const uplotMock = jest.fn(() => ({
|
||||||
|
paths,
|
||||||
|
}));
|
||||||
|
return {
|
||||||
|
paths,
|
||||||
|
default: uplotMock,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('react-redux', () => ({
|
||||||
|
...jest.requireActual('react-redux'),
|
||||||
|
useSelector: (): any => ({
|
||||||
|
globalTime: {
|
||||||
|
selectedTime: {
|
||||||
|
startTime: 1713734400000,
|
||||||
|
endTime: 1713738000000,
|
||||||
|
},
|
||||||
|
maxTime: 1713738000000,
|
||||||
|
minTime: 1713734400000,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.spyOn(useUpdateDashboardHooks, 'useUpdateDashboard').mockReturnValue({
|
||||||
|
mutate: jest.fn(),
|
||||||
|
isLoading: false,
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
jest.spyOn(useOptionsMenuHooks, 'useOptionsMenu').mockReturnValue({
|
||||||
|
selectColumns: [],
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
const mockUpdateAllQueriesOperators = jest.fn();
|
||||||
|
const mockUseQueryBuilderData = {
|
||||||
|
handleRunQuery: jest.fn(),
|
||||||
|
stagedQuery: initialQueriesMap[DataSource.METRICS],
|
||||||
|
updateAllQueriesOperators: mockUpdateAllQueriesOperators,
|
||||||
|
currentQuery: initialQueriesMap[DataSource.METRICS],
|
||||||
|
resetQuery: jest.fn(),
|
||||||
|
redirectWithQueryBuilderData: jest.fn(),
|
||||||
|
};
|
||||||
|
jest.spyOn(useQueryBuilderHooks, 'useQueryBuilder').mockReturnValue({
|
||||||
|
mockUseQueryBuilderData,
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
describe('Explorer', () => {
|
||||||
|
it('should render Explorer query builder with metrics datasource selected', () => {
|
||||||
|
jest.spyOn(useQueryBuilderHooks, 'useQueryBuilder').mockReturnValue({
|
||||||
|
...mockUseQueryBuilderData,
|
||||||
|
// Initially have a different datasource
|
||||||
|
stagedQuery: initialQueriesMap[DataSource.TRACES],
|
||||||
|
} as any);
|
||||||
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<Provider store={store}>
|
||||||
|
<Explorer />
|
||||||
|
</Provider>
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
expect(mockUpdateAllQueriesOperators).toHaveBeenCalledWith(
|
||||||
|
initialQueriesMap[DataSource.METRICS],
|
||||||
|
PANEL_TYPES.TIME_SERIES,
|
||||||
|
DataSource.METRICS,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -1,16 +1,19 @@
|
|||||||
import './Summary.styles.scss';
|
import './Summary.styles.scss';
|
||||||
|
|
||||||
import * as Sentry from '@sentry/react';
|
import * as Sentry from '@sentry/react';
|
||||||
|
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { usePageSize } from 'container/InfraMonitoringK8s/utils';
|
import { usePageSize } from 'container/InfraMonitoringK8s/utils';
|
||||||
import { useGetMetricsList } from 'hooks/metricsExplorer/useGetMetricsList';
|
import { useGetMetricsList } from 'hooks/metricsExplorer/useGetMetricsList';
|
||||||
import { useGetMetricsTreeMap } from 'hooks/metricsExplorer/useGetMetricsTreeMap';
|
import { useGetMetricsTreeMap } from 'hooks/metricsExplorer/useGetMetricsTreeMap';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
|
||||||
|
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||||
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
import InspectModal from '../Inspect';
|
import InspectModal from '../Inspect';
|
||||||
@ -25,13 +28,15 @@ import {
|
|||||||
getMetricsListQuery,
|
getMetricsListQuery,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
|
const DEFAULT_ORDER_BY: OrderByPayload = {
|
||||||
|
columnName: 'samples',
|
||||||
|
order: 'desc',
|
||||||
|
};
|
||||||
|
|
||||||
function Summary(): JSX.Element {
|
function Summary(): JSX.Element {
|
||||||
const { pageSize, setPageSize } = usePageSize('metricsExplorer');
|
const { pageSize, setPageSize } = usePageSize('metricsExplorer');
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [orderBy, setOrderBy] = useState<OrderByPayload>({
|
const [orderBy, setOrderBy] = useState<OrderByPayload>(DEFAULT_ORDER_BY);
|
||||||
columnName: 'samples',
|
|
||||||
order: 'desc',
|
|
||||||
});
|
|
||||||
const [heatmapView, setHeatmapView] = useState<TreemapViewType>(
|
const [heatmapView, setHeatmapView] = useState<TreemapViewType>(
|
||||||
TreemapViewType.TIMESERIES,
|
TreemapViewType.TIMESERIES,
|
||||||
);
|
);
|
||||||
@ -45,7 +50,31 @@ function Summary(): JSX.Element {
|
|||||||
(state) => state.globalTime,
|
(state) => state.globalTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { currentQuery } = useQueryBuilder();
|
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(
|
const queryFilters = useMemo(
|
||||||
() =>
|
() =>
|
||||||
currentQuery?.builder?.queryData[0]?.filters || {
|
currentQuery?.builder?.queryData[0]?.filters || {
|
||||||
|
@ -2,12 +2,8 @@ import './MetricsExplorerPage.styles.scss';
|
|||||||
|
|
||||||
import RouteTab from 'components/RouteTab';
|
import RouteTab from 'components/RouteTab';
|
||||||
import { TabRoutes } from 'components/RouteTab/types';
|
import { TabRoutes } from 'components/RouteTab/types';
|
||||||
import { initialQueriesMap } from 'constants/queryBuilder';
|
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { useLayoutEffect, useMemo } from 'react';
|
|
||||||
import { useLocation } from 'react-use';
|
import { useLocation } from 'react-use';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
|
||||||
|
|
||||||
import { Explorer, Summary } from './constants';
|
import { Explorer, Summary } from './constants';
|
||||||
|
|
||||||
@ -16,14 +12,6 @@ function MetricsExplorerPage(): JSX.Element {
|
|||||||
|
|
||||||
const routes: TabRoutes[] = [Summary, Explorer];
|
const routes: TabRoutes[] = [Summary, Explorer];
|
||||||
|
|
||||||
const initialQuery = useMemo(() => initialQueriesMap[DataSource.METRICS], []);
|
|
||||||
const { resetQuery } = useQueryBuilder();
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
resetQuery(initialQuery);
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="metrics-explorer-page">
|
<div className="metrics-explorer-page">
|
||||||
<RouteTab routes={routes} activeKey={pathname} history={history} />
|
<RouteTab routes={routes} activeKey={pathname} history={history} />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user