Skip to content

Align and flesh out trace propagation API #2050

Description

@limbonaut

The trace propagation spec's Public API section wants three methods: continue_trace, get_trace_data, and start_new_trace (naming can vary). Native already has most of the underlying behavior, but only the trace reset API is directly reachable from public.

continue_trace is not provided without starting a transaction.
sentry_transaction_context_update_from_header() already parses sentry-trace and baggage and checks sentry-org_id for strict continuation, but it writes into a transaction context and is only applied by the transaction-start path. The spec requires a public continuation API that updates trace propagation state directly and MUST NOT create a segment span (aka transaction or topmost span).

The method MUST NOT create a new segment span on its own.

get_trace_data is not provided without an active span.
sentry_span_iter_headers() and sentry_transaction_iter_headers() both require a live span or transaction. Similar gap as in the previous issue.

start_new_trace exists as sentry_regenerate_trace().
Already correct. Consider renaming for clarity.

Without spans there is no way to propagate a trace at all. The spec says an SDK with no traces_sample_rate must still continue incoming traces and send sentry-trace and baggage (default propagation), and deferred sampling describes what to send when no span is available.

Proposal

I marked API that we need in the Godot SDK with // [G].

// New API for continuing a trace from headers.
SENTRY_API void sentry_continue_trace(
    const char *sentry_trace, const char *baggage); // [G]
SENTRY_API void sentry_continue_trace_n(
    const char *sentry_trace, size_t sentry_trace_len,
    const char *baggage, size_t baggage_len);
// Same, for a given scope, so concurrent units of work can hold distinct traces.
SENTRY_API void sentry_scope_continue_trace(sentry_scope_t *scope,
    const char *sentry_trace, const char *baggage); // [G]
SENTRY_API void sentry_scope_continue_trace_n(sentry_scope_t *scope,
    const char *sentry_trace, size_t sentry_trace_len,
    const char *baggage, size_t baggage_len);

// The missing scope twin of sentry_set_trace.
SENTRY_API void sentry_scope_set_trace(sentry_scope_t *scope,
    const char *trace_id, const char *parent_span_id); // [G]
SENTRY_API void sentry_scope_set_trace_n(sentry_scope_t *scope,
    const char *trace_id, size_t trace_id_len,
    const char *parent_span_id, size_t parent_span_id_len);

// Reads the global scope: its bound span if it has one, otherwise 
// the propagation context.
SENTRY_API void sentry_iter_trace_propagation_headers(
    sentry_iter_headers_function_t callback, void *userdata);
// Same, for a given scope, falling back to the global scope for 
// what it does not set.
SENTRY_API void sentry_scope_iter_trace_propagation_headers(
    const sentry_scope_t *scope,
    sentry_iter_headers_function_t callback, void *userdata); // [G]

// Rename for clarity.
SENTRY_API void sentry_start_new_trace(void);
SENTRY_DEPRECATED("Use `sentry_start_new_trace` instead")
SENTRY_API void sentry_regenerate_trace(void);

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions