Skip to content

feat(issues): New stack trace component#109428

Merged
scttcper merged 76 commits intomasterfrom
scttcper/new-stack-trace
Mar 24, 2026
Merged

feat(issues): New stack trace component#109428
scttcper merged 76 commits intomasterfrom
scttcper/new-stack-trace

Conversation

@scttcper
Copy link
Copy Markdown
Member

@scttcper scttcper commented Feb 26, 2026

New stack trace component (non-native):

  • no longer uses a mix of emotion and global styles
  • stories for many of the complex states
  • A few contexts instead of prop drilling
  • Frame content does not render until opened, speeding up issue details render speed on large 100+ frame stack traces.
  • The regular opportunities that show up when re-writting, like using our components
  • Styles are no longer shared with native frames which has made them historically difficult to touch, since you had to look at the variations of regular errors and native errors.

Components are now broken into IssueStackTrace and StackTrace. All fetch requests happen in IssueStackTrace and StackTrace components are somewhat designed to be compostable. It got tricky in there.

stories - https://sentry-9kfjix4ca.sentry.dev/stories/product/components/stacktrace/stacktrace/

- handles long filenames by wrapping to two lines
- handles mobile screen sizes a little better
- has two contexts instead of prop drilling
- does not use global styles
@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Feb 26, 2026
Move frame context and variables rendering further onto layout/text primitives
and wire frame context regions to chevron controls for better semantics.

Avoid work for collapsed frames by gating source context/highlighting inputs
behind expansion state.

Add keyboard-focused tests for chevron Enter/Space behavior and aria wiring.

Co-Authored-By: Claude <[email protected]>
Extract frame context and variables rendering into reusable stacktrace units and tighten header/layout interactions for the new component API.

Add a coverage host that uses React Query query options and query cache, fetching coverage only for expanded frames while keeping the base StackTrace component data-source agnostic.
Fix Core StackTrace spec failures by adding default stacktrace-link mocks, making badge assertions resilient, and using explicit space key events for chevron keyboard behavior.

Also remove unused stacktrace exports and simplify coverage query eligibility checks without changing behavior.
scttcper and others added 16 commits February 27, 2026 13:59
Lift toolbar view state (view, isNewestFirst, isMinified) out of
per-exception StackTraceProviders into a single
StackTraceSharedViewContext. ChainedStackTrace now renders one
toolbar above all exceptions so switching App/Full/Raw or toggling
order affects all frames simultaneously.

- Add StackTraceSharedViewContext + StackTraceSharedViewProvider
- StackTraceProvider.Root falls back to local state when no shared
  context is present (existing single-trace usage unchanged)
- Toolbar sub-components read shared context first, then per-provider
  context, enabling standalone use in StackTraceSharedViewProvider

Co-Authored-By: Claude <[email protected]>
mix-blend-mode: screen washed out coverage colors to near-white when
blending against background.secondary (a light gray). The old component
used var(--prism-highlight-background) which is dark enough for screen
blending to produce visible results.

Since FrameSourceLineNumber is a grid cell, its background already covers
the row highlight naturally — no blending is needed. Remove mix-blend-mode
and apply coverage colors directly, using the 200-level shades for active
lines to distinguish from the 100-level shades on inactive lines.

Co-Authored-By: Claude <[email protected]>
Pull all frame actions (chevron, source link, source maps debugger,
hidden frames toggle) out of the monolithic FrameHeader into individual
files under frame/actions/, mirroring the toolbar/ pattern.

Expose them via StackTraceProvider.Frame.Actions.* so consumers can
compose exactly the actions they need. FrameHeader gains an `actions`
prop — when omitted it renders the same default set as before, so
all existing usage is unchanged.

Also extracts toolbar items (DisplayOptions, CopyButton, DownloadButton)
into toolbar/, adds ExceptionHeader as a standalone composable component,
and isolates hover state into a separate StackTraceFrameHoverContext so
only action components re-render on hover rather than the full frame tree.

Co-Authored-By: Claude <[email protected]>
…ckTrace

Replace the standalone ChainedStackTrace component with IssueStackTrace,
a single cohesive component that handles both single and chained exceptions.
IssueStackTrace owns the InterimSection chrome (title, actions in header)
for both cases and provides a CopyButton that concatenates all stacktraces
in the chained case.

Move SharedViewRoot out of stackTraceProvider into issueStackTrace so the
provider stays a pure generic component with no knowledge of the issues
layer. Remove StackTraceSharedViewProvider export entirely.

Co-Authored-By: Claude <[email protected]>
Remove lockAddress and threadId from the generic StackTraceProvider
context. These were ANR-specific concerns leaking into a generic
component.

Replace with a frameBadge render prop that lets callers inject
per-frame badges without the provider knowing about ANR. IssueStackTrace
now owns the ANR detection logic and passes a frameBadge callback that
computes the Suspect Frame badge for qualifying frames.

Also fixes the coverage line number aria-label for accessibility.

