diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dfb58306..522c97bb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ **Features**: - Add `sentry_clear_attachments()` to allow clearing all previously added attachments in the global scope. ([#1290](https://github.com/getsentry/sentry-native/pull/1290)) +- Provide `sentry_regenerate_trace()` to allow users to set manual trace boundaries. ([#1293](https://github.com/getsentry/sentry-native/pull/1293)) ## 0.9.1 diff --git a/include/sentry.h b/include/sentry.h index 34af7b44a..66e4a5c5f 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -1690,13 +1690,20 @@ SENTRY_API void sentry_remove_fingerprint(void); /** * Set the trace. The primary use for this is to allow other SDKs to propagate - * their trace context to connect events on all layers + * their trace context to connect events on all layers. */ SENTRY_API void sentry_set_trace( const char *trace_id, const char *parent_span_id); SENTRY_API void sentry_set_trace_n(const char *trace_id, size_t trace_id_len, const char *parent_span_id, size_t parent_span_id_len); +/** + * Generates a new random `trace_id` and `span_id` and sets these onto + * the propagation context. Use this to set a trace boundary for + * events/transactions. + */ +SENTRY_EXPERIMENTAL_API void sentry_regenerate_trace(void); + /** * Sets the transaction. */ diff --git a/src/sentry_core.c b/src/sentry_core.c index e31b63110..c8e90953d 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -94,17 +94,17 @@ sentry__should_skip_upload(void) } static void -initialize_propagation_context(sentry_value_t *propagation_context) +generate_propagation_context(sentry_value_t propagation_context) { sentry_value_set_by_key( - *propagation_context, "trace", sentry_value_new_object()); + propagation_context, "trace", sentry_value_new_object()); sentry_uuid_t trace_id = sentry_uuid_new_v4(); sentry_uuid_t span_id = sentry_uuid_new_v4(); sentry_value_set_by_key( - sentry_value_get_by_key(*propagation_context, "trace"), "trace_id", + sentry_value_get_by_key(propagation_context, "trace"), "trace_id", sentry__value_new_internal_uuid(&trace_id)); sentry_value_set_by_key( - sentry_value_get_by_key(*propagation_context, "trace"), "span_id", + sentry_value_get_by_key(propagation_context, "trace"), "span_id", sentry__value_new_span_uuid(&span_id)); } @@ -211,7 +211,7 @@ sentry_init(sentry_options_t *options) sentry_value_set_by_key(scope->client_sdk, "name", sdk_name); } sentry_value_freeze(scope->client_sdk); - initialize_propagation_context(&scope->propagation_context); + generate_propagation_context(scope->propagation_context); scope->attachments = options->attachments; options->attachments = NULL; } @@ -928,6 +928,14 @@ sentry_set_trace_n(const char *trace_id, size_t trace_id_len, } } +void +sentry_regenerate_trace(void) +{ + SENTRY_WITH_SCOPE_MUT (scope) { + generate_propagation_context(scope->propagation_context); + } +} + void sentry_set_transaction(const char *transaction) { diff --git a/tests/unit/test_tracing.c b/tests/unit/test_tracing.c index cecba0c67..7a4dd54dd 100644 --- a/tests/unit/test_tracing.c +++ b/tests/unit/test_tracing.c @@ -1693,8 +1693,8 @@ SENTRY_TEST(propagation_context_init) = sentry_transaction_start_child(tx, "op", "desc"); TEST_ASSERT(!!span_child); - const char *propagation_context_trace_id = sentry_value_as_string( - sentry_value_get_by_key(tx->inner, "trace_id")); + char *propagation_context_trace_id = sentry__string_clone( + sentry_value_as_string(sentry_value_get_by_key(tx->inner, "trace_id"))); TEST_ASSERT(!!propagation_context_trace_id); // on SDK init, propagation_context is set with a trace_id and span_id // the trace_id is used for both events and spans @@ -1703,6 +1703,28 @@ SENTRY_TEST(propagation_context_init) sentry_span_finish(span_child); sentry_transaction_finish(tx); + + // now generate a new trace which should be different from before + sentry_regenerate_trace(); + sentry_transaction_context_t *tx_ctx_2 + = sentry_transaction_context_new("wow!", NULL); + TEST_ASSERT(!!tx_ctx_2); + sentry_transaction_t *tx_2 + = sentry_transaction_start(tx_ctx_2, sentry_value_new_null()); + TEST_ASSERT(!!tx_2); + const char *new_propagation_context_trace_id = sentry_value_as_string( + sentry_value_get_by_key(tx_2->inner, "trace_id")); + apply_scope_and_check_trace_context( + options, new_propagation_context_trace_id, ""); + // ensure different trace_id before and after generate_trace() + TEST_ASSERT( + strcmp(propagation_context_trace_id, new_propagation_context_trace_id) + != 0); + + sentry_free(propagation_context_trace_id); + + sentry_transaction_finish(tx_2); + sentry_close(); }