Skip to content

Conversation

@supervacuus
Copy link
Collaborator

@supervacuus supervacuus commented Jun 10, 2025

With the recently introduced support for traces without performance (TwP) and how they interact with performance-related traces, we broke with an undocumented assumption: there should be no endless traces.

Endless traces would have consequences for the visualization in the web UI as well as sampling decisions, as we'd like to introduce in #1254 (where events/transactions along a single trace should follow the same dice roll, to obtain complete traces).

Since all events inherit their traces from the propagation context, which the SDK initializes with a random trace and dummy span, this trace would be active forever. When sentry_set_trace() is used (either by the user directly or in a downstream SDK), this also means that the caller assumes the burden of managing the trace life-cycle. However, if this doesn't happen, it is the Native SDK's duty.

After a short discussion during last week's sync, we established transactions as a boundary that breaks traces (leaving the question open of what happens without performance, which I tried to address in the comments).

Related docs PR: getsentry/sentry-docs#14586

@github-actions
Copy link

github-actions bot commented Jun 10, 2025

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 0b5a79b

@supervacuus supervacuus force-pushed the feat/manage_trace_length branch from c06cdd8 to 8542e8d Compare June 12, 2025 17:46
@supervacuus
Copy link
Collaborator Author

This change is no longer relevant, since traces can now have arbitrary length.

Summary of the quick discussion we had about this: if this ever comes up again, then the right choice parameterization is to define the number of captures until a trace is invalidated.

@JoshuaMoelans
Copy link
Member

JoshuaMoelans commented Aug 4, 2025

After a chat with @cleptric , we actually do want Transactions to be the default trace boundary in the native SDK.

The idea of having multiple transactions in one trace only holds for platforms where there actually are specific trace-boundaries (e.g. mobile screen load, web page load, unity scene load, ...). This is not the case for Native, hence we reopen this PR to be merged before release 0.10.0.

+ I think we can still keep the manual trace boundary API around for Tracing Without Performance (e.g. for a custom boundary between events/logs/...). Other SDKs solve this by still having pageloads/screenloads/requests/... start a new trace, but in native we don't have a boundary like this. If people want to avoid an unending trace with millions of manual event captures/logs in a TwP setting, they should be using the manual trace boundary API.

This page needs an updated graphic; although the behaviour post-set-trace remains unchanged, it could use an example of how a new transaction without an incoming trace changes the trace_id https://develop.sentry.dev/sdk/platform-specifics/native-sdks/tracing/

@JoshuaMoelans
Copy link
Member

JoshuaMoelans commented Aug 5, 2025

Visualizations

To better understand the flow of the trace_id, I created the visualizations below.

General Flow
graph TD
    A[SDK Init] --> B[trace_managed = true]
    B --> C[Create Transaction Context]
    C --> D{trace_managed?}
    D -->|true| E[Generate Fresh Trace ID]
    D -->|false| F
    E --> F[Create Transaction]
    F --> G[Send Event During Transaction]
    G --> H{Transaction Scoped?}
    H -->|Yes| I[Event uses Transaction Trace]
    H -->|No| J[Event uses Propagation Context]
    I --> K[Finish Transaction]
    J --> K
    K --> L{trace_managed?}
    L -->|true| M[Update Propagation Context<br/>with Transaction Trace ID]
    L -->|false| N[Keep Propagation Context<br/>as it is]


    style E fill:#49516e
    style I fill:#256332
    style M fill:#c98530
