Tracing
In the Native SDK we have the following scenarios, showcasing how trace-context data flows:
In Tracing without Performance (TwP) the SDK does not create spans. However, we still want to connect events across boundaries so we use a propagation_context to store the relevant data (a trace_id and a span_id) which gets generated during SDK initialization. This propagation_context can be updated by calling sentry_set_trace(), for example from a downstream SDK.
When any traces sampling option is enabled, the SDK can send spans. Just like in TwP, we still use a propagation_context to store the relevant data (a trace_id and a span_id). Now, events and spans can be connected through a common trace_id and, if a span is scoped, it will additionally be connected hierarchically to the event through its span_id. By default, both spans and events will inherit the trace_id from the propagation_context as generated during SDK initialization.
Independent of whether tracing is used with or without performance, downstream SDKs can use sentry_set_trace() to continue their traces in the Native SDK. This function updates the propagation_context with a new trace_id, span_id, and parent_span_id.
Root spans (=transactions) will inherit the trace context from the propagation_context during the transaction context creation, but introduce a new span layer. If users want to override the SDK-established traces with their external traces, this context can be overwritten by using sentry_transaction_context_update_from_header(). All of this happens before transaction creation or scoping.
Child spans will then inherit the trace data from their parent. As long as a span is scoped, any event will use that span's trace context. If no spans are scoped, events will use the trace data from the propagation_context directly.
The flow of the trace context (via the propagation_context) can be visualized for the following scenarios:
- The SDK initializes
propagation_contextwith atrace_idandspan_id. The event sent will use this data. - The SDK initializes
propagation_contextwith atrace_idandspan_id, which gets overwritten bysentry_set_trace(). The event sent will use this updated data. - The SDK initializes
propagation_contextwith atrace_idandspan_id, which gets overwritten bysentry_set_trace(). The event sent will use this updated data.
Now, a transaction context is created, which uses thepropagation_contextdata.
Since the transaction is started and scoped, any event sent while it is scoped will use the transaction's data (which has the sametrace_idas thepropagation_context, but its ownspan_id). - The SDK initializes
propagation_contextwith atrace_idandspan_id, which gets overwritten bysentry_set_trace(). The event sent will use this updated data.
Now, a transaction context is created, which uses thepropagation_contextdata.
Since the transaction is started and not scoped, any event sent will use thepropagation_contextdata. The transaction and event will still have the sametrace_id, but differentspan_ids. - The SDK initializes
propagation_contextwith atrace_idandspan_id, which gets overwritten bysentry_set_trace(). The event sent will use this updated data.
Now, a transaction context is created, which uses thepropagation_contextdata. It gets updated bysentry_transaction_context_update_from_header()before starting the transaction, setting a newtrace_id.
Since the transaction is started and scoped, any event sent while it is scoped will use the transaction's data, which now differs from thepropagation_contextdata.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").