Browse Source

fix(source-map-debugger): minor fixes to source map debugger (#44189)

1. Fixes problem where every event had platform `javascript`
2. Changes some text in the messages
Stephen Cefali 2 years ago
parent
commit
6dedaa5ced

+ 4 - 2
static/app/components/events/interfaces/crashContent/exception/content.tsx

@@ -55,7 +55,7 @@ export function Content({
   }
 
   const shouldDebugFrames = debugFramesEnabled({
-    platform,
+    sdkName: event.sdk?.name,
     organization,
     eventId: event.id,
     projectSlug,
@@ -68,6 +68,8 @@ export function Content({
       })
     : [];
 
+  const sdkName = event.sdk?.name;
+
   const children = values.map((exc, excIdx) => {
     const hasSourcemapDebug = debugFrames.some(
       ({query}) => query.exceptionIdx === excIdx
@@ -95,7 +97,7 @@ export function Content({
           <Fragment>
             {!shouldDebugFrames && <SetupSourceMapsAlert event={event} />}
             {hasSourcemapDebug && (
-              <SourceMapDebug debugFrames={debugFrames} platform={platform} />
+              <SourceMapDebug debugFrames={debugFrames} sdkName={sdkName} />
             )}
           </Fragment>
         </ErrorBoundary>

+ 9 - 9
static/app/components/events/interfaces/crashContent/exception/sourceMapDebug.spec.tsx

@@ -58,7 +58,7 @@ describe('SourceMapDebug', () => {
     },
   ];
   const url = `/projects/${organization.slug}/${project.slug}/events/${eventId}/source-map-debug/`;
-  const platform = 'javascript';
+  const sdkName = 'sentry.javascript.browser';
   const debugFrames = getUniqueFilesFromException(exceptionValues, {
     orgSlug: organization.slug,
     projectSlug: project.slug,
@@ -87,12 +87,12 @@ describe('SourceMapDebug', () => {
       match: [MockApiClient.matchQuery({exception_idx: '0', frame_idx: '0'})],
     });
 
-    render(<SourceMapDebug debugFrames={debugFrames} platform={platform} />, {
+    render(<SourceMapDebug debugFrames={debugFrames} sdkName={sdkName} />, {
       organization,
     });
     expect(
       await screen.findByText(
-        'We’ve encountered 1 problem de-minifying your applications source code!'
+        "We've encountered 1 problem de-minifying your applications source code!"
       )
     ).toBeInTheDocument();
 
@@ -100,7 +100,7 @@ describe('SourceMapDebug', () => {
     expect(screen.getByText('Event missing Release tag')).toBeInTheDocument();
     expect(screen.getByRole('link', {name: 'Read Guide'})).toHaveAttribute(
       'href',
-      'https://docs.sentry.io/platforms/javascript/configuration/options/#release'
+      'https://docs.sentry.io/platforms/javascript/sourcemaps/#uploading-source-maps-to-sentry'
     );
   });
 
@@ -116,12 +116,12 @@ describe('SourceMapDebug', () => {
       match: [MockApiClient.matchQuery({exception_idx: '0', frame_idx: '0'})],
     });
 
-    render(<SourceMapDebug debugFrames={debugFrames} platform={platform} />, {
+    render(<SourceMapDebug debugFrames={debugFrames} sdkName={sdkName} />, {
       organization,
     });
     expect(
       await screen.findByText(
-        'We’ve encountered 1 problem de-minifying your applications source code!'
+        "We've encountered 1 problem de-minifying your applications source code!"
       )
     ).toBeInTheDocument();
 
@@ -148,17 +148,17 @@ describe('SourceMapDebug', () => {
       body: {errors: [error]},
     });
 
-    render(<SourceMapDebug debugFrames={debugFrames} platform={platform} />, {
+    render(<SourceMapDebug debugFrames={debugFrames} sdkName={sdkName} />, {
       organization,
     });
     expect(
       await screen.findByText(
-        'We’ve encountered 1 problem de-minifying your applications source code!'
+        "We've encountered 1 problem de-minifying your applications source code!"
       )
     ).toBeInTheDocument();
 
     const expandedMessage =
-      'The abs_path of the stack frame has absValue which is not a valid URL.';
+      'The given abs_path of the stack frame is absValue which is not a valid URL. Please refer to the instructions in our docs guide for help with troubleshooting the issue.';
     expect(
       screen.queryByText(textWithMarkupMatcher(expandedMessage))
     ).not.toBeInTheDocument();

+ 63 - 62
static/app/components/events/interfaces/crashContent/exception/sourceMapDebug.tsx

@@ -10,7 +10,6 @@ import ListItem from 'sentry/components/list/listItem';
 import {IconWarning} from 'sentry/icons';
 import {t, tct, tn} from 'sentry/locale';
 import space from 'sentry/styles/space';
-import type {PlatformType} from 'sentry/types';
 import {defined} from 'sentry/utils';
 import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
 import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
@@ -23,30 +22,14 @@ import {
   StacktraceFilenameQuery,
   useSourceMapDebugQueries,
 } from './useSourceMapDebug';
+import {sourceMapSdkDocsMap} from './utils';
 
-const platformDocsMap: Record<string, string> = {
-  javascript: 'javascript',
-  node: 'node',
-  'javascript-react': 'react',
-  'javascript-angular': 'angular',
-  // Sending angularjs to angular docs since it's not supported, has limited docs
-  'javascript-angularjs': 'angular',
-  // Sending backbone to javascript docs since it's not supported
-  'javascript-backbone': 'javascript',
-  'javascript-ember': 'ember',
-  'javascript-gatsby': 'gatsby',
-  'javascript-vue': 'vue',
-  'javascript-nextjs': 'nextjs',
-  'javascript-remix': 'remix',
-  'javascript-svelte': 'svelte',
-};
-
-const shortPathPlatforms = ['javascript', 'node'];
+const shortPathPlatforms = ['javascript', 'node', 'react-native'];
 const sentryInit = <code>Sentry.init</code>;
 
 function getErrorMessage(
   error: SourceMapDebugError,
-  platform: PlatformType
+  sdkName?: string
 ): Array<{
   title: string;
   /**
@@ -55,9 +38,23 @@ function getErrorMessage(
   desc?: string;
   docsLink?: string;
 }> {
-  const docPlatform = platformDocsMap[platform] ?? 'javascript';
+  const docPlatform = (sdkName && sourceMapSdkDocsMap[sdkName]) ?? 'javascript';
   const useShortPath = shortPathPlatforms.includes(docPlatform);
 
+  const baseSourceMapDocsLink = useShortPath
+    ? `https://docs.sentry.io/platforms/${docPlatform}/sourcemaps/`
+    : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/sourcemaps/`;
+
+  function getTroubleshootingLink(section?: string) {
+    // react-native has a different troubleshooting page
+    if (docPlatform === 'react-native') {
+      return 'https://docs.sentry.io/platforms/react-native/troubleshooting/#source-maps';
+    }
+    return `${baseSourceMapDocsLink}troubleshooting_js/` + (section ? `#${section}` : '');
+  }
+
+  const defaultDocsLink = `${baseSourceMapDocsLink}#uploading-source-maps-to-sentry`;
+
   switch (error.type) {
     case SourceMapProcessingIssueType.MISSING_RELEASE:
       return [
@@ -66,9 +63,7 @@ function getErrorMessage(
           desc: t(
             'Integrate Sentry into your release pipeline. You can do this with a tool like Webpack or using the CLI.'
           ),
-          docsLink: useShortPath
-            ? `https://docs.sentry.io/platforms/${docPlatform}/configuration/options/#release`
-            : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/configuration/options/#release`,
+          docsLink: defaultDocsLink,
         },
       ];
     case SourceMapProcessingIssueType.PARTIAL_MATCH:
@@ -79,25 +74,23 @@ function getErrorMessage(
             error.data.absPath,
             error.data.partialMatchPath
           ),
-          docsLink: useShortPath
-            ? `https://docs.sentry.io/platforms/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`
-            : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`,
+          docsLink: getTroubleshootingLink(
+            'verify-artifact-names-match-stack-trace-frames'
+          ),
         },
       ];
     case SourceMapProcessingIssueType.MISSING_USER_AGENT:
       return [
         {
-          title: t('Event has Release but no User-Agent'),
+          title: t('Sentry not part of release pipeline'),
           desc: tct(
-            'Integrate Sentry into your release pipeline. You can do this with a tool like Webpack or using the CLI. Please note the release must be the same as being set in your [init]. The value for this event is [version]',
+            'Integrate Sentry into your release pipeline. You can do this with a tool like Webpack or using the CLI. Please note the release must be the same as being set in your [init]. The value for this event is [version].',
             {
               init: sentryInit,
-              version: error.data.version,
+              version: <code>{error.data.version}</code>,
             }
           ),
-          docsLink: useShortPath
-            ? `https://docs.sentry.io/platforms/${docPlatform}/sourcemaps/#uploading-source-maps-to-sentry`
-            : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/sourcemaps/#uploading-source-maps-to-sentry`,
+          docsLink: defaultDocsLink,
         },
       ];
     case SourceMapProcessingIssueType.MISSING_SOURCEMAPS:
@@ -107,9 +100,7 @@ function getErrorMessage(
           desc: t(
             'It looks like you are creating but not uploading your source maps. Please refer to the instructions in our docs guide for help with troubleshooting the issue.'
           ),
-          docsLink: useShortPath
-            ? `https://docs.sentry.io/platforms/${docPlatform}/sourcemaps/`
-            : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/sourcemaps/`,
+          docsLink: defaultDocsLink,
         },
       ];
     case SourceMapProcessingIssueType.URL_NOT_VALID:
@@ -117,12 +108,15 @@ function getErrorMessage(
         {
           title: t('Invalid Absolute Path URL'),
           desc: tct(
-            'The abs_path of the stack frame has [absPath] which is not a valid URL. Please refer to the instructions in our docs guide for help with troubleshooting the issue.',
-            {absPath: <code>{error.data.absPath}</code>}
+            'The given [literalAbsPath] of the stack frame is [absPath] which is not a valid URL. Please refer to the instructions in our docs guide for help with troubleshooting the issue.',
+            {
+              absPath: <code>{error.data.absPath}</code>,
+              literalAbsPath: <code>abs_path</code>,
+            }
+          ),
+          docsLink: getTroubleshootingLink(
+            'verify-artifact-names-match-stack-trace-frames'
           ),
-          docsLink: useShortPath
-            ? `https://docs.sentry.io/platforms/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`
-            : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`,
         },
       ];
     case SourceMapProcessingIssueType.NO_URL_MATCH:
@@ -130,12 +124,15 @@ function getErrorMessage(
         {
           title: t('Absolute Path Mismatch'),
           desc: tct(
-            'The [absPath] of the stack frame doesn’t match any release artifact. Please refer to the instructions in our docs guide for help with troubleshooting the issue.',
-            {absPath: <code>{error.data.absPath}</code>}
+            "The given [literalAbsPath] of the stack frame is [absPath] which doesn't match any release artifact. Please refer to the instructions in our docs guide for help with troubleshooting the issue.",
+            {
+              absPath: <code>{error.data.absPath}</code>,
+              literalAbsPath: <code>abs_path</code>,
+            }
+          ),
+          docsLink: getTroubleshootingLink(
+            'verify-artifact-names-match-stack-trace-frames'
           ),
-          docsLink: useShortPath
-            ? `https://docs.sentry.io/platforms/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`
-            : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`,
         },
       ];
     case SourceMapProcessingIssueType.DIST_MISMATCH:
@@ -143,12 +140,16 @@ function getErrorMessage(
         {
           title: t('Absolute Path Mismatch'),
           desc: tct(
-            'The distribution identifier you are providing doesn’t match. The [dist] value configured in your [init] must be the same as the one used during source map upload. Please refer to the instructions in our docs guide for help with troubleshooting the issue.',
-            {init: sentryInit, dist: <code>dist</code>}
+            "The distribution identifier you are providing doesn't match. The [literalDist] value of [dist] configured in your [init] must be the same as the one used during source map upload. Please refer to the instructions in our docs guide for help with troubleshooting the issue.",
+            {
+              init: sentryInit,
+              dist: <code>dist</code>,
+              literalDist: <code>dist</code>,
+            }
+          ),
+          docsLink: getTroubleshootingLink(
+            'verify-artifact-distribution-value-matches-value-configured-in-your-sdk'
           ),
-          docsLink: useShortPath
-            ? `https://docs.sentry.io/platforms/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`
-            : `https://docs.sentry.io/platforms/javascript/guides/${docPlatform}/sourcemaps/troubleshooting_js/#verify-artifact-names-match-stack-trace-frames`,
         },
       ];
     case SourceMapProcessingIssueType.UNKNOWN_ERROR:
@@ -203,7 +204,7 @@ function ExpandableErrorList({
 
 function combineErrors(
   response: Array<SourceMapDebugResponse | undefined | null>,
-  platform: PlatformType
+  sdkName?: string
 ) {
   const combinedErrors = uniqBy(
     response
@@ -214,7 +215,7 @@ function combineErrors(
   );
   const errors = combinedErrors
     .map(error =>
-      getErrorMessage(error, platform).map(message => ({...message, type: error.type}))
+      getErrorMessage(error, sdkName).map(message => ({...message, type: error.type}))
     )
     .flat();
 
@@ -226,17 +227,17 @@ interface SourcemapDebugProps {
    * A subset of the total error frames to validate sourcemaps
    */
   debugFrames: StacktraceFilenameQuery[];
-  platform: PlatformType;
+  sdkName?: string;
 }
 
-export function SourceMapDebug({debugFrames, platform}: SourcemapDebugProps) {
+export function SourceMapDebug({debugFrames, sdkName}: SourcemapDebugProps) {
   const organization = useOrganization();
   const results = useSourceMapDebugQueries(debugFrames.map(debug => debug.query));
 
   const isLoading = results.every(result => result.isLoading);
   const errorMessages = combineErrors(
     results.map(result => result.data).filter(defined),
-    platform
+    sdkName
   );
 
   useRouteAnalyticsParams({
@@ -248,17 +249,17 @@ export function SourceMapDebug({debugFrames, platform}: SourcemapDebugProps) {
   }
 
   const handleDocsClick = (type: SourceMapProcessingIssueType) => {
-    trackAdvancedAnalyticsEvent('growth.sourcemap_docs_clicked', {
+    trackAdvancedAnalyticsEvent('source_map_debug.docs_link_clicked', {
       organization,
-      platform,
+      sdkName,
       type,
     });
   };
 
   const handleExpandClick = (type: SourceMapProcessingIssueType) => {
-    trackAdvancedAnalyticsEvent('growth.sourcemap_expand_clicked', {
+    trackAdvancedAnalyticsEvent('source_map_debug.expand_clicked', {
       organization,
-      platform,
+      sdkName,
       type,
     });
   };
@@ -294,8 +295,8 @@ export function SourceMapDebug({debugFrames, platform}: SourcemapDebugProps) {
       }
     >
       {tn(
-        'We’ve encountered %s problem de-minifying your applications source code!',
-        'We’ve encountered %s problems de-minifying your applications source code!',
+        "We've encountered %s problem de-minifying your applications source code!",
+        "We've encountered %s problems de-minifying your applications source code!",
         errorMessages.length
       )}
     </Alert>

+ 7 - 23
static/app/components/events/interfaces/crashContent/exception/useSourceMapDebug.tsx

@@ -1,11 +1,11 @@
 import uniqBy from 'lodash/uniqBy';
 
-import type {ExceptionValue, Frame, Organization, PlatformType} from 'sentry/types';
+import type {ExceptionValue, Frame, Organization} from 'sentry/types';
 import {defined} from 'sentry/utils';
 import {QueryKey, useQueries, useQuery, UseQueryOptions} from 'sentry/utils/queryClient';
 import useApi from 'sentry/utils/useApi';
 
-import {isFrameFilenamePathlike} from './utils';
+import {isFrameFilenamePathlike, sourceMapSdkDocsMap} from './utils';
 
 interface BaseSourceMapDebugError {
   message: string;
@@ -130,40 +130,24 @@ export function useSourceMapDebugQueries(props: UseSourceMapDebugProps[]) {
   });
 }
 
-const ALLOWED_PLATFORMS = [
-  'node',
-  'javascript',
-  'javascript-react',
-  'javascript-angular',
-  'javascript-angularjs',
-  'javascript-backbone',
-  'javascript-ember',
-  'javascript-gatsby',
-  'javascript-vue',
-  'javascript-nextjs',
-  'javascript-remix',
-  'javascript-svelte',
-  // dart and unity might require more docs links
-  // 'dart',
-  // 'unity',
-];
+const ALLOWED_SDKS = Object.keys(sourceMapSdkDocsMap);
 const MAX_FRAMES = 3;
 
 /**
  * Check we have all required props and platform is supported
  */
 export function debugFramesEnabled({
-  platform,
+  sdkName,
   eventId,
   organization,
   projectSlug,
 }: {
-  platform: PlatformType;
   eventId?: string;
   organization?: Organization | null;
   projectSlug?: string;
+  sdkName?: string;
 }) {
-  if (!organization || !organization.features || !projectSlug || !eventId) {
+  if (!organization || !organization.features || !projectSlug || !eventId || !sdkName) {
     return false;
   }
 
@@ -171,7 +155,7 @@ export function debugFramesEnabled({
     return false;
   }
 
-  return ALLOWED_PLATFORMS.includes(platform);
+  return ALLOWED_SDKS.includes(sdkName);
 }
 
 /**

+ 15 - 0
static/app/components/events/interfaces/crashContent/exception/utils.tsx

@@ -19,3 +19,18 @@ export function isFrameFilenamePathlike(frame: Frame): boolean {
     (!!frame.absPath && !getFileExtension(filename))
   );
 }
+
+// Maps the SDK name to the url token for docs
+export const sourceMapSdkDocsMap: Record<string, string> = {
+  'sentry.javascript.browser': 'javascript',
+  'sentry.javascript.node': 'node',
+  'sentry.javascript.react': 'react',
+  'sentry.javascript.angular': 'angular',
+  'sentry.javascript.ember': 'ember',
+  'sentry.javascript.gatsby': 'gatsby',
+  'sentry.javascript.vue': 'vue',
+  'sentry.javascript.nextjs': 'nextjs',
+  'sentry.javascript.remix': 'remix',
+  'sentry.javascript.svelte': 'svelte',
+  'sentry.javascript.react-native': 'react-native',
+};

+ 0 - 11
static/app/utils/analytics/growthAnalyticsEvents.tsx

@@ -1,6 +1,4 @@
-import type {SourceMapProcessingIssueType} from 'sentry/components/events/interfaces/crashContent/exception/useSourceMapDebug';
 import type {PlatformKey} from 'sentry/data/platformCategories';
-import type {PlatformType} from 'sentry/types';
 
 type MobilePromptBannerParams = {
   matchedUserAgentString: string;
@@ -48,11 +46,6 @@ type SampleEvent = {
   source: string;
 };
 
-type SourceMapDebugParam = {
-  platform: PlatformType;
-  type: SourceMapProcessingIssueType;
-};
-
 // define the event key to payload mappings
 export type GrowthEventParameters = {
   'assistant.guide_cued': {
@@ -117,8 +110,6 @@ export type GrowthEventParameters = {
     project_id: string;
   };
   'growth.select_platform': PlatformPickerParam;
-  'growth.sourcemap_docs_clicked': SourceMapDebugParam;
-  'growth.sourcemap_expand_clicked': SourceMapDebugParam;
   'growth.submitted_mobile_prompt_ask_teammate': MobilePromptBannerParams;
   'invite_modal.add_more': InviteModal;
   'invite_modal.closed': InviteModal;
@@ -199,8 +190,6 @@ export const growthEventMap: Record<GrowthAnalyticsKey, string | null> = {
   'growth.sample_error_onboarding_link_clicked':
     'Growth: Sample Error Onboarding Link Clicked',
   'member_settings_page.loaded': 'Member Settings Page Loaded',
-  'growth.sourcemap_docs_clicked': 'SourceMap Debug: Docs Clicked',
-  'growth.sourcemap_expand_clicked': 'SourceMap Debug: Expand Clicked',
   'invite_modal.opened': 'Invite Modal: Opened',
   'invite_modal.closed': 'Invite Modal: Closed',
   'invite_modal.add_more': 'Invite Modal: Add More',

+ 11 - 0
static/app/utils/analytics/issueAnalyticsEvents.tsx

@@ -1,9 +1,16 @@
+import type {SourceMapProcessingIssueType} from 'sentry/components/events/interfaces/crashContent/exception/useSourceMapDebug';
+
 type IssueStream = {
   group_id: string;
   tab: string;
   was_shown_suggestion: boolean;
 };
 
+type SourceMapDebugParam = {
+  type: SourceMapProcessingIssueType;
+  sdkName?: string;
+};
+
 export type IssueEventParameters = {
   'event_cause.dismissed': {};
   'event_cause.docs_clicked': {};
@@ -122,6 +129,8 @@ export type IssueEventParameters = {
     node_key: string;
   };
   resolve_issue: {release: string};
+  'source_map_debug.docs_link_clicked': SourceMapDebugParam;
+  'source_map_debug.expand_clicked': SourceMapDebugParam;
   'span_view.embedded_child.hide': {};
   'span_view.embedded_child.show': {};
   'tag.clicked': {
@@ -176,4 +185,6 @@ export const issueEventMap: Record<IssueEventKey, string | null> = {
     'Performance Issue Details: Autogrouped Siblings Toggled',
   'issue_details.performance.hidden_spans_expanded':
     'Performance Issue Details: Hidden Spans Expanded',
+  'source_map_debug.docs_link_clicked': 'Source Map Debug: Docs Clicked',
+  'source_map_debug.expand_clicked': 'Source Map Debug: Expand Clicked',
 };