Loading
Start(t:a) → Tx_s(t:b) → E(t:a) → Tx_e(t:b) → E(t:b)
flowchart TD
    A["SDK Init<br/>🏁 Start(t:a)<br/>Propagation Context: trace_id = 'a'"] --> B["Transaction Start<br/>🚀 Tx_s(t:b)<br/>Fresh trace_id = 'b'<br/>(NOT scoped)"]

    B --> C{"Transaction<br/>Scoped?"}
    C -->|No| D["Event Captured<br/>📧 E(t:a)<br/>Uses Propagation Context<br/>trace_id = 'a'"]

    D --> E["Transaction Finish<br/>🏁 Tx_e(t:b)<br/>Updates Propagation Context<br/>trace_id = 'a' → 'b'"]

    E --> F["Event Captured<br/>📧 E(t:b)<br/>Uses Updated Propagation Context<br/>trace_id = 'b'"]

    C -->|Yes| G["Event would use<br/>Transaction trace 'b'<br/>(Alternative path)"]

        style A fill:#2e4e2e,color:#ffffff
    style B fill:#4a3728,color:#ffffff
    style D fill:#4a2c2c,color:#ffffff
    style E fill:#1e3a5f,color:#ffffff
    style F fill:#2d4a2d,color:#ffffff
    style G fill:#3d2a3d,color:#ffffff,stroke-dasharray: 5 5
    
    classDef traceA fill:#5a2d2d,stroke:#ff6b6b,stroke-width:2px,color:#ffffff
    classDef traceB fill:#2d4a2d,stroke:#69db7c,stroke-width:2px,color:#ffffff

    class A,D traceA
    class B,E,F traceB
Loading

Copy link
Member

@JoshuaMoelans JoshuaMoelans left a comment

Choose a reason for hiding this comment

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

LGTM; only needs fixing the one 'alternative' if 0 path.

Copy link
Member

@JoshuaMoelans JoshuaMoelans left a comment

Choose a reason for hiding this comment

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

LGTM, just very minor nit on a typo

cursor[bot]

This comment was marked as outdated.

sentry_value_set_by_key(
sentry_value_get_by_key(scope->propagation_context, "trace"),
"trace_id", txn_trace_id);
}
Copy link

Choose a reason for hiding this comment

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

Bug: Trace Context Inconsistency After Transaction

When a transaction finishes and the SDK manages the trace, the propagation context's trace_id is updated to match the finished transaction, but its parent_span_id and span_id are not. This creates an inconsistent trace context where the trace_id is new but the span_id and parent_span_id are from the old context, breaking the trace hierarchy for subsequent events and violating span ID uniqueness.

Fix in Cursor Fix in Web

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That is intentional until further specification counters the decision. From our current POV, only the trace_id should be changed, and the dummy hierarchy created during initialization can survive without compromising the effect of a trace boundary. I raised this topic during development and this resulted in the current decision. We can change this anytime.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

// TODO: what should we do with the span_id in the
// propagation_context? We can't use the transaction's, because we
// want to be outside the transaction's span hierarchy. Could we
// just keep the initially created dummy or should generate a new
// one?

@supervacuus supervacuus merged commit 6466da9 into master Aug 8, 2025
87 of 93 checks passed
@supervacuus supervacuus deleted the feat/manage_trace_length branch August 8, 2025 10:24
supervacuus added a commit to getsentry/sentry-docs that referenced this pull request Aug 8, 2025
This PR adds documentation for the behavior introduced in
getsentry/sentry-native#1270.

This PR should be merged/deployed after the Native SDK release `0.10.0`.

## IS YOUR CHANGE URGENT?  

Help us prioritize incoming PRs by letting us know when the change needs
to go live.
- [ ] Urgent deadline (GA date, etc.): <!-- ENTER DATE HERE -->
- [ ] Other deadline: <!-- ENTER DATE HERE -->
- [x] None: Not urgent, can wait up to 1 week+

## SLA

- Teamwork makes the dream work, so please add a reviewer to your PRs.
- Please give the docs team up to 1 week to review your PR unless you've
added an urgent due date to it.
Thanks in advance for your help!

## PRE-MERGE CHECKLIST

*Make sure you've checked the following before merging your changes:*

- [ ] Checked Vercel preview for correctness, including links
- [ ] PR was reviewed and approved by any necessary SMEs (subject matter
experts)
- [ ] PR was reviewed and approved by a member of the [Sentry docs
team](https://github.com/orgs/getsentry/teams/docs)

## EXTRA RESOURCES

- [Sentry Docs contributor guide](https://docs.sentry.io/contributing/)

---------

Co-authored-by: JoshuaMoelans <[email protected]>
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.

3 participants