Skip to content
Merged
2 changes: 1 addition & 1 deletion static/app/views/explore/hooks/useExploreTimeseries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ function useExploreTimeseriesImpl({
};
}

function shouldTriggerHighAccuracy(
export function shouldTriggerHighAccuracy(
data: ReturnType<typeof useSortedTimeSeries>['data'],
visualizes: readonly Visualize[],
isTopN: boolean
Expand Down
22 changes: 22 additions & 0 deletions static/app/views/explore/metrics/hooks/testUtils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type {ReactNode} from 'react';

import {defaultMetricQuery} from 'sentry/views/explore/metrics/metricQuery';
import {MetricsQueryParamsProvider} from 'sentry/views/explore/metrics/metricsQueryParams';
import {MultiMetricsQueryParamsProvider} from 'sentry/views/explore/metrics/multiMetricsQueryParams';

export function MockMetricQueryParamsContext({children}: {children: ReactNode}) {
const mockQueryParams = defaultMetricQuery();
return (
<MultiMetricsQueryParamsProvider>
<MetricsQueryParamsProvider
traceMetric={{name: 'mockMetric', type: 'counter'}}
queryParams={mockQueryParams.queryParams}
setQueryParams={() => {}}
setTraceMetric={() => {}}
removeMetric={() => {}}
>
{children}
</MetricsQueryParamsProvider>
</MultiMetricsQueryParamsProvider>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {PageFilterStateFixture} from 'sentry-fixture/pageFilters';

import {renderHookWithProviders, waitFor} from 'sentry-test/reactTestingLibrary';

import usePageFilters from 'sentry/utils/usePageFilters';
import {SAMPLING_MODE} from 'sentry/views/explore/hooks/useProgressiveQuery';
import {MockMetricQueryParamsContext} from 'sentry/views/explore/metrics/hooks/testUtils';
import {useMetricAggregatesTable} from 'sentry/views/explore/metrics/hooks/useMetricAggregatesTable';

jest.mock('sentry/utils/usePageFilters');

describe('useMetricAggregatesTable', () => {
beforeEach(() => {
jest.mocked(usePageFilters).mockReturnValue(PageFilterStateFixture());
jest.clearAllMocks();
});

it('triggers the high accuracy request when there is no data and a partial scan', async () => {
const mockNormalRequestUrl = MockApiClient.addMockResponse({
url: '/organizations/org-slug/events/',
body: {
data: [],
meta: {
dataScanned: 'partial',
fields: {},
},
},
method: 'GET',
match: [
function (_url: string, options: Record<string, any>) {
return options.query.sampling === SAMPLING_MODE.NORMAL;
},
],
});
const mockHighAccuracyRequest = MockApiClient.addMockResponse({
url: '/organizations/org-slug/events/',
match: [
function (_url: string, options: Record<string, any>) {
return options.query.sampling === SAMPLING_MODE.HIGH_ACCURACY;
},
],
method: 'GET',
});
renderHookWithProviders(
() =>
useMetricAggregatesTable({
metricName: 'test metric',
limit: 100,
enabled: true,
}),
{
additionalWrapper: MockMetricQueryParamsContext,
}
);

expect(mockNormalRequestUrl).toHaveBeenCalledTimes(1);
expect(mockNormalRequestUrl).toHaveBeenCalledWith(
'/organizations/org-slug/events/',
expect.objectContaining({
query: expect.objectContaining({
sampling: SAMPLING_MODE.NORMAL,
}),
})
);

await waitFor(() => {
expect(mockHighAccuracyRequest).toHaveBeenCalledTimes(1);
});
expect(mockHighAccuracyRequest).toHaveBeenCalledWith(
'/organizations/org-slug/events/',
expect.objectContaining({
query: expect.objectContaining({
sampling: SAMPLING_MODE.HIGH_ACCURACY,
}),
})
);
});
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import {useMemo} from 'react';
import {useCallback, useMemo} from 'react';

import type {NewQuery} from 'sentry/types/organization';
import {defined} from 'sentry/utils';
import EventView from 'sentry/utils/discover/eventView';
import {DiscoverDatasets} from 'sentry/utils/discover/types';
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
import usePageFilters from 'sentry/utils/usePageFilters';
import {formatSort} from 'sentry/views/explore/contexts/pageParamsContext/sortBys';
import {
useProgressiveQuery,
type RPCQueryExtras,
} from 'sentry/views/explore/hooks/useProgressiveQuery';
import {useMetricVisualize} from 'sentry/views/explore/metrics/metricsQueryParams';
import {
useQueryParamsAggregateSortBys,
Expand All @@ -18,6 +23,7 @@ interface UseMetricAggregatesTableOptions {
enabled: boolean;
limit: number;
metricName: string;
queryExtras?: RPCQueryExtras;
}

interface MetricAggregatesTableResult {
Expand All @@ -30,14 +36,30 @@ export function useMetricAggregatesTable({
enabled,
limit,
metricName,
queryExtras,
}: UseMetricAggregatesTableOptions) {
return useMetricAggregatesTableImp({enabled, limit, metricName});
const canTriggerHighAccuracy = useCallback(
(result: ReturnType<typeof useMetricAggregatesTableImp>['result']) => {
const canGoToHigherAccuracyTier = result.meta?.dataScanned === 'partial';
const hasData = defined(result.data) && result.data.length > 0;
return !hasData && canGoToHigherAccuracyTier;
},
[]
);
return useProgressiveQuery<typeof useMetricAggregatesTableImp>({
queryHookImplementation: useMetricAggregatesTableImp,
queryHookArgs: {enabled, limit, metricName, queryExtras},
queryOptions: {
canTriggerHighAccuracy,
},
});
}

function useMetricAggregatesTableImp({
enabled,
limit,
metricName,
queryExtras,
}: UseMetricAggregatesTableOptions): MetricAggregatesTableResult {
const {selection} = usePageFilters();
const visualize = useMetricVisualize();
Expand Down Expand Up @@ -92,6 +114,7 @@ function useMetricAggregatesTableImp({
limit,
referrer: 'api.explore.metric-aggregates-table',
trackResponseAnalytics: false,
queryExtras,
});

return useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {PageFilterStateFixture} from 'sentry-fixture/pageFilters';

import {renderHookWithProviders, waitFor} from 'sentry-test/reactTestingLibrary';

import usePageFilters from 'sentry/utils/usePageFilters';
import {SAMPLING_MODE} from 'sentry/views/explore/hooks/useProgressiveQuery';
import {MockMetricQueryParamsContext} from 'sentry/views/explore/metrics/hooks/testUtils';
import {useMetricSamplesTable} from 'sentry/views/explore/metrics/hooks/useMetricSamplesTable';

jest.mock('sentry/utils/usePageFilters');

describe('useMetricSamplesTable', () => {
beforeEach(() => {
jest.mocked(usePageFilters).mockReturnValue(PageFilterStateFixture());
jest.clearAllMocks();
});

it('triggers the high accuracy request when there is no data and a partial scan', async () => {
const mockNormalRequestUrl = MockApiClient.addMockResponse({
url: '/organizations/org-slug/events/',
body: {
data: [],
meta: {
dataScanned: 'partial',
fields: {},
},
},
method: 'GET',
match: [
function (_url: string, options: Record<string, any>) {
return options.query.sampling === SAMPLING_MODE.NORMAL;
},
],
});
const mockHighAccuracyRequest = MockApiClient.addMockResponse({
url: '/organizations/org-slug/events/',
match: [
function (_url: string, options: Record<string, any>) {
return options.query.sampling === SAMPLING_MODE.HIGH_ACCURACY;
},
],
method: 'GET',
});
renderHookWithProviders(
() =>
useMetricSamplesTable({
metricName: 'test metric',
fields: [],
limit: 100,
ingestionDelaySeconds: 0,
enabled: true,
}),
{
additionalWrapper: MockMetricQueryParamsContext,
}
);

expect(mockNormalRequestUrl).toHaveBeenCalledTimes(1);
expect(mockNormalRequestUrl).toHaveBeenCalledWith(
'/organizations/org-slug/events/',
expect.objectContaining({
query: expect.objectContaining({
sampling: SAMPLING_MODE.NORMAL,
}),
})
);

await waitFor(() => {
expect(mockHighAccuracyRequest).toHaveBeenCalledTimes(1);
});
expect(mockHighAccuracyRequest).toHaveBeenCalledWith(
'/organizations/org-slug/events/',
expect.objectContaining({
query: expect.objectContaining({
sampling: SAMPLING_MODE.HIGH_ACCURACY,
}),
})
);
});
});
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import {useMemo} from 'react';
import {useCallback, useMemo} from 'react';
import moment from 'moment-timezone';

import type {PageFilters} from 'sentry/types/core';
import type {NewQuery} from 'sentry/types/organization';
import {defined} from 'sentry/utils';
import EventView from 'sentry/utils/discover/eventView';
import {DiscoverDatasets} from 'sentry/utils/discover/types';
import {intervalToMilliseconds} from 'sentry/utils/duration/intervalToMilliseconds';
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
import usePageFilters from 'sentry/utils/usePageFilters';
import {formatSort} from 'sentry/views/explore/contexts/pageParamsContext/sortBys';
import type {RPCQueryExtras} from 'sentry/views/explore/hooks/useProgressiveQuery';
import {useProgressiveQuery} from 'sentry/views/explore/hooks/useProgressiveQuery';
import {
useQueryParamsSearch,
useQueryParamsSortBys,
Expand All @@ -27,6 +30,7 @@ interface UseMetricSamplesTableOptions {
limit: number;
metricName: string;
ingestionDelaySeconds?: number;
queryExtras?: RPCQueryExtras;
}

interface MetricSamplesTableResult {
Expand All @@ -41,22 +45,40 @@ export function useMetricSamplesTable({
metricName,
fields,
ingestionDelaySeconds,
queryExtras,
}: UseMetricSamplesTableOptions) {
return useMetricSamplesTableImp({
enabled,
limit,
metricName,
fields,
ingestionDelaySeconds,
const canTriggerHighAccuracy = useCallback(
(result: ReturnType<typeof useMetricSamplesTableImpl>['result']) => {
const canGoToHigherAccuracyTier = result.meta?.dataScanned === 'partial';
const hasData = defined(result.data) && result.data.length > 0;
return !hasData && canGoToHigherAccuracyTier;
},
[]
);

return useProgressiveQuery<typeof useMetricSamplesTableImpl>({
queryHookImplementation: useMetricSamplesTableImpl,
queryHookArgs: {
enabled,
limit,
metricName,
fields,
ingestionDelaySeconds,
queryExtras,
},
queryOptions: {
canTriggerHighAccuracy,
},
});
}

function useMetricSamplesTableImp({
function useMetricSamplesTableImpl({
enabled,
limit,
metricName,
fields,
ingestionDelaySeconds = INGESTION_DELAY,
queryExtras,
}: UseMetricSamplesTableOptions): MetricSamplesTableResult {
const {selection} = usePageFilters();
const searchQuery = useQueryParamsSearch();
Expand Down Expand Up @@ -118,6 +140,7 @@ function useMetricSamplesTableImp({
limit,
referrer: 'api.explore.metric-samples-table',
trackResponseAnalytics: false,
queryExtras,
});

return useMemo(() => {
Expand Down
Loading
Loading