Browse Source

feat(starfish): Span sample panel for screen loads (#57675)

Opens sample list when selecting a span from screen load module

[example](https://sentry-sdks.dev.getsentry.net:7999/starfish/pageload/spans/?primaryRelease=io.sentry.sample.iOS-Swift%408.13.0%2B1293&project=5428557&secondaryRelease=io.sentry.VisionOS-Swift%401.0%2B1&statsPeriod=7d&transaction=ErrorsViewController)
Shruthi 1 year ago
parent
commit
922e96a6e0

+ 37 - 10
static/app/views/starfish/views/screens/screenLoadSpans/index.tsx

@@ -15,30 +15,34 @@ import {
 } from 'sentry/utils/performance/contexts/pageError';
 import {useLocation} from 'sentry/utils/useLocation';
 import useOrganization from 'sentry/utils/useOrganization';
-import {getTransactionName} from 'sentry/views/performance/utils';
+import useRouter from 'sentry/utils/useRouter';
 import {ReleaseComparisonSelector} from 'sentry/views/starfish/components/releaseSelector';
 import {StarfishPageFiltersContainer} from 'sentry/views/starfish/components/starfishPageFiltersContainer';
 import {useRoutingContext} from 'sentry/views/starfish/utils/routingContext';
-import {
-  getPrimaryRelease,
-  getSecondaryRelease,
-} from 'sentry/views/starfish/views/mobileServiceView/utils';
 import {QueryParameterNames} from 'sentry/views/starfish/views/queryParameters';
 import {ScreensView, YAxis} from 'sentry/views/starfish/views/screens';
 import {ScreenLoadSpansTable} from 'sentry/views/starfish/views/screens/screenLoadSpans/table';
+import {SampleList} from 'sentry/views/starfish/views/spanSummaryPage/sampleList';
+
+type Query = {
+  primaryRelease: string;
+  project: string;
+  secondaryRelease: string;
+  spanGroup: string;
+  transaction: string;
+  [QueryParameterNames.SPANS_SORT]: string;
+};
 
 function ScreenLoadSpans() {
-  const location = useLocation();
+  const location = useLocation<Query>();
   const organization = useOrganization();
-  const transactionName = getTransactionName(location);
-  const primaryRelease = getPrimaryRelease(location);
-  const secondaryRelease = getSecondaryRelease(location);
   const routingContext = useRoutingContext();
+  const router = useRouter();
 
   const screenLoadModule: LocationDescriptor = {
     pathname: `${routingContext.baseURL}/pageload/`,
     query: {
-      ...omit(location.query, QueryParameterNames.SPANS_SORT),
+      ...omit(location.query, [QueryParameterNames.SPANS_SORT, 'transaction']),
     },
   };
 
@@ -54,6 +58,13 @@ function ScreenLoadSpans() {
     },
   ];
 
+  const {
+    spanGroup,
+    primaryRelease,
+    secondaryRelease,
+    transaction: transactionName,
+  } = location.query;
+
   return (
     <SentryDocumentTitle title={transactionName} orgSlug={organization.slug}>
       <Layout.Page>
@@ -85,6 +96,22 @@ function ScreenLoadSpans() {
                 primaryRelease={primaryRelease}
                 secondaryRelease={secondaryRelease}
               />
+              {spanGroup && (
+                <SampleList
+                  groupId={spanGroup}
+                  transactionName={transactionName}
+                  onClose={() => {
+                    router.replace({
+                      pathname: router.location.pathname,
+                      query: omit(
+                        router.location.query,
+                        'spanGroup',
+                        'transactionMethod'
+                      ),
+                    });
+                  }}
+                />
+              )}
             </Layout.Main>
           </Layout.Body>
         </PageErrorProvider>

+ 32 - 0
static/app/views/starfish/views/screens/screenLoadSpans/table.tsx

@@ -1,9 +1,12 @@
 import {Fragment} from 'react';
+import * as qs from 'query-string';
 
 import {getInterval} from 'sentry/components/charts/utils';
 import GridEditable, {GridColumnHeader} from 'sentry/components/gridEditable';
 import SortLink from 'sentry/components/gridEditable/sortLink';
+import Link from 'sentry/components/links/link';
 import Pagination from 'sentry/components/pagination';
+import Truncate from 'sentry/components/truncate';
 import {t} from 'sentry/locale';
 import {NewQuery} from 'sentry/types';
 import {TableDataRow} from 'sentry/utils/discover/discoverQuery';
@@ -15,10 +18,12 @@ import {MutableSearch} from 'sentry/utils/tokenizeSearch';
 import {useLocation} from 'sentry/utils/useLocation';
 import useOrganization from 'sentry/utils/useOrganization';
 import usePageFilters from 'sentry/utils/usePageFilters';
+import useRouter from 'sentry/utils/useRouter';
 import {TableColumn} from 'sentry/views/discover/table/types';
 import {SpanFunction, SpanMetricsField} from 'sentry/views/starfish/types';
 import {STARFISH_CHART_INTERVAL_FIDELITY} from 'sentry/views/starfish/utils/constants';
 import {appendReleaseFilters} from 'sentry/views/starfish/utils/releaseComparison';
+import {useRoutingContext} from 'sentry/views/starfish/utils/routingContext';
 import {QueryParameterNames} from 'sentry/views/starfish/views/queryParameters';
 import {useTableQuery} from 'sentry/views/starfish/views/screens/screensTable';
 import {DataTitles} from 'sentry/views/starfish/views/spans/types';
@@ -41,6 +46,8 @@ export function ScreenLoadSpansTable({
   const location = useLocation();
   const {selection} = usePageFilters();
   const organization = useOrganization();
+  const routingContext = useRoutingContext();
+  const router = useRouter();
 
   const searchQuery = new MutableSearch([
     'transaction.op:ui.load',
@@ -103,6 +110,31 @@ export function ScreenLoadSpansTable({
       return row[column.key];
     }
 
+    if (column.key === SPAN_DESCRIPTION) {
+      const label = row[SpanMetricsField.SPAN_DESCRIPTION];
+
+      const pathname = `${routingContext.baseURL}/pageload/spans`;
+      const query = {
+        ...location.query,
+        transaction,
+        spanGroup: row[SpanMetricsField.SPAN_GROUP],
+      };
+
+      return (
+        <Link
+          to={`${pathname}?${qs.stringify(query)}`}
+          onClick={() => {
+            router.replace({
+              pathname,
+              query,
+            });
+          }}
+        >
+          <Truncate value={label} maxLength={75} />
+        </Link>
+      );
+    }
+
     const renderer = getFieldRenderer(column.key, data?.meta.fields, false);
     const rendered = renderer(row, {
       location,

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

@@ -24,10 +24,16 @@ import SampleTable from 'sentry/views/starfish/views/spanSummaryPage/sampleList/
 type Props = {
   groupId: string;
   transactionName: string;
+  onClose?: () => void;
   transactionMethod?: string;
 };
 
-export function SampleList({groupId, transactionName, transactionMethod}: Props) {
+export function SampleList({
+  groupId,
+  transactionName,
+  transactionMethod,
+  onClose,
+}: Props) {
   const router = useRouter();
   const [highlightedSpanId, setHighlightedSpanId] = useState<string | undefined>(
     undefined
@@ -72,15 +78,19 @@ export function SampleList({groupId, transactionName, transactionMethod}: Props)
     transaction: transactionName,
   })}`;
 
+  function defaultOnClose() {
+    router.replace({
+      pathname: router.location.pathname,
+      query: omit(router.location.query, 'transaction', 'transactionMethod'),
+    });
+  }
+
   return (
     <PageErrorProvider>
       <DetailPanel
         detailKey={detailKey}
         onClose={() => {
-          router.replace({
-            pathname: router.location.pathname,
-            query: omit(router.location.query, 'transaction', 'transactionMethod'),
-          });
+          onClose ? onClose() : defaultOnClose();
         }}
         onOpen={onOpenDetailPanel}
       >