Browse Source

feat(starfish) Fetch span summary information from indexed spans (#50492)

The span operation and description on the span summary page can be
fetched from production data now! The way it works is that given a span
group, it fetches exactly 1 row from the indexed spans table with that
span group. It is _technically possible_ for more than one span
description to correspond to a single span group, but I don't think it's
critical to cover that case for now.

I had to introduce a new `IndexedSpan` type, since right now the field
names are different from span metrics. Hopefully we'll have time to make
them match. Otherwise, this is mostly all the same code, just with
slightly different fields.
George Gritsouk 1 year ago
parent
commit
7e7ad632bf

+ 5 - 5
static/app/views/starfish/components/spanDescription.tsx

@@ -1,22 +1,22 @@
 import styled from '@emotion/styled';
 
 import {FormattedCode} from 'sentry/views/starfish/components/formattedCode';
-import type {Span} from 'sentry/views/starfish/queries/types';
+import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
 import {highlightSql} from 'sentry/views/starfish/utils/highlightSql';
 
-export function SpanDescription({span}: {span: Span}) {
-  if (span.span_operation.startsWith('db')) {
+export function SpanDescription({span}: {span: IndexedSpan}) {
+  if (span.op.startsWith('db')) {
     return <DatabaseSpanDescription span={span} />;
   }
 
   return <div>{span.description}</div>;
 }
 
-function DatabaseSpanDescription({span}: {span: Span}) {
+function DatabaseSpanDescription({span}: {span: IndexedSpan}) {
   return (
     <CodeWrapper>
       <FormattedCode>
-        {highlightSql(span.formatted_desc || span.description || '', {
+        {highlightSql(span.description || '', {
           action: span.action || '',
           domain: span.domain || '',
         })}

+ 10 - 0
static/app/views/starfish/queries/types.tsx

@@ -7,3 +7,13 @@ export type Span = {
   formatted_desc?: string;
   span_id?: string;
 };
+
+export type IndexedSpan = {
+  action: string;
+  description: string;
+  domain: string;
+  group: string;
+  module: string;
+  op: string;
+  span_id: string;
+};

+ 63 - 0
static/app/views/starfish/queries/useIndexedSpan.ts

@@ -0,0 +1,63 @@
+import {Location} from 'history';
+
+import EventView from 'sentry/utils/discover/eventView';
+import {DiscoverDatasets} from 'sentry/utils/discover/types';
+import {useLocation} from 'sentry/utils/useLocation';
+import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
+import {useSpansQuery} from 'sentry/views/starfish/utils/useSpansQuery';
+
+export const useIndexedSpan = (
+  groupId: string,
+  _referrer: string = 'use-indexed-span'
+) => {
+  const location = useLocation();
+
+  const query = getQuery(groupId);
+  const eventView = getEventView(groupId, location);
+
+  // TODO: Add referrer
+  const {isLoading, data} = useSpansQuery<IndexedSpan[]>({
+    eventView,
+    limit: 1,
+    queryString: query,
+    initialData: [],
+    enabled: Boolean(query),
+  });
+
+  return {
+    isLoading,
+    data: data[0],
+  };
+};
+
+function getQuery(groupId: string) {
+  return `
+    SELECT
+    span_id as "id",
+    group_id as "group",
+    action,
+    description,
+    span_operation as "op",
+    domain,
+    module
+    FROM spans_experimental_starfish
+    WHERE group_id = '${groupId}'
+    LIMIT 1
+  `;
+}
+
+function getEventView(groupId: string, location: Location) {
+  const cleanGroupID = groupId.replaceAll('-', '').slice(-16);
+
+  return EventView.fromNewQueryWithLocation(
+    {
+      name: '',
+      query: `group:${cleanGroupID}`,
+      fields: ['group', 'action', 'description', 'domain', 'module', 'op'],
+      dataset: DiscoverDatasets.SPANS_INDEXED,
+      projects: [1],
+      version: 2,
+    },
+    location
+  );
+}

+ 0 - 29
static/app/views/starfish/queries/useSpanById.ts

@@ -1,29 +0,0 @@
-import {useQuery} from 'sentry/utils/queryClient';
-import type {Span} from 'sentry/views/starfish/queries/types';
-import {HOST} from 'sentry/views/starfish/utils/constants';
-
-export const useSpanById = (groupId: string, referrer: string) => {
-  const query = `
-  SELECT
-    group_id,
-    action,
-    description,
-    span_operation
-    FROM spans_experimental_starfish
-    WHERE group_id = '${groupId}'
-    LIMIT 1
-  `;
-
-  const result = useQuery<Span[]>({
-    queryKey: ['span-by-id', groupId],
-    queryFn: () =>
-      fetch(`${HOST}/?query=${query}&referrer=${referrer}&format=sql`).then(res =>
-        res.json()
-      ),
-    retry: false,
-    initialData: [],
-    enabled: Boolean(groupId),
-  });
-
-  return {...result, data: result.data[0]};
-};

+ 7 - 4
static/app/views/starfish/queries/useSpanMetricSeries.tsx

@@ -4,7 +4,7 @@ import moment from 'moment';
 import {Series} from 'sentry/types/echarts';
 import {useQuery} from 'sentry/utils/queryClient';
 import usePageFilters from 'sentry/utils/usePageFilters';
-import type {Span} from 'sentry/views/starfish/queries/types';
+import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
 import {HOST} from 'sentry/views/starfish/utils/constants';
 import {getDateFilters} from 'sentry/views/starfish/utils/dates';
 import {getDateQueryFilter} from 'sentry/views/starfish/utils/getDateQueryFilter';
@@ -19,7 +19,10 @@ export type Metric = {
   p95: number;
 };
 
-export const useSpanMetricSeries = (span?: Span, referrer = 'span-metrics-series') => {
+export const useSpanMetricSeries = (
+  span?: IndexedSpan,
+  referrer = 'span-metrics-series'
+) => {
   const pageFilters = usePageFilters();
   const {startTime, endTime} = getDateFilters(pageFilters);
   const dateFilters = getDateQueryFilter(startTime, endTime);
@@ -35,7 +38,7 @@ export const useSpanMetricSeries = (span?: Span, referrer = 'span-metrics-series
     countIf(greaterOrEquals(status, 400) AND lessOrEquals(status, 599)) as "failure_count",
     "failure_count" / "count" as "failure_rate"
   FROM spans_experimental_starfish
-  WHERE group_id = '${span.group_id}'
+  WHERE group_id = '${span.group}'
   ${dateFilters}
   GROUP BY interval
   ORDER BY interval
@@ -43,7 +46,7 @@ export const useSpanMetricSeries = (span?: Span, referrer = 'span-metrics-series
     : '';
 
   const {isLoading, error, data} = useQuery<Metric[]>({
-    queryKey: ['span-metrics-series', span?.group_id],
+    queryKey: ['span-metrics-series', span?.group],
     queryFn: () =>
       fetch(`${HOST}/?query=${query}&referrer=${referrer}`).then(res => res.json()),
     retry: false,

+ 4 - 4
static/app/views/starfish/queries/useSpanMetrics.tsx

@@ -2,7 +2,7 @@ import moment from 'moment';
 
 import {useQuery} from 'sentry/utils/queryClient';
 import usePageFilters from 'sentry/utils/usePageFilters';
-import type {Span} from 'sentry/views/starfish/queries/types';
+import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
 import {HOST} from 'sentry/views/starfish/utils/constants';
 import {getDateFilters} from 'sentry/views/starfish/utils/dates';
 import {getDateQueryFilter} from 'sentry/views/starfish/utils/getDateQueryFilter';
@@ -18,7 +18,7 @@ export type SpanMetrics = {
 };
 
 export const useSpanMetrics = (
-  span?: Pick<Span, 'group_id'>,
+  span?: Pick<IndexedSpan, 'group'>,
   queryFilters: {transactionName?: string} = {},
   referrer = 'span-metrics'
 ) => {
@@ -43,13 +43,13 @@ export const useSpanMetrics = (
     moment(endTime ?? undefined).unix() - moment(startTime).unix()
   }) as spans_per_second
   FROM spans_experimental_starfish
-  WHERE group_id = '${span.group_id}'
+  WHERE group_id = '${span.group}'
   ${dateFilters}
   ${filters.join(' AND ')}`
     : '';
 
   const {isLoading, error, data} = useQuery<SpanMetrics[]>({
-    queryKey: ['span-metrics', span?.group_id, dateFilters],
+    queryKey: ['span-metrics', span?.group, dateFilters],
     queryFn: () =>
       fetch(`${HOST}/?query=${query}&referrer=${referrer}`).then(res => res.json()),
     retry: false,

+ 4 - 4
static/app/views/starfish/queries/useSpanTransactionMetricSeries.tsx

@@ -5,7 +5,7 @@ import moment from 'moment';
 import {Series} from 'sentry/types/echarts';
 import {useQuery} from 'sentry/utils/queryClient';
 import usePageFilters from 'sentry/utils/usePageFilters';
-import type {Span} from 'sentry/views/starfish/queries/types';
+import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
 import {HOST} from 'sentry/views/starfish/utils/constants';
 import {getDateFilters} from 'sentry/views/starfish/utils/dates';
 import {getDateQueryFilter} from 'sentry/views/starfish/utils/getDateQueryFilter';
@@ -21,7 +21,7 @@ type Metric = {
 };
 
 export const useSpanTransactionMetricSeries = (
-  span?: Span,
+  span?: IndexedSpan,
   transactions?: string[],
   referrer: string = 'span-transaction-metrics-series'
 ) => {
@@ -39,7 +39,7 @@ export const useSpanTransactionMetricSeries = (
    FROM spans_experimental_starfish
    WHERE
      transaction IN ('${transactions.join("','")}')
-     AND group_id = '${span.group_id}'
+     AND group_id = '${span.group}'
      ${dateFilters}
    GROUP BY transaction, interval
    ORDER BY transaction, interval
@@ -47,7 +47,7 @@ export const useSpanTransactionMetricSeries = (
       : '';
 
   const {isLoading, error, data} = useQuery<Metric[]>({
-    queryKey: ['span-metrics-series', span?.group_id, transactions?.join(',') || ''],
+    queryKey: ['span-metrics-series', span?.group, transactions?.join(',') || ''],
     queryFn: () =>
       fetch(`${HOST}/?query=${query}&referrer=${referrer}`).then(res => res.json()),
     retry: false,

+ 4 - 4
static/app/views/starfish/queries/useSpanTransactionMetrics.tsx

@@ -3,7 +3,7 @@ import moment from 'moment';
 
 import {useQuery} from 'sentry/utils/queryClient';
 import usePageFilters from 'sentry/utils/usePageFilters';
-import type {Span} from 'sentry/views/starfish/queries/types';
+import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
 import {HOST} from 'sentry/views/starfish/utils/constants';
 import {getDateFilters} from 'sentry/views/starfish/utils/dates';
 import {getDateQueryFilter} from 'sentry/views/starfish/utils/getDateQueryFilter';
@@ -18,7 +18,7 @@ export type SpanTransactionMetrics = {
 };
 
 export const useSpanTransactionMetrics = (
-  span?: Pick<Span, 'group_id'>,
+  span?: Pick<IndexedSpan, 'group'>,
   transactions?: string[],
   referrer = 'span-transaction-metrics'
 ) => {
@@ -39,7 +39,7 @@ export const useSpanTransactionMetrics = (
         moment(endTime ?? undefined).unix() - moment(startTime).unix()
       }) as spans_per_second
     FROM spans_experimental_starfish
-    WHERE group_id = '${span.group_id}'
+    WHERE group_id = '${span.group}'
     ${dateFilters}
     AND transaction IN ('${transactions.join("','")}')
     GROUP BY transaction
@@ -49,7 +49,7 @@ export const useSpanTransactionMetrics = (
   const {isLoading, error, data} = useQuery<SpanTransactionMetrics[]>({
     queryKey: [
       'span-transactions-metrics',
-      span?.group_id,
+      span?.group,
       transactions?.join(',') || '',
       dateFilters,
     ],

+ 7 - 4
static/app/views/starfish/queries/useSpanTransactions.tsx

@@ -1,6 +1,6 @@
 import {useQuery} from 'sentry/utils/queryClient';
 import usePageFilters from 'sentry/utils/usePageFilters';
-import type {Span} from 'sentry/views/starfish/queries/types';
+import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
 import {HOST} from 'sentry/views/starfish/utils/constants';
 import {getDateFilters} from 'sentry/views/starfish/utils/dates';
 import {getDateQueryFilter} from 'sentry/views/starfish/utils/getDateQueryFilter';
@@ -10,7 +10,10 @@ type Transaction = {
   transaction: string;
 };
 
-export const useSpanTransactions = (span?: Span, referrer = 'span-transactions') => {
+export const useSpanTransactions = (
+  span?: IndexedSpan,
+  referrer = 'span-transactions'
+) => {
   const pageFilters = usePageFilters();
   const {startTime, endTime} = getDateFilters(pageFilters);
   const dateFilters = getDateQueryFilter(startTime, endTime);
@@ -22,7 +25,7 @@ export const useSpanTransactions = (span?: Span, referrer = 'span-transactions')
     count() AS count
   FROM spans_experimental_starfish
   WHERE
-    group_id = '${span.group_id}'
+    group_id = '${span.group}'
     ${dateFilters}
   GROUP BY transaction
   ORDER BY -power(10, floor(log10(count()))), -quantile(0.75)(exclusive_time)
@@ -31,7 +34,7 @@ export const useSpanTransactions = (span?: Span, referrer = 'span-transactions')
     : '';
 
   const {isLoading, error, data} = useQuery<Transaction[]>({
-    queryKey: ['span-transactions', span?.group_id],
+    queryKey: ['span-transactions', span?.group],
     queryFn: () =>
       fetch(`${HOST}/?query=${query}&referrer=${referrer}`).then(res => res.json()),
     retry: false,

+ 6 - 1
static/app/views/starfish/utils/useSpansQuery.tsx

@@ -21,6 +21,7 @@ export function useSpansQuery<T = any[]>({
   eventView,
   queryString,
   initialData,
+  limit,
   forceUseDiscover,
   enabled,
 }: {
@@ -28,6 +29,7 @@ export function useSpansQuery<T = any[]>({
   eventView?: EventView;
   forceUseDiscover?: boolean;
   initialData?: any;
+  limit?: number;
   queryString?: string;
 }): UseSpansQueryReturnType<T> {
   const {options} = useStarfishOptions();
@@ -38,7 +40,7 @@ export function useSpansQuery<T = any[]>({
   });
   if (isDiscoverFunction(queryFunction) || isDiscoverTimeseriesFunction(queryFunction)) {
     if (eventView) {
-      return queryFunction({eventView, initialData, enabled});
+      return queryFunction({eventView, initialData, limit, enabled});
     }
     throw new Error(
       'eventView argument must be defined when Starfish useDiscover is true'
@@ -136,9 +138,11 @@ export function useWrappedDiscoverQuery({
   eventView,
   initialData,
   referrer,
+  limit,
 }: {
   eventView: EventView;
   initialData?: any;
+  limit?: number;
   referrer?: string;
 }) {
   const location = useLocation();
@@ -148,6 +152,7 @@ export function useWrappedDiscoverQuery({
     orgSlug: organization.slug,
     location,
     referrer,
+    limit,
   });
   return {isLoading, data: isLoading && initialData ? initialData : data?.data};
 }

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