Browse Source

fix(perf-issues): Make resources section mobile responsive + contextual links (#39430)

Ash Anand 2 years ago
parent
commit
8f4aa15bf0

+ 1 - 1
static/app/components/events/eventEntry.tsx

@@ -180,7 +180,7 @@ function EventEntry({
       return (
         <Resources
           description={getResourceDescription(group.issueType)}
-          links={getResourceLinks(group.issueType)}
+          links={getResourceLinks(group.issueType, event.platform)}
         />
       );
     default:

+ 23 - 7
static/app/components/events/interfaces/performance/resources.tsx

@@ -21,13 +21,21 @@ export function Resources(props: Props) {
   return (
     <EventDataSection type="resources-and-whatever" title={t('Resources and Whatever')}>
       {props.description}
-      <LinkSection>
-        {props.links.map(({link, text}) => (
-          <a key={link} href={link} target="_blank" rel="noreferrer">
-            <IconDocs /> {text}
-          </a>
-        ))}
-      </LinkSection>
+      {props.links.length === 0 ? (
+        <NoResourcesMessage>
+          {t(
+            "Well this is awkward. We don't appear to have any resources available for your project platform :("
+          )}
+        </NoResourcesMessage>
+      ) : (
+        <LinkSection>
+          {props.links.map(({link, text}) => (
+            <a key={link} href={link} target="_blank" rel="noreferrer">
+              <IconDocs /> {text}
+            </a>
+          ))}
+        </LinkSection>
+      )}
     </EventDataSection>
   );
 }
@@ -37,6 +45,10 @@ const LinkSection = styled('div')`
   grid-template-columns: 1fr 1fr;
   grid-row-gap: ${space(1)};
 
+  @media (max-width: ${p => p.theme.breakpoints.small}) {
+    grid-template-columns: 1fr;
+  }
+
   margin-top: ${space(2)};
 
   a {
@@ -48,3 +60,7 @@ const LinkSection = styled('div')`
     margin-right: ${space(1)};
   }
 `;
+
+const NoResourcesMessage = styled('p')`
+  margin-top: ${space(1)};
+`;

+ 44 - 25
static/app/components/events/interfaces/performance/utils.tsx

@@ -1,42 +1,61 @@
 import {t} from 'sentry/locale';
-import {IssueType} from 'sentry/types';
+import {IssueType, PlatformType} from 'sentry/types';
 
 import {ResourceLink} from './resources';
 
 const RESOURCES_DESCRIPTIONS: Record<IssueType, string> = {
   [IssueType.PERFORMANCE_N_PLUS_ONE_DB_QUERIES]: t(
-    "N+1 queries are extraneous queries (N) caused by a single, initial query (+1). In the Span Evidence above, we've identified the parent span where the extraneous spans are located, the source span where the queries are initialized, and the extraneous spans themselves. To learn more about how to fix N+1 problems, check out these resources:"
+    "N+1 queries are extraneous queries (N) caused by a single, initial query (+1). In the Span Evidence above, we've identified the parent span where the extraneous spans are located and the extraneous spans themselves. To learn more about how to fix N+1 problems, check out these resources:"
   ),
   [IssueType.ERROR]: '',
 };
 
-const RESOURCE_LINKS: Record<IssueType, ResourceLink[]> = {
-  [IssueType.PERFORMANCE_N_PLUS_ONE_DB_QUERIES]: [
-    {
-      text: t('Finding and Fixing Django N+1 Problems'),
-      link: 'https://blog.sentry.io/2020/09/14/finding-and-fixing-django-n-1-problems',
-    },
-    {
-      text: t('Rails Guide: Active Record Query Interface'),
-      link: 'https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations',
-    },
-    {
-      text: t('Django select_related and prefetch_related'),
-      link: 'https://betterprogramming.pub/django-select-related-and-prefetch-related-f23043fd635d',
-    },
-    // TODO: Update this when the blogpost has been written
-    // {
-    //   text: t('[Leave empty for future Sentry post]'),
-    //   link: 'https://sentry.io/',
-    // },
-  ],
-  [IssueType.ERROR]: [],
+type PlatformSpecificResources = Partial<Record<PlatformType, ResourceLink[]>>;
+
+// TODO: When the Sentry blogpost for N+1s and documentation has been released, add them as resources for all platforms
+const RESOURCE_LINKS: Record<IssueType, PlatformSpecificResources> = {
+  [IssueType.PERFORMANCE_N_PLUS_ONE_DB_QUERIES]: {
+    python: [
+      {
+        text: t('Finding and Fixing Django N+1 Problems'),
+        link: 'https://blog.sentry.io/2020/09/14/finding-and-fixing-django-n-1-problems',
+      },
+      {
+        text: t('Django select_related and prefetch_related'),
+        link: 'https://betterprogramming.pub/django-select-related-and-prefetch-related-f23043fd635d',
+      },
+    ],
+    'python-django': [
+      {
+        text: t('Finding and Fixing Django N+1 Problems'),
+        link: 'https://blog.sentry.io/2020/09/14/finding-and-fixing-django-n-1-problems',
+      },
+      {
+        text: t('Django select_related and prefetch_related'),
+        link: 'https://betterprogramming.pub/django-select-related-and-prefetch-related-f23043fd635d',
+      },
+    ],
+    'ruby-rails': [
+      {
+        text: t('Rails Guide: Active Record Query Interface'),
+        link: 'https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations',
+      },
+    ],
+  },
+  [IssueType.ERROR]: {},
 };
 
 export function getResourceDescription(issueType: IssueType): string {
   return RESOURCES_DESCRIPTIONS[issueType];
 }
 
-export function getResourceLinks(issueType: IssueType) {
-  return RESOURCE_LINKS[issueType];
+export function getResourceLinks(
+  issueType: IssueType,
+  platform: PlatformType | undefined
+): ResourceLink[] {
+  if (!platform || !RESOURCE_LINKS[issueType][platform]) {
+    return [];
+  }
+
+  return RESOURCE_LINKS[issueType][platform] ?? [];
 }

+ 1 - 1
static/app/data/platformCategories.tsx

@@ -168,7 +168,7 @@ export const tracing = [
   'react-native-tracing',
 ] as const;
 
-export const performance: PlatformKey[] = [
+export const performance = [
   'javascript',
   'javascript-ember',
   'javascript-react',

+ 1 - 0
static/app/views/projectInstall/platform.tsx

@@ -157,6 +157,7 @@ class ProjectInstallPlatform extends Component<Props, State> {
                         project: (projects[0] as Project).id,
                       }
                     : {};
+
                 const showPerformancePrompt = performancePlatforms.includes(
                   platform.id as PlatformKey
                 );