Browse Source

feat(replay): Display an error message when response body was not parsed (#79061)

Previously, when the response body was unable to be parsed, we treated
as if it were skipped. This now displays an error message and hides the
setup instructions.


<img width="433" alt="image"
src="https://github.com/user-attachments/assets/05bea86e-a98c-487c-a81e-1866e0d28c61">


Closes https://github.com/getsentry/sentry/issues/67360
Billy Vong 4 months ago
parent
commit
1395364cc3

+ 15 - 0
static/app/views/replays/detail/network/details/content.tsx

@@ -1,6 +1,8 @@
 import {useEffect} from 'react';
 import {useEffect} from 'react';
 import styled from '@emotion/styled';
 import styled from '@emotion/styled';
 
 
+import {t} from 'sentry/locale';
+import {space} from 'sentry/styles/space';
 import {trackAnalytics} from 'sentry/utils/analytics';
 import {trackAnalytics} from 'sentry/utils/analytics';
 import {getFrameMethod, getFrameStatus} from 'sentry/utils/replays/resourceFrame';
 import {getFrameMethod, getFrameStatus} from 'sentry/utils/replays/resourceFrame';
 import useOrganization from 'sentry/utils/useOrganization';
 import useOrganization from 'sentry/utils/useOrganization';
@@ -68,6 +70,16 @@ export default function NetworkDetailsContent(props: Props) {
             <Setup showSnippet={output} {...props} />
             <Setup showSnippet={output} {...props} />
           )}
           )}
           {output === Output.UNSUPPORTED && <UnsupportedOp type="bodies" />}
           {output === Output.UNSUPPORTED && <UnsupportedOp type="bodies" />}
+          {output === Output.BODY_PARSE_ERROR && (
+            <ParseError>{t('The SDK was unable to parse the response body.')}</ParseError>
+          )}
+          {output === Output.BODY_PARSE_TIMEOUT && (
+            <ParseError>
+              {t(
+                'The SDK timed out while parsing response body. This is to reduce CPU usage on client browsers.'
+              )}
+            </ParseError>
+          )}
         </OverflowFluidHeight>
         </OverflowFluidHeight>
       );
       );
     case 'details':
     case 'details':
@@ -94,3 +106,6 @@ const OverflowFluidHeight = styled(FluidHeight)`
 const SectionList = styled('dl')`
 const SectionList = styled('dl')`
   margin: 0;
   margin: 0;
 `;
 `;
+const ParseError = styled('p')`
+  padding: ${space(2)};
+`;

+ 11 - 0
static/app/views/replays/detail/network/details/getOutputType.tsx

@@ -7,6 +7,8 @@ export enum Output {
   UNSUPPORTED = 'unsupported',
   UNSUPPORTED = 'unsupported',
   URL_SKIPPED = 'url_skipped',
   URL_SKIPPED = 'url_skipped',
   BODY_SKIPPED = 'body_skipped',
   BODY_SKIPPED = 'body_skipped',
+  BODY_PARSE_ERROR = 'body_parse_error',
+  BODY_PARSE_TIMEOUT = 'body_parse_timeout',
   DATA = 'data',
   DATA = 'data',
 }
 }
 
 
@@ -44,6 +46,15 @@ export default function getOutputType({isSetup, item, visibleTab}: Args): Output
   const respWarnings = response?._meta?.warnings ?? ['URL_SKIPPED'];
   const respWarnings = response?._meta?.warnings ?? ['URL_SKIPPED'];
   const isReqUrlSkipped = reqWarnings?.includes('URL_SKIPPED');
   const isReqUrlSkipped = reqWarnings?.includes('URL_SKIPPED');
   const isRespUrlSkipped = respWarnings?.includes('URL_SKIPPED');
   const isRespUrlSkipped = respWarnings?.includes('URL_SKIPPED');
+
+  if (respWarnings?.includes('BODY_PARSE_ERROR')) {
+    return Output.BODY_PARSE_ERROR;
+  }
+
+  if (respWarnings?.includes('BODY_PARSE_TIMEOUT')) {
+    return Output.BODY_PARSE_TIMEOUT;
+  }
+
   if (isReqUrlSkipped || isRespUrlSkipped) {
   if (isReqUrlSkipped || isRespUrlSkipped) {
     return Output.URL_SKIPPED;
     return Output.URL_SKIPPED;
   }
   }