Co-Authored-By: Claude <[email protected]>
…x minified story

- Document all StackTraceProviderProps with JSDoc comments
- Rename Display Options toggle from "Unsymbolicated" to "Minified" to
  match the internal value name and be more discoverable
- Update the minified story to use StackTraceProvider directly with
  defaultIsMinified so the feature is visible on load

Co-Authored-By: Claude <[email protected]>
Introduce a dedicated view-state provider and require stack-trace consumers to
read from a single context source to remove cross-context fallbacks. Replace
hover context with explicit props, tighten shared type contracts, and document
context field guarantees so stack-trace APIs are easier to reason about.

Co-Authored-By: Claude <[email protected]>
Made-with: Cursor
Move frame expansion state out of shared stacktrace context so toggling one frame
updates only per-row consumers. Also hoist project lookup to provider scope and use
set-based index membership in row building to cut repeated per-frame work.

Co-Authored-By: Claude <[email protected]>
Made-with: Cursor
Restore StackTraceProvider.Frame to its public row-based API so composed frame
stories compile without internal expansion props. Also remove a dead nullable
context check in DownloadButton and align minifiedStacktrace docs with the new
view-state provider model.

Co-Authored-By: Claude <[email protected]>
Made-with: Cursor
Split frame rendering and default actions into dedicated stack trace modules
and update the frame header to rely on CSS truncation with selectable inline
text. This keeps path suffixes visible, improves copy/paste behavior, and
stabilizes single-line and wrapped alignment.

Co-Authored-By: Claude <[email protected]>
Made-with: Cursor
Use shared Text primitives and simplify inline metadata wrappers so the
frame title row keeps consistent spacing and baseline alignment.

Co-Authored-By: Claude <[email protected]>
Made-with: Cursor
scttcper and others added 2 commits March 5, 2026 14:02
Render chevrons as non-interactive indicators and reserve slot width only when
visible rows include expandable frames. Keep action columns aligned across mixed
rows and add a Storybook example to verify the behavior quickly.

Co-Authored-By: Claude <[email protected]>
Made-with: Cursor
# Conflicts:
#	static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsx
Copy link
Copy Markdown
Member

@malwilley malwilley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits and questions but overall looks good 👍

* Default trailing actions rendered for every frame row:
* hidden-frames toggle, repeated-frame badge, in-app badge, and chevron.
*/
export function DefaultFrameActions({isHovering: _isHovering}: DefaultFrameActionsProps) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this unused prop?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this barrel file? I thought we were against them

border-radius: 0;

&& {
white-space: pre-wrap;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is necessary because we have some styles in the less files?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah seems like there's a code[class*='language-'] in global

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The context definitely makes things so much nicer to work with


// Lazy: track frames that have ever been visible so we only mount on first appearance.
// A ref is sufficient — the component already re-renders when `rows` changes.
const everVisibleRef = useRef(new Set<number>());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this used before or is this a new performance optimization?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its new, i wanted to make them only render after being opened but its a little annoying that everything loses state when you toggle the frames open/close so there's this ref that preserves the state using react 19's activity https://react.dev/reference/react/Activity

might be overcomplicated

@scttcper scttcper requested a review from a team as a code owner March 23, 2026 18:13
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Mar 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

scttcper and others added 3 commits March 24, 2026 11:40
Replace rest-spread destructuring of the discriminated union props with
direct narrowing on the props object, so TypeScript properly resolves
values as ExceptionValue[] and stacktrace as StacktraceType in each
branch. Remove the now-unused isStandaloneProps helper.

Add EntryMap mapped type that maps each EntryType to its corresponding
Entry subtype. Use it in eventEntries so lookups like
eventEntries[EntryType.EXCEPTION].data.values resolve to
ExceptionValue[] | undefined instead of any.

Move the raw view early return above the single-exception branch so
raw rendering is handled uniformly regardless of exception count.
Add test covering raw view for single exceptions and type-level
assertions for the component props.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@scttcper scttcper merged commit b4db717 into master Mar 24, 2026
64 checks passed
@scttcper scttcper deleted the scttcper/new-stack-trace branch March 24, 2026 20:24
Asynchronite pushed a commit to Asynchronite/sentry that referenced this pull request Mar 24, 2026
New stack trace component (non-native):
- no longer uses a mix of emotion and global styles
- [stories for many of the complex
states](https://sentry-9kfjix4ca.sentry.dev/stories/product/components/stacktrace/stacktrace/)
- A few contexts instead of prop drilling
- Frame content does not render until opened, speeding up issue details
render speed on large 100+ frame stack traces.
- The regular opportunities that show up when re-writting, like using
our <Grid> <Flex> components
- Styles are no longer shared with native frames which has made them
historically difficult to touch, since you had to look at the variations
of regular errors and native errors.

Components are now broken into IssueStackTrace and StackTrace. **All
fetch requests** happen in IssueStackTrace and StackTrace components are
somewhat designed to be compostable. It got tricky in there.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants