Skip to content

Commit 8f99f80

Browse files
scttcperclaude
andcommitted
feat(profiling): New stack trace in span profile details + fix maxDepth
`StackTraceProvider` was applying `maxDepth` to both `allRows` (the full frame list used as the render loop) and `rows` (the filtered visible frames). Since `allRows` includes all system frames and `rows` only includes in-app frames, `maxDepth` would slice different ranges and the intersection could lose in-app frames entirely. Fix: only apply `maxDepth` to `rows`. `allRows` drives the render loop but frames outside `rows` are either null or Activity-hidden, so visible count is still capped. Also uses the new stack trace in the "Most Frequent Stacks in this Span" section behind `issue-details-new-stack-trace`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 151080e commit 8f99f80

File tree

5 files changed

+77
-20
lines changed

5 files changed

+77
-20
lines changed

static/app/components/events/interfaces/spans/spanProfileDetails.tsx

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import {SectionHeading} from 'sentry/components/charts/styles';
77
import {StackTraceContent} from 'sentry/components/events/interfaces/crashContent/stackTrace';
88
import {StackTraceContentPanel} from 'sentry/components/events/interfaces/crashContent/stackTrace/content';
99
import {QuestionTooltip} from 'sentry/components/questionTooltip';
10+
import {FrameContent} from 'sentry/components/stackTrace/frame/frameContent';
11+
import {StackTraceViewStateProvider} from 'sentry/components/stackTrace/stackTraceContext';
12+
import {StackTraceFrames} from 'sentry/components/stackTrace/stackTraceFrames';
13+
import {StackTraceProvider} from 'sentry/components/stackTrace/stackTraceProvider';
1014
import {IconChevron, IconProfiling} from 'sentry/icons';
1115
import {t, tct} from 'sentry/locale';
1216
import {EntryType, type EventTransaction, type Frame} from 'sentry/types/event';
@@ -298,20 +302,37 @@ export function SpanProfileDetails({
298302
</LinkButton>
299303
</SpanDetailsItem>
300304
</SpanDetails>
301-
<StackTraceContent
302-
event={processedEvent}
303-
newestFirst
304-
platform={event.platform || 'other'}
305-
stacktrace={{
306-
framesOmitted: null,
307-
hasSystemFrames: false,
308-
registers: null,
309-
frames,
310-
}}
311-
stackView={StackView.APP}
312-
inlined
313-
maxDepth={MAX_STACK_DEPTH}
314-
/>
305+
{organization.features.includes('issue-details-new-stack-trace') ? (
306+
<StackTraceViewStateProvider platform={event.platform || 'other'}>
307+
<StackTraceProvider
308+
event={processedEvent}
309+
stacktrace={{
310+
framesOmitted: null,
311+
hasSystemFrames: false,
312+
registers: null,
313+
frames,
314+
}}
315+
maxDepth={MAX_STACK_DEPTH}
316+
>
317+
<StackTraceFrames borderless frameContextComponent={FrameContent} />
318+
</StackTraceProvider>
319+
</StackTraceViewStateProvider>
320+
) : (
321+
<StackTraceContent
322+
event={processedEvent}
323+
newestFirst
324+
platform={event.platform || 'other'}
325+
stacktrace={{
326+
framesOmitted: null,
327+
hasSystemFrames: false,
328+
registers: null,
329+
frames,
330+
}}
331+
stackView={StackView.APP}
332+
inlined
333+
maxDepth={MAX_STACK_DEPTH}
334+
/>
335+
)}
315336
</SpanContainer>
316337
);
317338
}

static/app/components/stackTrace/getRows.spec.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ describe('stackTrace rows utils', () => {
7878
frameCountMap,
7979
newestFirst: false,
8080
framesOmitted: null,
81-
maxDepth: undefined,
8281
});
8382

8483
expect(rows).toHaveLength(4);
@@ -108,7 +107,6 @@ describe('stackTrace rows utils', () => {
108107
frameCountMap: getFrameCountMap(frames, true),
109108
newestFirst: false,
110109
framesOmitted: null,
111-
maxDepth: undefined,
112110
});
113111

114112
expect(rows).toHaveLength(2);
@@ -130,7 +128,6 @@ describe('stackTrace rows utils', () => {
130128
frameCountMap: getFrameCountMap(frames, true),
131129
newestFirst: false,
132130
framesOmitted: [1, 3],
133-
maxDepth: undefined,
134131
});
135132

136133
expect(rowsWithOmitted.some(row => row.kind === 'omitted')).toBe(true);

static/app/components/stackTrace/getRows.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ export function getRows({
116116
framesOmitted: [number, number] | null | undefined;
117117
hiddenFrameToggleMap: Record<number, boolean>;
118118
includeSystemFrames: boolean;
119-
maxDepth: number | undefined;
120119
newestFirst: boolean;
120+
maxDepth?: number;
121121
}): Row[] {
122122
const hiddenFrameIndices = getHiddenFrameIndices({
123123
frames,

static/app/components/stackTrace/stackTrace.spec.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,46 @@ describe('Core StackTrace', () => {
812812
expect(screen.getByText('abc123')).toBeInTheDocument();
813813
});
814814

815+
it('shows in-app frames with maxDepth even when system frames outnumber them', async () => {
816+
const {event, stacktrace} = makeStackTraceData();
817+
const frame = stacktrace.frames[stacktrace.frames.length - 1]!;
818+
819+
// 2 in-app frames followed by 10 system frames — the in-app frames are
820+
// near the start, so a naive maxDepth slice on all frames would miss them.
821+
const appFrames = Array.from({length: 2}, (_, i) => ({
822+
...frame,
823+
inApp: true,
824+
function: `app_fn_${i}`,
825+
lineNo: i + 1,
826+
instructionAddr: `0xA${i}`,
827+
}));
828+
const systemFrames = Array.from({length: 10}, (_, i) => ({
829+
...frame,
830+
inApp: false,
831+
function: `system_fn_${i}`,
832+
lineNo: i + 100,
833+
instructionAddr: `0xS${i}`,
834+
}));
835+
836+
render(
837+
<TestStackTraceProvider
838+
event={event}
839+
stacktrace={{
840+
...stacktrace,
841+
frames: [...appFrames, ...systemFrames],
842+
}}
843+
maxDepth={4}
844+
>
845+
<StackTraceFrames frameContextComponent={FrameContent} />
846+
</TestStackTraceProvider>
847+
);
848+
849+
const rows = await screen.findAllByTestId('core-stacktrace-frame-row');
850+
expect(rows.length).toBeGreaterThanOrEqual(2);
851+
expect(screen.getByText('app_fn_0')).toBeInTheDocument();
852+
expect(screen.getByText('app_fn_1')).toBeInTheDocument();
853+
});
854+
815855
it('renders empty source notation for single frame with no details', async () => {
816856
const {event, stacktrace} = makeStackTraceData();
817857
const frame = stacktrace.frames[stacktrace.frames.length - 1]!;

static/app/components/stackTrace/stackTraceProvider.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,8 @@ export function StackTraceProvider({
6666
frameCountMap: {},
6767
newestFirst: isNewestFirst,
6868
framesOmitted: activeStacktrace.framesOmitted,
69-
maxDepth,
7069
}),
71-
[frames, isNewestFirst, activeStacktrace.framesOmitted, maxDepth]
70+
[frames, isNewestFirst, activeStacktrace.framesOmitted]
7271
);
7372

7473
const rows = useMemo(

0 commit comments

Comments
 (0)