Browse Source

feat(perf): Add span searchbar to Spans tab (#71704)

Updates the Search bar in the Spans tab of Transaction Summary. This PR
leverages the new suggested tags provided by the Trace Explorer, so that
mainly relevant attributes are provided.

The suggested tag set for this page may need to be refined, as there are
many tags that cannot be used here as the table is using the metrics
dataset. For example, we cannot filter by `span.duration` because the
table is making use of aggregates.


![image](https://github.com/getsentry/sentry/assets/16740047/a111489b-b35f-49d8-984d-d3819d6e4363)
Ash 9 months ago
parent
commit
b54869d13c

+ 17 - 1
static/app/views/performance/transactionSummary/transactionSpans/content.tsx

@@ -11,6 +11,7 @@ import {EnvironmentPageFilter} from 'sentry/components/organizations/environment
 import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
 import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
 import Pagination from 'sentry/components/pagination';
+import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import type {Organization} from 'sentry/types/organization';
 import {defined} from 'sentry/utils';
@@ -18,11 +19,14 @@ import {trackAnalytics} from 'sentry/utils/analytics';
 import {browserHistory} from 'sentry/utils/browserHistory';
 import DiscoverQuery from 'sentry/utils/discover/discoverQuery';
 import type EventView from 'sentry/utils/discover/eventView';
+import {DiscoverDatasets} from 'sentry/utils/discover/types';
 import SuspectSpansQuery from 'sentry/utils/performance/suspectSpans/suspectSpansQuery';
 import {VisuallyCompleteWithData} from 'sentry/utils/performanceForSentry';
 import {decodeScalar} from 'sentry/utils/queryString';
+import useLocationQuery from 'sentry/utils/url/useLocationQuery';
 import useProjects from 'sentry/utils/useProjects';
 import SpanMetricsTable from 'sentry/views/performance/transactionSummary/transactionSpans/spanMetricsTable';
+import {useSpanFieldSupportedTags} from 'sentry/views/performance/utils/useSpanFieldSupportedTags';
 
 import type {SetStateAction} from '../types';
 
@@ -192,6 +196,12 @@ function SpansContentV2(props: Props) {
   const {projects} = useProjects();
   const project = projects.find(p => p.id === projectId);
 
+  const query = useLocationQuery({
+    fields: {
+      query: decodeScalar,
+    },
+  });
+
   function handleChange(key: string) {
     return function (value: string | undefined) {
       ANALYTICS_VALUES[key]?.(organization, value);
@@ -215,6 +225,8 @@ function SpansContentV2(props: Props) {
     };
   }
 
+  const supportedTags = useSpanFieldSupportedTags();
+
   return (
     <Layout.Main fullWidth>
       <FilterActions>
@@ -235,8 +247,12 @@ function SpansContentV2(props: Props) {
         <StyledSearchBar
           organization={organization}
           projectIds={eventView.project}
-          query={''}
+          query={query.query}
           fields={eventView.fields}
+          placeholder={t('Search for span attributes')}
+          supportedTags={supportedTags}
+          // This dataset is separate from the query itself which is on metrics; it's for obtaining autocomplete recommendations
+          dataset={DiscoverDatasets.SPANS_INDEXED}
           onSearch={handleChange('query')}
         />
       </FilterActions>

+ 19 - 8
static/app/views/performance/transactionSummary/transactionSpans/spanMetricsTable.tsx

@@ -7,13 +7,15 @@ import GridEditable, {COL_WIDTH_UNDEFINED} from 'sentry/components/gridEditable'
 import Link from 'sentry/components/links/link';
 import Pagination, {type CursorHandler} from 'sentry/components/pagination';
 import {t} from 'sentry/locale';
-import type {Organization, Project} from 'sentry/types';
+import type {Organization} from 'sentry/types/organization';
+import type {Project} from 'sentry/types/project';
 import {getFieldRenderer} from 'sentry/utils/discover/fieldRenderers';
 import type {ColumnType} from 'sentry/utils/discover/fields';
 import {Container as TableCellContainer} from 'sentry/utils/discover/styles';
 import {VisuallyCompleteWithData} from 'sentry/utils/performanceForSentry';
 import {decodeScalar} from 'sentry/utils/queryString';
 import {MutableSearch} from 'sentry/utils/tokenizeSearch';
+import useLocationQuery from 'sentry/utils/url/useLocationQuery';
 import {useLocation} from 'sentry/utils/useLocation';
 import useOrganization from 'sentry/utils/useOrganization';
 import {spanDetailsRouteWithQuery} from 'sentry/views/performance/transactionSummary/transactionSpans/spanDetails/utils';
@@ -90,28 +92,37 @@ type Props = {
 export default function SpanMetricsTable(props: Props) {
   const {project, transactionName} = props;
   const organization = useOrganization();
-
   const location = useLocation();
-  const spansCursor = decodeScalar(location.query?.[QueryParameterNames.SPANS_CURSOR]);
-  const spanOp = decodeScalar(location.query?.spanOp);
+  const sort = useSpansTabTableSort();
+
+  const query = useLocationQuery({
+    fields: {
+      query: decodeScalar,
+      spansCursor: decodeScalar,
+      spanOp: decodeScalar,
+    },
+  });
+
+  const {query: search, spansCursor, spanOp} = query;
 
   const filters: SpanMetricsQueryFilters = {
     transaction: transactionName,
     ['span.op']: spanOp,
   };
 
-  const handleCursor: CursorHandler = (cursor, pathname, query) => {
+  const handleCursor: CursorHandler = (cursor, pathname, q) => {
     browserHistory.push({
       pathname,
-      query: {...query, [QueryParameterNames.SPANS_CURSOR]: cursor},
+      query: {...q, [QueryParameterNames.SPANS_CURSOR]: cursor},
     });
   };
 
-  const sort = useSpansTabTableSort();
+  const mutableSearch = MutableSearch.fromQueryObject(filters);
+  mutableSearch.addStringMultiFilter(search);
 
   const {data, isLoading, pageLinks} = useSpanMetrics(
     {
-      search: MutableSearch.fromQueryObject(filters),
+      search: mutableSearch,
       fields: [
         SpanMetricsField.SPAN_OP,
         SpanMetricsField.SPAN_DESCRIPTION,