Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ const makeEventWithThreads = (threads: Thread[]): Event => {
type: 'ZeroDivisionError',
value: 'divided by 0',
},
tags: [{key: 'level', value: 'error'}],
tags: [
{key: 'level', value: 'error'},
{key: 'mechanism', value: 'ANR'},
],
platform: 'other',
dateReceived: '2021-10-28T12:28:22.318469Z',
errors: [],
Expand Down Expand Up @@ -251,12 +254,8 @@ describe('anrRootCause', () => {
)
)
).toBeInTheDocument();
expect(screen.getByTestId('stack-trace-content')).toBeInTheDocument();
expect(
screen.getByText(textWithMarkupMatcher('Thread.java in wait at line 10'))
).toBeInTheDocument();
expect(
screen.getByText(textWithMarkupMatcher('MainActivity.java in onCreate at line 366'))
).toBeInTheDocument();
expect(screen.getByText('Suspect Frame')).toBeInTheDocument();
expect(screen.getByText('wait')).toBeInTheDocument();
expect(screen.getByText('onCreate')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import styled from '@emotion/styled';
import {Link} from '@sentry/scraps/link';

import {analyzeFramesForRootCause} from 'sentry/components/events/interfaces/analyzeFrames';
import {StackTraceContent} from 'sentry/components/events/interfaces/crashContent/stackTrace';
import {NoStackTraceMessage} from 'sentry/components/events/interfaces/noStackTraceMessage';
import {getThreadStacktrace} from 'sentry/components/events/interfaces/threads/threadSelector/getThreadStacktrace';
import {
Expand All @@ -15,10 +14,14 @@ import {
import {ShortId} from 'sentry/components/group/inboxBadges/shortId';
import ProjectBadge from 'sentry/components/idBadge/projectBadge';
import {extractSelectionParameters} from 'sentry/components/pageFilters/parse';
import {FrameContent} from 'sentry/components/stackTrace/frame/frameContent';
import {IssueFrameActions} from 'sentry/components/stackTrace/issueStackTrace/issueFrameActions';
import {StackTraceViewStateProvider} from 'sentry/components/stackTrace/stackTraceContext';
import {StackTraceFrames} from 'sentry/components/stackTrace/stackTraceFrames';
import {StackTraceProvider} from 'sentry/components/stackTrace/stackTraceProvider';
import {t} from 'sentry/locale';
import type {Event} from 'sentry/types/event';
import type {Organization} from 'sentry/types/organization';
import {StackView} from 'sentry/types/stacktrace';
import {trackAnalytics} from 'sentry/utils/analytics';
import {defined} from 'sentry/utils/defined';
import {useLocation} from 'sentry/utils/useLocation';
Expand Down Expand Up @@ -113,14 +116,20 @@ export function AnrRootCause({event, organization}: Props) {
{anrCulprit?.resources}
<StackTraceWrapper>
{defined(stackTrace) ? (
<StackTraceContent
stacktrace={stackTrace}
stackView={StackView.FULL}
newestFirst
event={event}
platform={platform}
lockAddress={address ?? undefined}
/>
<StackTraceViewStateProvider defaultView="full" platform={platform}>
<StackTraceProvider
stacktrace={stackTrace}
event={event}
platform={platform}
thread={culpritThread}
lockAddress={address ?? undefined}
>
<StackTraceFrames
frameActionsComponent={IssueFrameActions}
frameContextComponent={FrameContent}
/>
</StackTraceProvider>
</StackTraceViewStateProvider>
) : (
<NoStackTraceMessage />
)}
Expand Down
55 changes: 55 additions & 0 deletions static/app/components/events/interfaces/template.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {EventFixture} from 'sentry-fixture/event';
import {FrameFixture} from 'sentry-fixture/frame';

import {render, screen} from 'sentry-test/reactTestingLibrary';

import {Template} from 'sentry/components/events/interfaces/template';
import {EntryType} from 'sentry/types/event';

it('renders template source context expanded in the new stack trace', () => {
const frame = FrameFixture({
platform: 'python',
filename: 'template.html',
context: [[3, '{{ example.value }}']],
lineNo: 3,
vars: {example: 'value'},
});
render(
<Template
data={frame}
event={EventFixture({
platform: 'python',
entries: [{type: EntryType.TEMPLATE, data: frame}],
})}
/>
);
expect(screen.getByText('Template')).toBeInTheDocument();
expect(screen.getByText('{{ example.value }}')).toBeInTheDocument();
expect(screen.getByTestId('core-stacktrace-frame-row')).toBeInTheDocument();
});

it('preserves redaction metadata on template variables', () => {
const frame = FrameFixture({platform: 'python', vars: {password: ''}});
render(
<Template
data={frame}
event={EventFixture({
platform: 'python',
entries: [{type: EntryType.TEMPLATE, data: frame}],
_meta: {
entries: {
0: {
data: {
values: {
vars: {password: {'': {rem: [['!config', 's', 0, 0]]}}},
},
},
},
},
},
})}
/>
);

expect(screen.getByText(/redacted/)).toBeVisible();
});
47 changes: 19 additions & 28 deletions static/app/components/events/interfaces/template.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
import {FrameContent} from 'sentry/components/stackTrace/frame/frameContent';
import {StackTraceViewStateProvider} from 'sentry/components/stackTrace/stackTraceContext';
import {StackTraceFrames} from 'sentry/components/stackTrace/stackTraceFrames';
import {StackTraceProvider} from 'sentry/components/stackTrace/stackTraceProvider';
import {t} from 'sentry/locale';
import type {Event, Frame} from 'sentry/types/event';
import {EntryType} from 'sentry/types/event';
import {SectionKey} from 'sentry/views/issueDetails/context';
import {FoldSection} from 'sentry/views/issueDetails/foldSection';

import {DeprecatedLine} from './frame/deprecatedLine';

type Props = {
data: Frame;
event: Event;
};
type Props = {data: Frame; event: Event};

export function Template({data, event}: Props) {
const entryIndex = event.entries.findIndex(entry => entry.type === EntryType.TEMPLATE);
const meta = event._meta?.entries?.[entryIndex]?.data?.values;
return (
<FoldSection title={t('Template')} sectionKey={SectionKey.TEMPLATE}>
<div className="traceback no-exception">
<ul>
<DeprecatedLine
data={data}
event={event}
registers={{}}
frameMeta={meta}
isExpanded
platform={event.platform ?? 'other'}
hideSourceMapDebugger={false}
isHoverPreviewed={false}
threadId={undefined}
frameSourceResolutionResults={undefined}
emptySourceNotation={false}
hiddenFrameCount={0}
isANR={false}
lockAddress={undefined}
nextFrame={undefined}
timesRepeated={0}
/>
</ul>
</div>
<StackTraceViewStateProvider defaultView="full" platform={event.platform}>
<StackTraceProvider
event={event}
stacktrace={{
frames: [data],
framesOmitted: null,
hasSystemFrames: false,
registers: null,
}}
meta={{frames: [meta]}}
>
<StackTraceFrames frameContextComponent={FrameContent} />
</StackTraceProvider>
</StackTraceViewStateProvider>
</FoldSection>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {Tag} from '@sentry/scraps/badge';

import {analyzeFrameForRootCause} from 'sentry/components/events/interfaces/analyzeFrames';
import {
useStackTraceContext,
useStackTraceFrameContext,
} from 'sentry/components/stackTrace/stackTraceContext';
import {t} from 'sentry/locale';
import {SectionKey} from 'sentry/views/issueDetails/context';

export function AnrFrameAction() {
const {thread, lockAddress} = useStackTraceContext();
const {event, frame} = useStackTraceFrameContext();
const mechanism = event.tags?.find(tag => tag.key === 'mechanism')?.value;
if (mechanism !== 'ANR' && mechanism !== 'AppExitInfo') {
return null;
}
if (!analyzeFrameForRootCause(frame, thread, lockAddress)) {
return null;
}
return (
<Tag
variant="warning"
onClick={clickEvent => {
clickEvent.stopPropagation();
document
.getElementById(SectionKey.SUSPECT_ROOT_CAUSE)
?.scrollIntoView({block: 'start', behavior: 'smooth'});
}}
>
{t('Suspect Frame')}
</Tag>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import {IconRefresh} from 'sentry/icons';
import {t, tn} from 'sentry/locale';

import {AnrFrameAction} from './anrFrameAction';
import {IssueSourceLinkAction} from './issueSourceLinkAction';
import {IssueSourceMapsDebuggerAction} from './issueSourceMapsDebuggerAction';

Expand All @@ -27,6 +28,7 @@ export function IssueFrameActions({isHovering}: IssueFrameActionsProps) {
<Fragment>
<IssueSourceLinkAction isHovering={isHovering} />
<IssueSourceMapsDebuggerAction />
<AnrFrameAction />
{hiddenFrameCount ? <HiddenFramesToggleAction /> : null}
{timesRepeated > 0 ? (
<Tooltip
Expand Down
4 changes: 3 additions & 1 deletion static/app/components/stackTrace/stackTraceContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {createContext, useContext, useMemo, useState} from 'react';

import type {FrameSourceMapDebuggerData} from 'sentry/components/events/interfaces/sourceMapsDebuggerModal';
import type {Event, Frame} from 'sentry/types/event';
import type {Event, Frame, Thread} from 'sentry/types/event';
import type {PlatformKey} from 'sentry/types/platform';
import type {Project} from 'sentry/types/project';
import type {StacktraceType} from 'sentry/types/stacktrace';
Expand Down Expand Up @@ -82,10 +82,12 @@ export interface StackTraceContextValue {
exceptionIndex?: number;
/** Optional per-frame source map debugger resolution data. */
frameSourceMapDebuggerData?: FrameSourceMapDebuggerData[];
lockAddress?: string;
/** Optional redaction metadata used by variable/register renderers. */
meta?: StackTraceMeta;
/** Active project from ProjectsStore, used by frame source-link actions. */
project?: Project;
thread?: Thread;
}

export interface StackTraceFrameContextValue {
Expand Down
6 changes: 6 additions & 0 deletions static/app/components/stackTrace/stackTraceProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ function getDefaultPlatform(stacktrace: StacktraceType, event: Event): PlatformK
export function StackTraceProvider({
children,
collapseAll = false,
thread,
lockAddress,
exceptionIndex,
event,
frameSourceMapDebuggerData,
Expand Down Expand Up @@ -133,6 +135,8 @@ export function StackTraceProvider({
const value = useMemo<StackTraceContextValue>(
() => ({
allRows,
thread,
lockAddress,
collapseAll,
exceptionIndex,
event,
Expand All @@ -152,6 +156,8 @@ export function StackTraceProvider({
}),
[
allRows,
lockAddress,
thread,
collapseAll,
exceptionIndex,
event,
Expand Down
4 changes: 3 additions & 1 deletion static/app/components/stackTrace/types.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {ReactNode} from 'react';

import type {FrameSourceMapDebuggerData} from 'sentry/components/events/interfaces/sourceMapsDebuggerModal';
import type {Event, Frame} from 'sentry/types/event';
import type {Event, Frame, Thread} from 'sentry/types/event';
import type {PlatformKey} from 'sentry/types/platform';
import type {StacktraceType} from 'sentry/types/stacktrace';

Expand Down Expand Up @@ -66,6 +66,7 @@ export interface StackTraceProviderProps {
hasScmSourceContext?: boolean;
/** Hide the source maps debugger button entirely. */
hideSourceMapDebugger?: boolean;
lockAddress?: string;
/** Cap the number of frames rendered. Frames beyond this depth are omitted. */
maxDepth?: number;
/** Relay PII/scrubbing metadata used to render redaction annotations on frame variables. */
Expand All @@ -77,4 +78,5 @@ export interface StackTraceProviderProps {
minifiedStacktrace?: StacktraceType;
/** Override the platform used for frame rendering logic. Defaults to the event/frame platform. */
platform?: PlatformKey;
thread?: Thread;
}
Loading