Browse Source

fix(perf): Use separate query param for span search in spans tab (#72610)

Same fix as https://github.com/getsentry/sentry/pull/72563, but simpler.
Prevents the search query from the transaction overview from propagating
into the searchbar in the spans tab. This is done because the search
params for transactions will not work for spans.
Ash 9 months ago
parent
commit
41f2390c3b

+ 8 - 9
static/app/views/performance/transactionSummary/transactionSpans/content.tsx

@@ -23,7 +23,6 @@ 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';
@@ -196,11 +195,7 @@ function SpansContentV2(props: Props) {
   const {projects} = useProjects();
   const project = projects.find(p => p.id === projectId);
 
-  const query = useLocationQuery({
-    fields: {
-      query: decodeScalar,
-    },
-  });
+  const spansQuery = decodeScalar(location.query.spansQuery);
 
   function handleChange(key: string) {
     return function (value: string | undefined) {
@@ -247,17 +242,21 @@ function SpansContentV2(props: Props) {
         <StyledSearchBar
           organization={organization}
           projectIds={eventView.project}
-          query={query.query}
+          query={spansQuery}
           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')}
+          onSearch={handleChange('spansQuery')}
         />
       </FilterActions>
 
-      <SpanMetricsTable project={project} transactionName={transactionName} />
+      <SpanMetricsTable
+        project={project}
+        transactionName={transactionName}
+        query={spansQuery ?? ''}
+      />
     </Layout.Main>
   );
 }

+ 45 - 4
static/app/views/performance/transactionSummary/transactionSpans/index.spec.tsx

@@ -3,7 +3,13 @@ import {ProjectFixture} from 'sentry-fixture/project';
 
 import {initializeOrg} from 'sentry-test/initializeOrg';
 import {generateSuspectSpansResponse} from 'sentry-test/performance/initializePerformanceData';
-import {act, render, screen, within} from 'sentry-test/reactTestingLibrary';
+import {
+  act,
+  render,
+  screen,
+  waitForElementToBeRemoved,
+  within,
+} from 'sentry-test/reactTestingLibrary';
 
 import ProjectsStore from 'sentry/stores/projectsStore';
 import TransactionSpans from 'sentry/views/performance/transactionSummary/transactionSpans';
@@ -12,10 +18,13 @@ import {
   SpanSortPercentiles,
 } from 'sentry/views/performance/transactionSummary/transactionSpans/types';
 
-function initializeData({query} = {query: {}}) {
-  const features = ['performance-view'];
+function initializeData(options: {query: {}; additionalFeatures?: string[]}) {
+  const {query, additionalFeatures} = options;
+
+  const defaultFeatures = ['performance-view'];
+
   const organization = OrganizationFixture({
-    features,
+    features: [...defaultFeatures, ...(additionalFeatures ? additionalFeatures : [])],
     projects: [ProjectFixture()],
   });
   const initialData = initializeOrg({
@@ -67,6 +76,10 @@ describe('Performance > Transaction Spans', function () {
       url: '/organizations/org-slug/replay-count/',
       body: {},
     });
+    MockApiClient.addMockResponse({
+      url: '/organizations/org-slug/spans/fields/',
+      body: [],
+    });
   });
 
   afterEach(function () {
@@ -169,4 +182,32 @@ describe('Performance > Transaction Spans', function () {
       expect(await within(grid).findByText('Total Self Time')).toBeInTheDocument();
     });
   });
+
+  describe('Spans Tab V2', function () {
+    it('does not propagate transaction search query and properly tokenizes span query', async function () {
+      const initialData = initializeData({
+        query: {query: 'http.method:POST', spansQuery: 'span.op:db span.action:SELECT'},
+        additionalFeatures: [
+          'performance-view',
+          'performance-spans-new-ui',
+          'insights-initial-modules',
+        ],
+      });
+
+      render(<TransactionSpans location={initialData.router.location} />, {
+        router: initialData.router,
+        organization: initialData.organization,
+      });
+
+      await waitForElementToBeRemoved(() => screen.queryAllByTestId('loading-indicator'));
+
+      const searchTokens = await screen.findAllByTestId('filter-token');
+      expect(searchTokens).toHaveLength(2);
+      expect(searchTokens[0]).toHaveTextContent('span.op:db');
+      expect(searchTokens[1]).toHaveTextContent('span.action:SELECT');
+      expect(await screen.findByTestId('smart-search-bar')).not.toHaveTextContent(
+        'http.method:POST'
+      );
+    });
+  });
 });

+ 6 - 2
static/app/views/performance/transactionSummary/transactionSpans/spanMetricsTable.spec.tsx

@@ -34,7 +34,9 @@ describe('SuspectSpansTable', () => {
       },
     });
 
-    render(<SpanMetricsTable transactionName="Test Transaction" project={project} />);
+    render(
+      <SpanMetricsTable transactionName="Test Transaction" project={project} query={''} />
+    );
 
     await waitFor(() =>
       expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument()
@@ -84,7 +86,9 @@ describe('SuspectSpansTable', () => {
       },
     });
 
-    render(<SpanMetricsTable transactionName="Test Transaction" project={project} />);
+    render(
+      <SpanMetricsTable transactionName="Test Transaction" project={project} query={''} />
+    );
 
     await waitFor(() =>
       expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument()

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

@@ -86,24 +86,24 @@ const LIMIT = 12;
 
 type Props = {
   project: Project | undefined;
+  query: string;
   transactionName: string;
 };
 
 export default function SpanMetricsTable(props: Props) {
-  const {project, transactionName} = props;
+  const {project, transactionName, query: search} = props;
   const organization = useOrganization();
   const location = useLocation();
   const sort = useSpansTabTableSort();
 
   const query = useLocationQuery({
     fields: {
-      query: decodeScalar,
       spansCursor: decodeScalar,
       spanOp: decodeScalar,
     },
   });
 
-  const {query: search, spansCursor, spanOp} = query;
+  const {spansCursor, spanOp} = query;
 
   const filters: SpanMetricsQueryFilters = {
     transaction: transactionName,