Browse Source

fix(stack-trace): Display message when stack trace frames equals null (#26584)

Priscila Oliveira 3 years ago
parent
commit
e5d1dee837

+ 12 - 10
static/app/components/events/interfaces/crashHeader/crashTitle.tsx

@@ -8,7 +8,7 @@ import {t} from 'app/locale';
 type Props = {
   title: string;
   newestFirst: boolean;
-  onChange: ({newestFirst}: {newestFirst: boolean}) => void;
+  onChange?: ({newestFirst}: {newestFirst: boolean}) => void;
   beforeTitle?: React.ReactNode;
   hideGuide?: boolean;
 };
@@ -33,15 +33,17 @@ const CrashTitle = ({
         <GuideAnchor target="exception" disabled={hideGuide} position="bottom">
           {title}
         </GuideAnchor>
-        <Tooltip title={t('Toggle stack trace order')}>
-          <small>
-            (
-            <span onClick={handleToggleOrder}>
-              {newestFirst ? t('most recent call first') : t('most recent call last')}
-            </span>
-            )
-          </small>
-        </Tooltip>
+        {onChange && (
+          <Tooltip title={t('Toggle stack trace order')}>
+            <small>
+              (
+              <span onClick={handleToggleOrder}>
+                {newestFirst ? t('most recent call first') : t('most recent call last')}
+              </span>
+              )
+            </small>
+          </Tooltip>
+        )}
       </StyledH3>
     </Wrapper>
   );

+ 12 - 0
static/app/components/events/interfaces/noStackTraceMessage.tsx

@@ -0,0 +1,12 @@
+import Alert from 'app/components/alert';
+import {t} from 'app/locale';
+
+type Props = {
+  message?: React.ReactNode;
+};
+
+function NoStackTraceMessage({message}: Props) {
+  return <Alert type="error">{message ?? t('No or unknown stacktrace')}</Alert>;
+}
+
+export default NoStackTraceMessage;

+ 25 - 15
static/app/components/events/interfaces/stacktrace.tsx

@@ -10,6 +10,8 @@ import {Project} from 'app/types';
 import {Event} from 'app/types/event';
 import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace';
 
+import NoStackTraceMessage from './noStackTraceMessage';
+
 export function isStacktraceNewestFirst() {
   const user = ConfigStore.get('user');
   // user may not be authenticated
@@ -76,6 +78,8 @@ class StacktraceInterface extends React.Component<Props, State> {
     const {projectId, event, data, hideGuide, type} = this.props;
     const {stackView, newestFirst} = this.state;
 
+    const stackTraceNotFound = !(data.frames ?? []).length;
+
     return (
       <EventDataSection
         type={type}
@@ -84,27 +88,33 @@ class StacktraceInterface extends React.Component<Props, State> {
             title={t('Stack Trace')}
             hideGuide={hideGuide}
             newestFirst={newestFirst}
-            onChange={this.handleChangeNewestFirst}
+            onChange={!stackTraceNotFound ? this.handleChangeNewestFirst : undefined}
           />
         }
         actions={
-          <CrashActions
-            stackView={stackView}
-            platform={event.platform}
-            stacktrace={data}
-            onChange={this.handleChangeStackView}
-          />
+          !stackTraceNotFound && (
+            <CrashActions
+              stackView={stackView}
+              platform={event.platform}
+              stacktrace={data}
+              onChange={this.handleChangeStackView}
+            />
+          )
         }
         wrapTitle={false}
       >
-        <CrashContent
-          projectId={projectId}
-          event={event}
-          stackView={stackView}
-          newestFirst={newestFirst}
-          stacktrace={data}
-          stackType={STACK_TYPE.ORIGINAL}
-        />
+        {stackTraceNotFound ? (
+          <NoStackTraceMessage />
+        ) : (
+          <CrashContent
+            projectId={projectId}
+            event={event}
+            stackView={stackView}
+            newestFirst={newestFirst}
+            stacktrace={data}
+            stackType={STACK_TYPE.ORIGINAL}
+          />
+        )}
       </EventDataSection>
     );
   }

+ 6 - 12
static/app/components/events/interfaces/threads/content.tsx

@@ -10,6 +10,8 @@ import {Event} from 'app/types/event';
 import {Thread} from 'app/types/events';
 import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace';
 
+import NoStackTraceMessage from '../noStackTraceMessage';
+
 type CrashContentProps = React.ComponentProps<typeof CrashContent>;
 
 type Props = {
@@ -17,7 +19,7 @@ type Props = {
   projectId: Project['id'];
   stackType: STACK_TYPE;
   newestFirst: boolean;
-  hasMissingStacktrace: boolean;
+  stackTraceNotFound: boolean;
   stackView?: STACK_VIEW;
   data?: Thread;
 } & Pick<CrashContentProps, 'exception' | 'stacktrace'>;
@@ -31,7 +33,7 @@ const Content = ({
   newestFirst,
   exception,
   stacktrace,
-  hasMissingStacktrace,
+  stackTraceNotFound,
 }: Props) => (
   <div className="thread">
     {data && (!isNil(data?.id) || !!data?.name) && (
@@ -45,16 +47,8 @@ const Content = ({
       </Pills>
     )}
 
-    {hasMissingStacktrace ? (
-      <div className="traceback missing-traceback">
-        <ul>
-          <li className="frame missing-frame">
-            <div className="title">
-              <i>{data?.crashed ? t('Thread Errored') : t('No or unknown stacktrace')}</i>
-            </div>
-          </li>
-        </ul>
-      </div>
+    {stackTraceNotFound ? (
+      <NoStackTraceMessage message={data?.crashed ? t('Thread Errored') : undefined} />
     ) : (
       <CrashContent
         event={event}

+ 4 - 4
static/app/components/events/interfaces/threads/index.tsx

@@ -106,7 +106,7 @@ class Threads extends Component<Props, State> {
       ? getThreadStacktrace(stackType !== STACK_TYPE.ORIGINAL, activeThread)
       : undefined;
 
-    const hasMissingStacktrace = !(exception || stacktrace);
+    const stackTraceNotFound = !(exception || stacktrace);
     const hasMoreThanOneThread = threads.length > 1;
 
     return (
@@ -136,12 +136,12 @@ class Threads extends Component<Props, State> {
               title={t('Stack Trace')}
               newestFirst={newestFirst}
               hideGuide={hideGuide}
-              onChange={this.handleChangeNewestFirst}
+              onChange={!stackTraceNotFound ? this.handleChangeNewestFirst : undefined}
             />
           )
         }
         actions={
-          !hasMissingStacktrace && (
+          !stackTraceNotFound && (
             <CrashActions
               stackView={stackView}
               platform={event.platform}
@@ -165,7 +165,7 @@ class Threads extends Component<Props, State> {
           event={event}
           newestFirst={newestFirst}
           projectId={projectId}
-          hasMissingStacktrace={hasMissingStacktrace}
+          stackTraceNotFound={stackTraceNotFound}
         />
       </EventDataSection>
     );

+ 1 - 1
static/app/types/index.tsx

@@ -1989,7 +1989,7 @@ export type ExceptionValue = {
   rawStacktrace: RawStacktrace;
   mechanism: Mechanism | null;
   module: string | null;
-  frames?: Frame[];
+  frames: Frame[] | null;
 };
 
 export type ExceptionType = {

+ 0 - 4
static/less/group-detail.less

@@ -572,10 +572,6 @@ div.traceback > ul {
       background: @white-dark;
     }
 
-    &.missing-frame .title {
-      background: lighten(@red-light, 30);
-    }
-
     .title.as-table {
       width: 100%;
       padding-left: 15px;