Browse Source

feat(starfish): Add transaction.method filters (#51165)

Filters all applicable span queries (metrics and indexed) in starfish by
transaction method when necessary.
Shruthi 1 year ago
parent
commit
7ef1718552

+ 23 - 3
static/app/views/starfish/queries/useSpanList.tsx

@@ -31,6 +31,7 @@ export type SpanMetrics = {
 export const useSpanList = (
   moduleName: ModuleName,
   transaction?: string,
+  method?: string,
   spanCategory?: string,
   sorts?: Sort[],
   limit?: number,
@@ -39,7 +40,14 @@ export const useSpanList = (
 ) => {
   const location = useLocation();
 
-  const eventView = getEventView(moduleName, location, transaction, spanCategory, sorts);
+  const eventView = getEventView(
+    moduleName,
+    location,
+    transaction,
+    method,
+    spanCategory,
+    sorts
+  );
 
   const {isLoading, data, meta, pageLinks} = useWrappedDiscoverQuery<SpanMetrics[]>({
     eventView,
@@ -56,10 +64,17 @@ function getEventView(
   moduleName: ModuleName,
   location: Location,
   transaction?: string,
+  method?: string,
   spanCategory?: string,
   sorts?: Sort[]
 ) {
-  const query = buildEventViewQuery(moduleName, location, transaction, spanCategory)
+  const query = buildEventViewQuery(
+    moduleName,
+    location,
+    transaction,
+    method,
+    spanCategory
+  )
     .filter(Boolean)
     .join(' ');
 
@@ -85,7 +100,7 @@ function getEventView(
       projects: [1],
       version: 2,
     },
-    omit(location, 'span.category')
+    omit(location, 'span.category', 'http.method')
   );
 
   if (sorts) {
@@ -99,6 +114,7 @@ function buildEventViewQuery(
   moduleName: ModuleName,
   location: Location,
   transaction?: string,
+  method?: string,
   spanCategory?: string
 ) {
   const {query} = location;
@@ -125,5 +141,9 @@ function buildEventViewQuery(
     result.push(`transaction:${transaction}`);
   }
 
+  if (method) {
+    result.push(`transaction.method:${method}`);
+  }
+
   return result;
 }

+ 17 - 4
static/app/views/starfish/queries/useSpanMeta.tsx

@@ -3,6 +3,7 @@ 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 {SpanSummaryQueryFilters} from 'sentry/views/starfish/queries/useSpanMetrics';
 import {useSpansQuery} from 'sentry/views/starfish/utils/useSpansQuery';
 
 export type SpanMeta = {
@@ -14,23 +15,35 @@ export type SpanMeta = {
 
 export const useSpanMeta = (
   group: string,
-  queryFilters: {transactionName?: string} = {},
+  queryFilters: SpanSummaryQueryFilters = {},
   referrer: string = 'span-metrics'
 ) => {
   const location = useLocation();
 
   return useSpansQuery<SpanMeta[]>({
-    eventView: getEventView(group, location, queryFilters.transactionName),
+    eventView: getEventView(group, location, queryFilters),
     initialData: [],
     referrer,
   });
 };
 
-function getEventView(groupId, location: Location, transaction?: string) {
+function getEventView(
+  groupId,
+  location: Location,
+  queryFilters?: SpanSummaryQueryFilters
+) {
   return EventView.fromNewQueryWithLocation(
     {
       name: '',
-      query: `span.group:${groupId}${transaction ? ` transaction:${transaction}` : ''}`,
+      query: `span.group:${groupId}${
+        queryFilters?.transactionName
+          ? ` transaction:${queryFilters?.transactionName}`
+          : ''
+      }${
+        queryFilters?.['transaction.method']
+          ? ` transaction.method:${queryFilters?.['transaction.method']}`
+          : ''
+      }`,
       fields: ['span.op', 'span.description', 'span.action', 'span.domain', 'count()'], // TODO: Failing to pass a field like `count()` causes an error
       dataset: DiscoverDatasets.SPANS_METRICS,
       projects: [1],

+ 15 - 12
static/app/views/starfish/queries/useSpanMetrics.tsx

@@ -14,22 +14,19 @@ export type SpanMetrics = {
   'time_spent_percentage()': number;
 };
 
+export type SpanSummaryQueryFilters = {
+  'transaction.method'?: string;
+  transactionName?: string;
+};
+
 export const useSpanMetrics = (
   span?: Pick<IndexedSpan, 'group'>,
-  queryFilters: {transactionName?: string} = {},
+  queryFilters: SpanSummaryQueryFilters = {},
   fields: string[] = [],
   referrer: string = 'span-metrics'
 ) => {
   const location = useLocation();
-
-  const filters: string[] = [];
-  if (queryFilters.transactionName) {
-    filters.push(`transaction = ${queryFilters.transactionName}`);
-  }
-
-  const eventView = span
-    ? getEventView(span, location, queryFilters.transactionName, fields)
-    : undefined;
+  const eventView = span ? getEventView(span, location, queryFilters, fields) : undefined;
 
   // TODO: Add referrer
   const {isLoading, data} = useSpansQuery<SpanMetrics[]>({
@@ -45,7 +42,7 @@ export const useSpanMetrics = (
 function getEventView(
   span: {group: string},
   location: Location,
-  transaction?: string,
+  queryFilters?: SpanSummaryQueryFilters,
   fields: string[] = []
 ) {
   const cleanGroupId = span.group.replaceAll('-', '').slice(-16);
@@ -54,7 +51,13 @@ function getEventView(
     {
       name: '',
       query: `span.group:${cleanGroupId}${
-        transaction ? ` transaction:${transaction}` : ''
+        queryFilters?.transactionName
+          ? ` transaction:${queryFilters?.transactionName}`
+          : ''
+      }${
+        queryFilters?.['transaction.method']
+          ? ` transaction.method:${queryFilters?.['transaction.method']}`
+          : ''
       }`,
       fields,
       dataset: DiscoverDatasets.SPANS_METRICS,

+ 11 - 10
static/app/views/starfish/queries/useSpanMetricsSeries.tsx

@@ -9,6 +9,7 @@ import {DiscoverDatasets} from 'sentry/utils/discover/types';
 import {useLocation} from 'sentry/utils/useLocation';
 import usePageFilters from 'sentry/utils/usePageFilters';
 import type {IndexedSpan} from 'sentry/views/starfish/queries/types';
+import {SpanSummaryQueryFilters} from 'sentry/views/starfish/queries/useSpanMetrics';
 import {useSpansQuery} from 'sentry/views/starfish/utils/useSpansQuery';
 
 export type SpanMetrics = {
@@ -21,7 +22,7 @@ export type SpanMetrics = {
 
 export const useSpanMetricsSeries = (
   span?: Pick<IndexedSpan, 'group'>,
-  queryFilters: {transactionName?: string} = {},
+  queryFilters: SpanSummaryQueryFilters = {},
   yAxis: string[] = [],
   referrer = 'span-metrics-series'
 ) => {
@@ -29,13 +30,7 @@ export const useSpanMetricsSeries = (
   const pageFilters = usePageFilters();
 
   const eventView = span
-    ? getEventView(
-        span,
-        location,
-        pageFilters.selection,
-        yAxis,
-        queryFilters.transactionName
-      )
+    ? getEventView(span, location, pageFilters.selection, yAxis, queryFilters)
     : undefined;
 
   // TODO: Add referrer
@@ -65,7 +60,7 @@ function getEventView(
   location: Location,
   pageFilters: PageFilters,
   yAxis: string[],
-  transaction?: string
+  queryFilters?: SpanSummaryQueryFilters
 ) {
   const cleanGroupId = span.group.replaceAll('-', '').slice(-16);
 
@@ -73,7 +68,13 @@ function getEventView(
     {
       name: '',
       query: `span.group:${cleanGroupId}${
-        transaction ? ` transaction:${transaction}` : ''
+        queryFilters?.transactionName
+          ? ` transaction:${queryFilters?.transactionName}`
+          : ''
+      }${
+        queryFilters?.['transaction.method']
+          ? ` transaction.method:${queryFilters?.['transaction.method']}`
+          : ''
       }`,
       fields: [],
       yAxis,

+ 4 - 2
static/app/views/starfish/queries/useSpanSamples.tsx

@@ -12,6 +12,7 @@ import {DATE_FORMAT} from 'sentry/views/starfish/utils/useSpansQuery';
 
 type Options = {
   groupId?: string;
+  transactionMethod?: string;
   transactionName?: string;
 };
 
@@ -28,12 +29,13 @@ export const useSpanSamples = (options: Options) => {
   const url = '/api/0/organizations/sentry/spans-samples/';
   const api = useApi();
   const pageFilter = usePageFilters();
-  const {groupId, transactionName} = options;
+  const {groupId, transactionName, transactionMethod} = options;
   const location = useLocation();
-  // TODO - add http method when available
+
   const query = new MutableSearch([
     `span.group:${groupId}`,
     `transaction:${transactionName}`,
+    `transaction.method:${transactionMethod}`,
   ]);
 
   const dateCondtions = getDateConditions(pageFilter.selection);

+ 2 - 0
static/app/views/starfish/queries/useSpanTransactionMetrics.tsx

@@ -19,6 +19,7 @@ export type SpanTransactionMetrics = {
   'sum(span.self_time)': number;
   'time_spent_percentage(local)': number;
   transaction: string;
+  transactionMethod: string;
 };
 
 export const useSpanTransactionMetrics = (
@@ -54,6 +55,7 @@ function getEventView(span: {group: string}, location: Location, transactions: s
       query: search.formatString(),
       fields: [
         'transaction',
+        'transaction.method',
         'sps()',
         'sps_percent_change()',
         `sum(${SPAN_SELF_TIME})`,

+ 10 - 1
static/app/views/starfish/queries/useTransactions.tsx

@@ -25,17 +25,26 @@ export function useTransactions(eventIDs: string[], referrer = 'use-transactions
     location
   );
 
+  const enabled = Boolean(eventIDs.length);
+
   const response = useDiscoverQuery({
     eventView,
     location,
     orgSlug: slug,
     referrer,
     options: {
-      enabled: Boolean(eventIDs.length),
+      enabled,
     },
   });
   const data = (response.data?.data ?? []) as unknown as Transaction[];
 
+  if (!enabled) {
+    return {
+      isLoading: false,
+      data: [],
+    };
+  }
+
   return {
     ...response,
     data,

+ 19 - 5
static/app/views/starfish/views/spanSummaryPage/index.tsx

@@ -43,10 +43,14 @@ type Props = {
 function SpanSummaryPage({params, location}: Props) {
   const organization = useOrganization();
   const {groupId} = params;
-  const {transaction, endpoint, method} = location.query;
+  const {transaction, transactionMethod, endpoint, endpointMethod} = location.query;
 
   const queryFilter = endpoint ? {transactionName: endpoint} : undefined;
 
+  if (endpointMethod && queryFilter) {
+    queryFilter['transaction.method'] = endpointMethod;
+  }
+
   const {data: spanMetas} = useSpanMeta(
     groupId,
     queryFilter,
@@ -106,7 +110,7 @@ function SpanSummaryPage({params, location}: Props) {
                         location
                       )}/?${qs.stringify({
                         endpoint,
-                        method,
+                        'http.method': endpointMethod,
                       })}`
                     ),
                   },
@@ -116,7 +120,9 @@ function SpanSummaryPage({params, location}: Props) {
                 ]}
               />
               <Layout.Title>
-                {method && endpoint ? `${method} ${endpoint}` : t('Span Summary')}
+                {endpointMethod && endpoint
+                  ? `${endpointMethod} ${endpoint}`
+                  : t('Span Summary')}
               </Layout.Title>
             </Layout.HeaderContent>
           </Layout.Header>
@@ -211,11 +217,19 @@ function SpanSummaryPage({params, location}: Props) {
               )}
 
               {span && (
-                <SpanTransactionsTable span={span} endpoint={endpoint} method={method} />
+                <SpanTransactionsTable
+                  span={span}
+                  endpoint={endpoint}
+                  endpointMethod={endpointMethod}
+                />
               )}
 
               {transaction && span?.group && (
-                <SampleList groupId={span.group} transactionName={transaction} />
+                <SampleList
+                  groupId={span.group}
+                  transactionName={transaction}
+                  transactionMethod={transactionMethod}
+                />
               )}
             </Layout.Main>
           </Layout.Body>

+ 4 - 2
static/app/views/starfish/views/spanSummaryPage/sampleList/durationChart/index.tsx

@@ -14,11 +14,12 @@ const {SPAN_SELF_TIME, SPAN_OP} = SpanMetricsFields;
 
 type Props = {
   groupId: string;
+  transactionMethod: string;
   transactionName: string;
   spanDescription?: string;
 };
 
-function DurationChart({groupId, transactionName}: Props) {
+function DurationChart({groupId, transactionName, transactionMethod}: Props) {
   const theme = useTheme();
 
   const getSampleSymbol = (duration: number, p95: number) => {
@@ -35,7 +36,7 @@ function DurationChart({groupId, transactionName}: Props) {
 
   const {isLoading, data: spanMetricsSeriesData} = useSpanMetricsSeries(
     {group: groupId},
-    {transactionName},
+    {transactionName, 'transaction.method': transactionMethod},
     [`p95(${SPAN_SELF_TIME})`],
     'sidebar-span-metrics'
   );
@@ -56,6 +57,7 @@ function DurationChart({groupId, transactionName}: Props) {
   } = useSpanSamples({
     groupId,
     transactionName,
+    transactionMethod,
   });
 
   const baselineP95Series: Series = {

+ 18 - 5
static/app/views/starfish/views/spanSummaryPage/sampleList/index.tsx

@@ -8,10 +8,11 @@ import SampleTable from 'sentry/views/starfish/views/spanSummaryPage/sampleList/
 
 type Props = {
   groupId: string;
+  transactionMethod: string;
   transactionName: string;
 };
 
-export function SampleList({groupId, transactionName}: Props) {
+export function SampleList({groupId, transactionName, transactionMethod}: Props) {
   const router = useRouter();
 
   return (
@@ -24,13 +25,25 @@ export function SampleList({groupId, transactionName}: Props) {
         });
       }}
     >
-      <h3>{transactionName}</h3>
+      <h3>{`${transactionMethod} ${transactionName}`}</h3>
 
-      <SampleInfo groupId={groupId} transactionName={transactionName} />
+      <SampleInfo
+        groupId={groupId}
+        transactionName={transactionName}
+        transactionMethod={transactionMethod}
+      />
 
-      <DurationChart groupId={groupId} transactionName={transactionName} />
+      <DurationChart
+        groupId={groupId}
+        transactionName={transactionName}
+        transactionMethod={transactionMethod}
+      />
 
-      <SampleTable groupId={groupId} transactionName={transactionName} />
+      <SampleTable
+        groupId={groupId}
+        transactionName={transactionName}
+        transactionMethod={transactionMethod}
+      />
     </DetailPanel>
   );
 }

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