Browse Source

ref(insights): create useSpansIndexed (#71538)

1. Create `useSpansIndexed` in `useDiscover.ts` (for type safety and
consistency)
2. Remove `useIndexedSpans` and replace with `useSpansIndexed`
3. Move tests for `useIndexedSpans.spec.ts` to `useDiscover.spec.ts`

I think we should rename `SpanIndexedField` -> `SpansIndexedField`,
`SpanIndexedResponse` -> `SpansIndexedResponse`, etc (to directly match
the datasets, but that can be another PR.
Dominik Buszowiecki 9 months ago
parent
commit
5820ecab4d

+ 11 - 9
static/app/components/events/interfaces/llm-monitoring/llmMonitoringSection.tsx

@@ -13,8 +13,8 @@ import {
 } from 'sentry/views/llmMonitoring/llmMonitoringCharts';
 import * as ModuleLayout from 'sentry/views/performance/moduleLayout';
 import {useModuleURL} from 'sentry/views/performance/utils/useModuleURL';
-import {useIndexedSpans} from 'sentry/views/starfish/queries/useIndexedSpans';
-import {type IndexedResponse, SpanIndexedField} from 'sentry/views/starfish/types';
+import {useSpansIndexed} from 'sentry/views/starfish/queries/useDiscover';
+import {SpanIndexedField, type SpanIndexedResponse} from 'sentry/views/starfish/types';
 
 interface Props {
   event: Event;
@@ -24,15 +24,17 @@ interface Props {
 export default function LLMMonitoringSection({event}: Props) {
   const traceId = event.contexts.trace?.trace_id;
   const spanId = event.contexts.trace?.span_id;
-  const {data, error, isLoading} = useIndexedSpans({
-    limit: 1,
-    fields: [SpanIndexedField.SPAN_AI_PIPELINE_GROUP],
-    referrer: 'api.ai-pipelines.view',
-    search: new MutableSearch(`trace:${traceId} id:"${spanId}"`),
-  });
+  const {data, error, isLoading} = useSpansIndexed(
+    {
+      limit: 1,
+      fields: [SpanIndexedField.SPAN_AI_PIPELINE_GROUP],
+      search: new MutableSearch(`trace:${traceId} id:"${spanId}"`),
+    },
+    'api.ai-pipelines.view'
+  );
   const moduleUrl = useModuleURL('ai');
   const aiPipelineGroup =
-    data && (data[0] as IndexedResponse)?.[SpanIndexedField.SPAN_AI_PIPELINE_GROUP];
+    data && (data[0] as SpanIndexedResponse)?.[SpanIndexedField.SPAN_AI_PIPELINE_GROUP];
 
   const actions = (
     <ButtonBar gap={1}>

+ 18 - 16
static/app/views/llmMonitoring/pipelineSpansTable.tsx

@@ -17,7 +17,7 @@ import {MutableSearch} from 'sentry/utils/tokenizeSearch';
 import {useLocation} from 'sentry/utils/useLocation';
 import useOrganization from 'sentry/utils/useOrganization';
 import {renderHeadCell} from 'sentry/views/starfish/components/tableCells/renderHeadCell';
-import {useIndexedSpans} from 'sentry/views/starfish/queries/useIndexedSpans';
+import {useSpansIndexed} from 'sentry/views/starfish/queries/useDiscover';
 import {SpanIndexedField} from 'sentry/views/starfish/types';
 import {QueryParameterNames} from 'sentry/views/starfish/views/queryParameters';
 
@@ -87,21 +87,23 @@ export function PipelineSpansTable({groupId}: Props) {
     meta: rawMeta,
     error,
     isLoading,
-  } = useIndexedSpans({
-    limit: 30,
-    sorts: [sort],
-    fields: [
-      SpanIndexedField.ID,
-      SpanIndexedField.TRACE,
-      SpanIndexedField.SPAN_DURATION,
-      SpanIndexedField.TRANSACTION_ID,
-      SpanIndexedField.USER,
-      SpanIndexedField.TIMESTAMP,
-      SpanIndexedField.PROJECT,
-    ],
-    referrer: 'api.ai-pipelines.view',
-    search: new MutableSearch(`span.category:ai.pipeline span.group:"${groupId}"`),
-  });
+  } = useSpansIndexed(
+    {
+      limit: 30,
+      sorts: [sort],
+      fields: [
+        SpanIndexedField.ID,
+        SpanIndexedField.TRACE,
+        SpanIndexedField.SPAN_DURATION,
+        SpanIndexedField.TRANSACTION_ID,
+        SpanIndexedField.USER,
+        SpanIndexedField.TIMESTAMP,
+        SpanIndexedField.PROJECT,
+      ],
+      search: new MutableSearch(`span.category:ai.pipeline span.group:"${groupId}"`),
+    },
+    'api.ai-pipelines.view'
+  );
   const data = rawData || [];
   const meta = rawMeta as EventsMetaType;
 

+ 33 - 31
static/app/views/performance/browser/webVitals/utils/queries/useInpSpanSamplesWebVitalsQuery.tsx

@@ -5,7 +5,7 @@ import {
   SORTABLE_INDEXED_INTERACTION_FIELDS,
 } from 'sentry/views/performance/browser/webVitals/utils/types';
 import {useWebVitalsSort} from 'sentry/views/performance/browser/webVitals/utils/useWebVitalsSort';
-import {useIndexedSpans} from 'sentry/views/starfish/queries/useIndexedSpans';
+import {useSpansIndexed} from 'sentry/views/starfish/queries/useDiscover';
 import {SpanIndexedField} from 'sentry/views/starfish/types';
 
 export function useInpSpanSamplesWebVitalsQuery({
@@ -27,36 +27,38 @@ export function useInpSpanSamplesWebVitalsQuery({
     defaultSort: DEFAULT_INDEXED_INTERACTION_SORT,
     sortableFields: filteredSortableFields as unknown as string[],
   });
-  const {data, isLoading, ...rest} = useIndexedSpans({
-    search: MutableSearch.fromQueryObject({
-      'span.op': 'ui.interaction.click',
-      'measurements.score.weight.inp': '>0',
-      ...(transaction !== undefined
-        ? {[SpanIndexedField.ORIGIN_TRANSACTION]: transaction}
-        : {}),
-      ...filters,
-    }),
-    sorts: [sort],
-    fields: [
-      SpanIndexedField.INP,
-      SpanIndexedField.INP_SCORE,
-      SpanIndexedField.INP_SCORE_WEIGHT,
-      SpanIndexedField.TOTAL_SCORE,
-      SpanIndexedField.ID,
-      SpanIndexedField.TIMESTAMP,
-      SpanIndexedField.PROFILE_ID,
-      SpanIndexedField.REPLAY_ID,
-      SpanIndexedField.USER,
-      SpanIndexedField.ORIGIN_TRANSACTION,
-      SpanIndexedField.PROJECT,
-      SpanIndexedField.BROWSER_NAME,
-      SpanIndexedField.SPAN_SELF_TIME,
-      SpanIndexedField.SPAN_DESCRIPTION,
-    ],
-    enabled,
-    limit,
-    referrer: 'api.performance.browser.web-vitals.spans',
-  });
+  const {data, isLoading, ...rest} = useSpansIndexed(
+    {
+      search: MutableSearch.fromQueryObject({
+        'span.op': 'ui.interaction.click',
+        'measurements.score.weight.inp': '>0',
+        ...(transaction !== undefined
+          ? {[SpanIndexedField.ORIGIN_TRANSACTION]: transaction}
+          : {}),
+        ...filters,
+      }),
+      sorts: [sort],
+      fields: [
+        SpanIndexedField.INP,
+        SpanIndexedField.INP_SCORE,
+        SpanIndexedField.INP_SCORE_WEIGHT,
+        SpanIndexedField.TOTAL_SCORE,
+        SpanIndexedField.ID,
+        SpanIndexedField.TIMESTAMP,
+        SpanIndexedField.PROFILE_ID,
+        SpanIndexedField.REPLAY_ID,
+        SpanIndexedField.USER,
+        SpanIndexedField.ORIGIN_TRANSACTION,
+        SpanIndexedField.PROJECT,
+        SpanIndexedField.BROWSER_NAME,
+        SpanIndexedField.SPAN_SELF_TIME,
+        SpanIndexedField.SPAN_DESCRIPTION,
+      ],
+      enabled,
+      limit,
+    },
+    'api.performance.browser.web-vitals.spans'
+  );
   const tableData: InteractionSpanSampleRowWithScore[] =
     !isLoading && data?.length
       ? data.map(row => {

+ 0 - 1
static/app/views/performance/browser/webVitals/utils/types.tsx

@@ -49,7 +49,6 @@ export type InteractionSpanSampleRow = {
   projectSlug: string;
   replayId: string;
   [SpanIndexedField.SPAN_DESCRIPTION]: string;
-  [SpanIndexedField.SPAN_OP]: string;
   [SpanIndexedField.SPAN_SELF_TIME]: number;
   [SpanIndexedField.TIMESTAMP]: string;
   'user.display': string;

+ 34 - 25
static/app/views/performance/cache/samplePanel/samplePanel.tsx

@@ -35,9 +35,12 @@ import * as ModuleLayout from 'sentry/views/performance/moduleLayout';
 import {useSpanFieldSupportedTags} from 'sentry/views/performance/utils/useSpanFieldSupportedTags';
 import DetailPanel from 'sentry/views/starfish/components/detailPanel';
 import {getTimeSpentExplanation} from 'sentry/views/starfish/components/tableCells/timeSpentCell';
-import {useMetrics, useSpanMetrics} from 'sentry/views/starfish/queries/useDiscover';
+import {
+  useMetrics,
+  useSpanMetrics,
+  useSpansIndexed,
+} from 'sentry/views/starfish/queries/useDiscover';
 import {useSpanMetricsSeries} from 'sentry/views/starfish/queries/useDiscoverSeries';
-import {useIndexedSpans} from 'sentry/views/starfish/queries/useIndexedSpans';
 import {useTransactions} from 'sentry/views/starfish/queries/useTransactions';
 import {
   MetricsFields,
@@ -46,6 +49,7 @@ import {
   SpanFunction,
   SpanIndexedField,
   type SpanIndexedQueryFilters,
+  type SpanIndexedResponse,
   SpanMetricsField,
   type SpanMetricsQueryFilters,
 } from 'sentry/views/starfish/types';
@@ -146,29 +150,34 @@ export function CacheSamplePanel() {
     project_id: query.project,
   };
 
-  const useIndexedCacheSpans = (isCacheHit, limit) =>
-    useIndexedSpans({
-      search: MutableSearch.fromQueryObject({
-        ...sampleFilters,
-        ...new MutableSearch(query.spanSearchQuery).filters,
-        'cache.hit': isCacheHit,
-      }),
-      fields: [
-        SpanIndexedField.PROJECT,
-        SpanIndexedField.TRACE,
-        SpanIndexedField.TRANSACTION_ID,
-        SpanIndexedField.ID,
-        SpanIndexedField.TIMESTAMP,
-        SpanIndexedField.SPAN_DESCRIPTION,
-        SpanIndexedField.CACHE_HIT,
-        SpanIndexedField.SPAN_OP,
-        SpanIndexedField.CACHE_ITEM_SIZE,
-      ],
-      sorts: [SPAN_SAMPLES_SORT],
-      limit: limit,
-      enabled: isPanelOpen,
-      referrer: Referrer.SAMPLES_CACHE_SPAN_SAMPLES,
-    });
+  const useIndexedCacheSpans = (
+    isCacheHit: SpanIndexedResponse['cache.hit'],
+    limit: number
+  ) =>
+    useSpansIndexed(
+      {
+        search: MutableSearch.fromQueryObject({
+          ...sampleFilters,
+          ...new MutableSearch(query.spanSearchQuery).filters,
+          'cache.hit': isCacheHit,
+        }),
+        fields: [
+          SpanIndexedField.PROJECT,
+          SpanIndexedField.TRACE,
+          SpanIndexedField.TRANSACTION_ID,
+          SpanIndexedField.ID,
+          SpanIndexedField.TIMESTAMP,
+          SpanIndexedField.SPAN_DESCRIPTION,
+          SpanIndexedField.CACHE_HIT,
+          SpanIndexedField.SPAN_OP,
+          SpanIndexedField.CACHE_ITEM_SIZE,
+        ],
+        sorts: [SPAN_SAMPLES_SORT],
+        limit,
+        enabled: isPanelOpen,
+      },
+      Referrer.SAMPLES_CACHE_SPAN_SAMPLES
+    );
 
   // display half hits and half misses by default
   let cacheHitSamplesLimit = SPAN_SAMPLE_LIMIT / 2;

+ 2 - 2
static/app/views/performance/cache/tables/cacheHitMissCell.tsx

@@ -1,7 +1,7 @@
 import {t} from 'sentry/locale';
-import type {IndexedResponse} from 'sentry/views/starfish/types';
+import type {SpanIndexedResponse} from 'sentry/views/starfish/types';
 
-export function CacheHitMissCell(props: {hit: IndexedResponse['cache.hit']}) {
+export function CacheHitMissCell(props: {hit: SpanIndexedResponse['cache.hit']}) {
   const {hit} = props;
   if (hit === 'true') {
     return <span>{t('HIT')}</span>;

+ 2 - 2
static/app/views/performance/cache/tables/spanSamplesTable.tsx

@@ -15,7 +15,7 @@ import useOrganization from 'sentry/utils/useOrganization';
 import {CacheHitMissCell} from 'sentry/views/performance/cache/tables/cacheHitMissCell';
 import {renderHeadCell} from 'sentry/views/starfish/components/tableCells/renderHeadCell';
 import {SpanIdCell} from 'sentry/views/starfish/components/tableCells/spanIdCell';
-import type {IndexedResponse} from 'sentry/views/starfish/types';
+import type {SpanIndexedResponse} from 'sentry/views/starfish/types';
 import {ModuleName, SpanIndexedField} from 'sentry/views/starfish/types';
 
 type DataRowKeys =
@@ -35,7 +35,7 @@ type ColumnKeys =
   | SpanIndexedField.CACHE_ITEM_SIZE
   | 'transaction.duration';
 
-export type DataRow = Pick<IndexedResponse, DataRowKeys> & {
+export type DataRow = Pick<SpanIndexedResponse, DataRowKeys> & {
   'transaction.duration': number;
 };
 

+ 2 - 9
static/app/views/performance/http/data/useSpanSamples.spec.tsx

@@ -9,7 +9,6 @@ import {MutableSearch} from 'sentry/utils/tokenizeSearch';
 import usePageFilters from 'sentry/utils/usePageFilters';
 import {OrganizationContext} from 'sentry/views/organizationContext';
 import {useSpanSamples} from 'sentry/views/performance/http/data/useSpanSamples';
-import type {IndexedProperty} from 'sentry/views/starfish/types';
 import {SpanIndexedField} from 'sentry/views/starfish/types';
 
 jest.mock('sentry/utils/usePageFilters');
@@ -60,10 +59,7 @@ describe('useSpanSamples', () => {
       {
         wrapper: Wrapper,
         initialProps: {
-          fields: [
-            SpanIndexedField.TRANSACTION_ID,
-            SpanIndexedField.ID,
-          ] as IndexedProperty[],
+          fields: [SpanIndexedField.TRANSACTION_ID, SpanIndexedField.ID],
           enabled: false,
         },
       }
@@ -104,10 +100,7 @@ describe('useSpanSamples', () => {
             release: '0.0.1',
             environment: undefined,
           },
-          fields: [
-            SpanIndexedField.TRANSACTION_ID,
-            SpanIndexedField.ID,
-          ] as IndexedProperty[],
+          fields: [SpanIndexedField.TRANSACTION_ID, SpanIndexedField.ID],
           referrer: 'api-spec',
         },
       }

+ 3 - 7
static/app/views/performance/http/data/useSpanSamples.tsx

@@ -5,11 +5,7 @@ import {useApiQuery} from 'sentry/utils/queryClient';
 import type {MutableSearch} from 'sentry/utils/tokenizeSearch';
 import useOrganization from 'sentry/utils/useOrganization';
 import usePageFilters from 'sentry/utils/usePageFilters';
-import type {
-  IndexedProperty,
-  IndexedResponse,
-  SpanIndexedField,
-} from 'sentry/views/starfish/types';
+import type {SpanIndexedField, SpanIndexedResponse} from 'sentry/views/starfish/types';
 import {getDateConditions} from 'sentry/views/starfish/utils/getDateConditions';
 
 interface UseSpanSamplesOptions<Fields> {
@@ -21,7 +17,7 @@ interface UseSpanSamplesOptions<Fields> {
   search?: MutableSearch;
 }
 
-export const useSpanSamples = <Fields extends IndexedProperty[]>(
+export const useSpanSamples = <Fields extends SpanIndexedField[]>(
   options: UseSpanSamplesOptions<Fields> = {}
 ) => {
   const {
@@ -50,7 +46,7 @@ export const useSpanSamples = <Fields extends IndexedProperty[]>(
   const result = useApiQuery<{
     data:
       | Pick<
-          IndexedResponse,
+          SpanIndexedResponse,
           | Fields[number]
           // These fields are returned by default
           | SpanIndexedField.PROJECT

+ 19 - 18
static/app/views/performance/http/httpSamplesPanel.tsx

@@ -45,9 +45,8 @@ import {useSpanFieldSupportedTags} from 'sentry/views/performance/utils/useSpanF
 import {computeAxisMax} from 'sentry/views/starfish/components/chart';
 import DetailPanel from 'sentry/views/starfish/components/detailPanel';
 import {getTimeSpentExplanation} from 'sentry/views/starfish/components/tableCells/timeSpentCell';
-import {useSpanMetrics} from 'sentry/views/starfish/queries/useDiscover';
+import {useSpanMetrics, useSpansIndexed} from 'sentry/views/starfish/queries/useDiscover';
 import {useSpanMetricsSeries} from 'sentry/views/starfish/queries/useDiscoverSeries';
-import {useIndexedSpans} from 'sentry/views/starfish/queries/useIndexedSpans';
 import {useSpanMetricsTopNSeries} from 'sentry/views/starfish/queries/useSpanMetricsTopNSeries';
 import {
   ModuleName,
@@ -250,22 +249,24 @@ export function HTTPSamplesPanel() {
     isFetching: isResponseCodeSamplesDataFetching,
     error: responseCodeSamplesDataError,
     refetch: refetchResponseCodeSpanSamples,
-  } = useIndexedSpans({
-    search: sampleSpansSearch,
-    fields: [
-      SpanIndexedField.PROJECT,
-      SpanIndexedField.TRACE,
-      SpanIndexedField.TRANSACTION_ID,
-      SpanIndexedField.ID,
-      SpanIndexedField.TIMESTAMP,
-      SpanIndexedField.SPAN_DESCRIPTION,
-      SpanIndexedField.RESPONSE_CODE,
-    ],
-    sorts: [SPAN_SAMPLES_SORT],
-    limit: SPAN_SAMPLE_LIMIT,
-    enabled: isPanelOpen && query.panel === 'status',
-    referrer: Referrer.SAMPLES_PANEL_RESPONSE_CODE_SAMPLES,
-  });
+  } = useSpansIndexed(
+    {
+      search: sampleSpansSearch,
+      fields: [
+        SpanIndexedField.PROJECT,
+        SpanIndexedField.TRACE,
+        SpanIndexedField.TRANSACTION_ID,
+        SpanIndexedField.ID,
+        SpanIndexedField.TIMESTAMP,
+        SpanIndexedField.SPAN_DESCRIPTION,
+        SpanIndexedField.RESPONSE_CODE,
+      ],
+      sorts: [SPAN_SAMPLES_SORT],
+      limit: SPAN_SAMPLE_LIMIT,
+      enabled: isPanelOpen && query.panel === 'status',
+    },
+    Referrer.SAMPLES_PANEL_RESPONSE_CODE_SAMPLES
+  );
 
   const sampledSpanDataSeries = useSampleScatterPlotSeries(
     durationSamplesData,

Some files were not shown because too many files changed in this diff