diff --git a/static/app/views/insights/common/queries/useSpanMetricsTopNSeries.spec.tsx b/static/app/views/insights/common/queries/useSpanMetricsTopNSeries.spec.tsx deleted file mode 100644 index 4f17fab9660c6a..00000000000000 --- a/static/app/views/insights/common/queries/useSpanMetricsTopNSeries.spec.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import type {ReactNode} from 'react'; -import {OrganizationFixture} from 'sentry-fixture/organization'; -import {PageFilterStateFixture} from 'sentry-fixture/pageFilters'; - -import {makeTestQueryClient} from 'sentry-test/queryClient'; -import {renderHook, waitFor} from 'sentry-test/reactTestingLibrary'; - -import {QueryClientProvider} from 'sentry/utils/queryClient'; -import {MutableSearch} from 'sentry/utils/tokenizeSearch'; -import {useLocation} from 'sentry/utils/useLocation'; -import usePageFilters from 'sentry/utils/usePageFilters'; -import {useSpanMetricsTopNSeries} from 'sentry/views/insights/common/queries/useSpanMetricsTopNSeries'; -import type {SpanMetricsProperty} from 'sentry/views/insights/types'; -import {OrganizationContext} from 'sentry/views/organizationContext'; - -jest.mock('sentry/utils/useLocation'); -jest.mock('sentry/utils/usePageFilters'); - -describe('useSpanMetricsTopNSeries', () => { - const organization = OrganizationFixture(); - - function Wrapper({children}: {children?: ReactNode}) { - return ( - - {children} - - ); - } - - jest.mocked(usePageFilters).mockReturnValue( - PageFilterStateFixture({ - selection: { - datetime: { - period: '10d', - start: null, - end: null, - utc: false, - }, - environments: [], - projects: [], - }, - }) - ); - - jest.mocked(useLocation).mockReturnValue({ - pathname: '', - search: '', - query: {}, - hash: '', - state: undefined, - action: 'PUSH', - key: '', - }); - - it('rolls multi-axis top-n responses up into multiple series', async () => { - const eventsRequest = MockApiClient.addMockResponse({ - url: `/organizations/${organization.slug}/events-stats/`, - method: 'GET', - body: { - '200': { - data: [ - [1699907700, [{count: 117}]], - [1699908000, [{count: 199}]], - ], - meta: { - fields: { - 'span.group': 'string', - 'count()': 'integer', - }, - units: { - 'span.group': null, - 'count()': null, - }, - }, - }, - '304': { - data: [ - [1699907700, [{count: 12}]], - [1699908000, [{count: 13}]], - ], - meta: { - fields: { - 'span.group': 'string', - 'count()': 'integer', - }, - units: { - 'span.group': null, - 'count()': null, - }, - }, - }, - }, - }); - - const {result} = renderHook( - ({filters, fields, topEvents, yAxis}) => - useSpanMetricsTopNSeries({ - search: MutableSearch.fromQueryObject(filters), - fields, - topEvents, - yAxis, - }), - { - wrapper: Wrapper, - initialProps: { - filters: { - 'span.group': '221aa7ebd216', - }, - fields: ['span.status_code' as const, 'count()' as const], - topEvents: 5, - yAxis: ['count()'] as SpanMetricsProperty[], - }, - } - ); - - expect(eventsRequest).toHaveBeenCalledWith( - '/organizations/org-slug/events-stats/', - expect.objectContaining({ - method: 'GET', - query: expect.objectContaining({ - query: `span.group:221aa7ebd216`, - dataset: 'spansMetrics', - statsPeriod: '10d', - referrer: 'span-metrics-top-n-series', - interval: '30m', - topEvents: '5', - field: ['span.status_code', 'count()'], - yAxis: 'count()', - }), - }) - ); - - await waitFor(() => expect(result.current.isPending).toBe(false)); - - expect(result.current.data).toEqual({ - '200': { - data: [ - {name: '2023-11-13T20:35:00+00:00', value: 117}, - {name: '2023-11-13T20:40:00+00:00', value: 199}, - ], - seriesName: '200', - meta: { - fields: { - 'span.group': 'string', - 'count()': 'integer', - }, - units: { - 'span.group': null, - 'count()': null, - }, - }, - }, - '304': { - data: [ - {name: '2023-11-13T20:35:00+00:00', value: 12}, - {name: '2023-11-13T20:40:00+00:00', value: 13}, - ], - seriesName: '304', - meta: { - fields: { - 'span.group': 'string', - 'count()': 'integer', - }, - units: { - 'span.group': null, - 'count()': null, - }, - }, - }, - }); - }); -}); diff --git a/static/app/views/insights/common/queries/useSpanMetricsTopNSeries.tsx b/static/app/views/insights/common/queries/useSpanMetricsTopNSeries.tsx deleted file mode 100644 index 356f525b5bd911..00000000000000 --- a/static/app/views/insights/common/queries/useSpanMetricsTopNSeries.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import type {MultiSeriesEventsStats} from 'sentry/types/organization'; -import {encodeSort, type EventsMetaType} from 'sentry/utils/discover/eventView'; -import type {Sort} from 'sentry/utils/discover/fields'; -import { - type DiscoverQueryProps, - useGenericDiscoverQuery, -} from 'sentry/utils/discover/genericDiscoverQuery'; -import type {MutableSearch} from 'sentry/utils/tokenizeSearch'; -import {useLocation} from 'sentry/utils/useLocation'; -import useOrganization from 'sentry/utils/useOrganization'; -import usePageFilters from 'sentry/utils/usePageFilters'; -import {getSeriesEventView} from 'sentry/views/insights/common/queries/getSeriesEventView'; -import { - getRetryDelay, - shouldRetryHandler, -} from 'sentry/views/insights/common/utils/retryHandlers'; -import type {SpanMetricsProperty} from 'sentry/views/insights/types'; - -import {convertDiscoverTimeseriesResponse} from './convertDiscoverTimeseriesResponse'; -import type {DiscoverSeries} from './useDiscoverSeries'; - -interface UseSpanMetricsSeriesOptions { - topEvents: number; - enabled?: boolean; - fields?: Fields; - referrer?: string; - search?: MutableSearch; - sorts?: Sort[]; - yAxis?: Fields; -} - -export const useSpanMetricsTopNSeries = ( - options: UseSpanMetricsSeriesOptions = {topEvents: DEFAULT_EVENT_COUNT} -) => { - const { - search = undefined, - fields = [], - enabled, - yAxis = [], - topEvents, - sorts = [], - referrer = 'span-metrics-top-n-series', - } = options; - - if (yAxis.length > 1) { - throw new Error( - 'Multi-axis top-N queries are not supported by this hook. Try using `useSpansQuery` directly.' - ); - } - - const location = useLocation(); - const organization = useOrganization(); - const pageFilters = usePageFilters(); - - const eventView = getSeriesEventView( - search, - fields, - pageFilters.selection, - yAxis, - topEvents - ); - - if (sorts.length > 0) { - eventView.sorts = sorts; - } - - const result = useGenericDiscoverQuery({ - route: 'events-stats', - eventView, - location, - orgSlug: organization.slug, - getRequestPayload: () => ({ - ...eventView.getEventsAPIPayload(location), - yAxis: eventView.yAxis, - topEvents: eventView.topEvents, - excludeOther: 0, - partial: 1, - orderby: eventView.sorts?.[0] ? encodeSort(eventView.sorts?.[0]) : undefined, - interval: eventView.interval, - }), - options: { - enabled: enabled && pageFilters.isReady, - refetchOnWindowFocus: false, - retry: shouldRetryHandler, - retryDelay: getRetryDelay, - }, - referrer, - }); - - const parsedData: Record = {}; - - const data = result.data ?? {}; - - Object.keys(data).forEach(seriesName => { - const dataSeries = data[seriesName]!; - - const convertedSeries: DiscoverSeries = { - seriesName, - data: convertDiscoverTimeseriesResponse(dataSeries.data), - meta: dataSeries?.meta as EventsMetaType, - }; - - parsedData[seriesName] = convertedSeries; - }); - - return {...result, data: parsedData}; -}; - -const DEFAULT_EVENT_COUNT = 5; diff --git a/static/app/views/insights/http/components/httpSamplesPanel.spec.tsx b/static/app/views/insights/http/components/httpSamplesPanel.spec.tsx index 06bdd21babeb57..bb54d331234ed9 100644 --- a/static/app/views/insights/http/components/httpSamplesPanel.spec.tsx +++ b/static/app/views/insights/http/components/httpSamplesPanel.spec.tsx @@ -242,7 +242,6 @@ describe('HTTPSamplesPanel', () => { expect.objectContaining({ method: 'GET', query: { - cursor: undefined, dataset: 'spansMetrics', environment: [], excludeOther: 0, @@ -256,8 +255,8 @@ describe('HTTPSamplesPanel', () => { 'span.module:http span.op:http.client !has:span.domain transaction:/api/0/users span.status_code:[300,301,302,303,304,305,307,308]', referrer: 'api.performance.http.samples-panel-response-code-chart', statsPeriod: '10d', - sort: '-count()', topEvents: '5', + transformAliasToInputFormat: '0', yAxis: 'count()', }, }) diff --git a/static/app/views/insights/http/components/httpSamplesPanel.tsx b/static/app/views/insights/http/components/httpSamplesPanel.tsx index 25c272088d5007..88d7c1c46c7ed0 100644 --- a/static/app/views/insights/http/components/httpSamplesPanel.tsx +++ b/static/app/views/insights/http/components/httpSamplesPanel.tsx @@ -40,7 +40,7 @@ import { useSpansIndexed, } from 'sentry/views/insights/common/queries/useDiscover'; import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries'; -import {useSpanMetricsTopNSeries} from 'sentry/views/insights/common/queries/useSpanMetricsTopNSeries'; +import {useTopNSpanMetricsSeries} from 'sentry/views/insights/common/queries/useTopNDiscoverSeries'; import { DataTitles, getDurationChartTitle, @@ -205,20 +205,20 @@ export function HTTPSamplesPanel() { isFetching: isResponseCodeDataLoading, data: responseCodeData, error: responseCodeError, - } = useSpanMetricsTopNSeries({ - search, - fields: ['span.status_code', 'count()'], - yAxis: ['count()'], - topEvents: 5, - sorts: [ - { + } = useTopNSpanMetricsSeries( + { + search, + fields: ['span.status_code', 'count()'], + yAxis: ['count()'], + topN: 5, + sort: { kind: 'desc', field: 'count()', }, - ], - enabled: isPanelOpen && query.panel === 'status', - referrer: Referrer.SAMPLES_PANEL_RESPONSE_CODE_CHART, - }); + enabled: isPanelOpen && query.panel === 'status', + }, + Referrer.SAMPLES_PANEL_RESPONSE_CODE_CHART + ); const durationAxisMax = computeAxisMax([durationData?.[`avg(span.self_time)`]]);