Skip to content

feat: add attach_stacktrace option - #2195

Merged
jpnurmi merged 4 commits into
getsentry:masterfrom
Denimworld12:feat/attach-stacktrace
Oct 15, 2026
Merged

jpnurmi merged 4 commits into
getsentry:masterfrom
Denimworld12:feat/attach-stacktrace

Conversation

@Denimworld12

Copy link
Copy Markdown
Contributor

Closes #1097.

A plain sentry_capture_event with a message carries no frames at all, so Sentry has nothing to group those events by except the message text. Two completely different code paths logging "connection failed" end up in the same issue. Every other Sentry SDK has attach_stacktrace for exactly this; the Native SDK was the one without it.

What it does

sentry_options_set_attach_stacktrace(options, 1) makes sentry__capture_event attach the stack trace of the capturing thread as a thread entry on events that don't already have one. It is off by default, so nothing changes unless you ask for it.

The attach happens just before sentry__prepare_event, which is deliberate: the scope pass inside it runs sentry__foreach_stacktrace(event, sentry__symbolize_stacktrace), so the new frames get symbolized along with every other stack trace on the event when symbolize_stacktraces is on. I checked that locally — with symbolization enabled, every frame in the attached trace comes back with a function.

Events that already carry an exception or a threads interface are skipped, so crash events keep the stack the backend captured. Transactions never reach this path, and sentry_capture_minidump calls sentry__prepare_event directly, so a minidump doesn't get the capturing thread's stack bolted onto it.

Two things I'd like your call on

Which events. Right now it applies to every event without a stack trace, which is what the other SDKs do. The issue also floats fatal-only as an option. That's a one-line change if you prefer it — I went with the cross-SDK behaviour as the default rather than guess.

SENTRY_EXPERIMENTAL_API. I put it there rather than SENTRY_API because 1.0 is close and I'd rather not add to the stable surface right before a freeze. #2116 would pick it up later if you want it promoted. Happy to move it if you'd rather it land stable straight away.

One thing worth knowing: the trace starts inside the SDK, so the first few frames are sentry_capture_event and friends. The existing sentry_value_new_stacktrace has the same characteristic and nothing in the tree trims SDK frames today, so I left it alone instead of inventing a trimming rule here.

Tests

Three in test_basic.c — the thread gets attached with current/crashed set and a non-empty frame list, nothing is attached when the option is off, and an event that already has an exception is left alone — plus a set/get test in test_options.c.

make test-unit is green at 613 tests (609 before), and clang-format is clean.

Events captured without an exception or thread stack trace, like plain
messages, carry no frames at all, so Sentry has nothing to group them by
except the message text. Every other Sentry SDK solves this with an
attach_stacktrace option; the Native SDK had no equivalent.

With the option enabled, sentry__capture_event attaches the stack trace of
the capturing thread as a thread entry before the scope is applied, so the
frames are symbolized along with every other stack trace on the event when
symbolize_stacktraces is on. Events that already carry an exception or a
threads interface are left untouched, which keeps crash events as they are.

Closes getsentry#1097
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.53%. Comparing base (d458aed) to head (f384051).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2195      +/-   ##
==========================================
+ Coverage   75.46%   75.53%   +0.07%     
==========================================
  Files         103      103              
  Lines       28220    28242      +22     
  Branches     5170     5174       +4     
==========================================
+ Hits        21297    21334      +37     
+ Misses       5578     5559      -19     
- Partials     1345     1349       +4     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jpnurmi

jpnurmi commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Sorry, I've been a bit busy with the ongoing 1.0 activities. This looks good at first glance! The only thing I was wondering is whether it would be possible to have some simple integration tests?

Which events. Right now it applies to every event without a stack trace, which is what the other SDKs do. The issue also floats fatal-only as an option. That's a one-line change if you prefer it — I went with the cross-SDK behaviour as the default rather than guess.

Following the same conventions as what other SDKs already do is always a good choice 👍

SENTRY_EXPERIMENTAL_API. I put it there rather than SENTRY_API because 1.0 is close and I'd rather not add to the stable surface right before a freeze. #2116 would pick it up later if you want it promoted. Happy to move it if you'd rather it land stable straight away.

I'd be fine either way. Since the same feature/option/API already exists in other SDKs, and it's an opt-in flag, it's highly unlikely to get us in trouble later... 🤔

Adds an attach-stacktrace flag to the integration fixture and three tests
over it: the option attaches a symbolized thread stack trace to a plain
message event, nothing is attached when the option is off, and an event
that already carries an exception stack trace gets no threads entry.

The fixture enables symbolize_stacktraces, so assert_stacktrace also covers
the symbolization of the attached frames end to end.
@Denimworld12

Copy link
Copy Markdown
Contributor Author

No worries, and thanks for looking.

Integration tests added. There's a new attach-stacktrace flag on the fixture and three tests on top of it:

  • the option attaches a thread stack trace to a plain message event
  • nothing is attached when the option is off
  • an event that already has an exception stack trace gets no threads entry

The first one turned out to be worth more than I expected. The fixture already calls sentry_options_set_symbolize_stacktraces(options, true), so assert_stacktrace checks that the attached frames come back with function and package filled in. That covers the part of this I most wanted covered: the attach happens just before sentry__prepare_event, and the scope pass inside it runs the symbolizer over every stack trace on the event, so the new frames go through it like any other. If someone later moves that call after prepare_event, this test fails rather than silently shipping unsymbolized frames.

On the API: I'll leave it experimental for now, if that's alright. #2116 is already the path for promoting these, so experimental-then-promote fits what you're doing anyway, and it's the direction that's easy to reverse — the other way isn't. That said it's a one-line change, so just say the word and I'll flip it.

@jpnurmi jpnurmi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice! 💯 Thank you for yet another contribution! 🙏

@jpnurmi
jpnurmi merged commit d04453d into getsentry:master Oct 15, 2026
62 checks passed
jpnurmi added a commit that referenced this pull request Oct 15, 2026
On Switch, the platform integration supplies a release, enabling
automatic session tracking. `sentry_close()` then sends a session
envelope in addition to the event expected by the tests added in #2195.
Their callback counts this envelope and replaces the saved `threads`
with null, failing all three capture tests.

Disable automatic session tracking in their shared setup, matching the
neighboring capture tests.

Introduced by:
#2195

Failed CI job:
https://github.com/getsentry/sentry-switch/actions/runs/38732357928/job/116426400577
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add option attach_stacktrace

2 participants