diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eaef44af..496418d67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Add `sentry_set_tags` and `sentry_scope_set_tags` for updating multiple tags with a single scope flush, improving bulk-update performance. ([#1993](https://github.com/getsentry/sentry-native/pull/1993)) - Add `sentry_get_last_event_id` and `sentry_scope_get_last_event_id` for retrieving the last event ID captured with the global or given scope, respectively. ([#1992](https://github.com/getsentry/sentry-native/pull/1992)) - Native/Unix: The native crash daemon now loads `libcurl` dynamically at runtime by default when `SENTRY_LINK_CURL=AUTO`, avoiding `libcurl` linker work during process startup and significantly speeding up startup time. Explicitly set `SENTRY_LINK_CURL=ON` to link it directly. ([#1955](https://github.com/getsentry/sentry-native/pull/1955)) +- Add missing public scope mutators: `set_release`, `set_environment`, `set_transaction`, `remove_tag`, `remove_extra`, `remove_context`, and `remove_attachment`. ([#2011](https://github.com/getsentry/sentry-native/pull/2011)) **Deprecations**: diff --git a/include/sentry.h b/include/sentry.h index 5e2cb5155..e657c4a6e 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -2540,6 +2540,10 @@ SENTRY_API void sentry_remove_user(void); */ SENTRY_API void sentry_set_release(const char *release); SENTRY_API void sentry_set_release_n(const char *release, size_t release_len); +SENTRY_API void sentry_scope_set_release( + sentry_scope_t *scope, const char *release); +SENTRY_API void sentry_scope_set_release_n( + sentry_scope_t *scope, const char *release, size_t release_len); /** * Sets the environment after the SDK has been initialized. To apply the new @@ -2548,6 +2552,10 @@ SENTRY_API void sentry_set_release_n(const char *release, size_t release_len); SENTRY_API void sentry_set_environment(const char *environment); SENTRY_API void sentry_set_environment_n( const char *environment, size_t environment_len); +SENTRY_API void sentry_scope_set_environment( + sentry_scope_t *scope, const char *environment); +SENTRY_API void sentry_scope_set_environment_n( + sentry_scope_t *scope, const char *environment, size_t environment_len); /** * Sets a tag. @@ -2575,6 +2583,9 @@ SENTRY_API void sentry_scope_set_tags( */ SENTRY_API void sentry_remove_tag(const char *key); SENTRY_API void sentry_remove_tag_n(const char *key, size_t key_len); +SENTRY_API void sentry_scope_remove_tag(sentry_scope_t *scope, const char *key); +SENTRY_API void sentry_scope_remove_tag_n( + sentry_scope_t *scope, const char *key, size_t key_len); /** * Sets extra information. @@ -2592,6 +2603,10 @@ SENTRY_API void sentry_scope_set_extra_n(sentry_scope_t *scope, const char *key, */ SENTRY_API void sentry_remove_extra(const char *key); SENTRY_API void sentry_remove_extra_n(const char *key, size_t key_len); +SENTRY_API void sentry_scope_remove_extra( + sentry_scope_t *scope, const char *key); +SENTRY_API void sentry_scope_remove_extra_n( + sentry_scope_t *scope, const char *key, size_t key_len); /** * Sets attributes created with `sentry_value_new_attribute` to be applied to @@ -2649,6 +2664,10 @@ SENTRY_API void sentry_scope_update_context_n(sentry_scope_t *scope, */ SENTRY_API void sentry_remove_context(const char *key); SENTRY_API void sentry_remove_context_n(const char *key, size_t key_len); +SENTRY_API void sentry_scope_remove_context( + sentry_scope_t *scope, const char *key); +SENTRY_API void sentry_scope_remove_context_n( + sentry_scope_t *scope, const char *key, size_t key_len); /** * Sets the event fingerprint. @@ -2712,6 +2731,10 @@ SENTRY_EXPERIMENTAL_API void sentry_regenerate_trace(void); SENTRY_API void sentry_set_transaction(const char *transaction); SENTRY_API void sentry_set_transaction_n( const char *transaction, size_t transaction_len); +SENTRY_API void sentry_scope_set_transaction( + sentry_scope_t *scope, const char *transaction); +SENTRY_API void sentry_scope_set_transaction_n( + sentry_scope_t *scope, const char *transaction, size_t transaction_len); /** * Sets the event level. @@ -3242,7 +3265,8 @@ typedef struct sentry_attachment_s sentry_attachment_t; * * The returned `sentry_attachment_t` is owned by the SDK and will remain valid * until the attachment is removed with `sentry_remove_attachment` or - * `sentry_close` is called. + * `sentry_scope_remove_attachment`, or its owning scope is freed with + * `sentry_scope_free` or `sentry_close`. * * See the NOTE on attachments above for restrictions of this API. */ @@ -3274,7 +3298,8 @@ SENTRY_API sentry_attachment_t *sentry_scope_attach_file_n( * * The returned `sentry_attachment_t` is owned by the SDK and will remain valid * until the attachment is removed with `sentry_remove_attachment` or - * `sentry_close` is called. + * `sentry_scope_remove_attachment`, or its owning scope is freed with + * `sentry_scope_free` or `sentry_close`. * * See the NOTE on attachments above for restrictions of this API. */ @@ -3299,6 +3324,8 @@ SENTRY_API void sentry_clear_attachments(void); * See the NOTE on attachments above for restrictions of this API. */ SENTRY_API void sentry_remove_attachment(sentry_attachment_t *attachment); +SENTRY_API void sentry_scope_remove_attachment( + sentry_scope_t *scope, sentry_attachment_t *attachment); #ifdef SENTRY_PLATFORM_WINDOWS /** diff --git a/src/sentry_core.c b/src/sentry_core.c index b87e36c59..09d870aed 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -983,11 +983,7 @@ void sentry_set_release_n(const char *release, size_t release_len) { SENTRY_WITH_SCOPE_MUT (scope) { - sentry_free(scope->release); - scope->release = sentry__string_clone_n(release, release_len); - sentry_value_set_by_key(scope->dynamic_sampling_context, "release", - sentry_value_new_string(scope->release)); - SENTRY_SCOPE_NOTIFY(scope, set_release, scope->release); + sentry_scope_set_release_n(scope, release, release_len); } } @@ -1001,12 +997,7 @@ void sentry_set_environment_n(const char *environment, size_t environment_len) { SENTRY_WITH_SCOPE_MUT (scope) { - sentry_free(scope->environment); - scope->environment - = sentry__string_clone_n(environment, environment_len); - sentry_value_set_by_key(scope->dynamic_sampling_context, "environment", - sentry_value_new_string(scope->environment)); - SENTRY_SCOPE_NOTIFY(scope, set_environment, scope->environment); + sentry_scope_set_environment_n(scope, environment, environment_len); } } @@ -1086,9 +1077,7 @@ void sentry_remove_tag(const char *key) { SENTRY_WITH_SCOPE_MUT (scope) { - if (sentry_value_remove_by_key(scope->tags, key) == 0) { - SENTRY_SCOPE_NOTIFY(scope, remove_tag, key); - } + sentry_scope_remove_tag(scope, key); } } @@ -1096,12 +1085,7 @@ void sentry_remove_tag_n(const char *key, size_t key_len) { SENTRY_WITH_SCOPE_MUT (scope) { - char *k - = sentry__value_remove_and_take_key_n(scope->tags, key, key_len); - if (k) { - SENTRY_SCOPE_NOTIFY(scope, remove_tag, k); - } - sentry_free(k); + sentry_scope_remove_tag_n(scope, key, key_len); } } @@ -1125,9 +1109,7 @@ void sentry_remove_extra(const char *key) { SENTRY_WITH_SCOPE_MUT (scope) { - if (sentry_value_remove_by_key(scope->extra, key) == 0) { - SENTRY_SCOPE_NOTIFY(scope, remove_extra, key); - } + sentry_scope_remove_extra(scope, key); } } @@ -1135,12 +1117,7 @@ void sentry_remove_extra_n(const char *key, size_t key_len) { SENTRY_WITH_SCOPE_MUT (scope) { - char *k - = sentry__value_remove_and_take_key_n(scope->extra, key, key_len); - if (k) { - SENTRY_SCOPE_NOTIFY(scope, remove_extra, k); - } - sentry_free(k); + sentry_scope_remove_extra_n(scope, key, key_len); } } @@ -1241,9 +1218,7 @@ void sentry_remove_context(const char *key) { SENTRY_WITH_SCOPE_MUT (scope) { - if (sentry_value_remove_by_key(scope->contexts, key) == 0) { - SENTRY_SCOPE_NOTIFY(scope, remove_context, key); - } + sentry_scope_remove_context(scope, key); } } @@ -1251,12 +1226,7 @@ void sentry_remove_context_n(const char *key, size_t key_len) { SENTRY_WITH_SCOPE_MUT (scope) { - char *k = sentry__value_remove_and_take_key_n( - scope->contexts, key, key_len); - if (k) { - SENTRY_SCOPE_NOTIFY(scope, remove_context, k); - } - sentry_free(k); + sentry_scope_remove_context_n(scope, key, key_len); } } @@ -1360,15 +1330,7 @@ void sentry_set_transaction_n(const char *transaction, size_t transaction_len) { SENTRY_WITH_SCOPE_MUT (scope) { - sentry_free(scope->transaction); - scope->transaction - = sentry__string_clone_n(transaction, transaction_len); - - if (scope->transaction_object) { - sentry_transaction_set_name_n( - scope->transaction_object, transaction, transaction_len); - } - SENTRY_SCOPE_NOTIFY(scope, set_transaction, scope->transaction); + sentry_scope_set_transaction_n(scope, transaction, transaction_len); } } diff --git a/src/sentry_scope.c b/src/sentry_scope.c index 0bb7057e1..eef62c09d 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -806,6 +806,25 @@ sentry_scope_set_tags(sentry_scope_t *scope, sentry_value_t tags) sentry_value_decref(tags); } +void +sentry_scope_remove_tag(sentry_scope_t *scope, const char *key) +{ + if (sentry_value_remove_by_key(scope->tags, key) == 0) { + SENTRY_SCOPE_NOTIFY(scope, remove_tag, key); + } +} + +void +sentry_scope_remove_tag_n( + sentry_scope_t *scope, const char *key, size_t key_len) +{ + char *k = sentry__value_remove_and_take_key_n(scope->tags, key, key_len); + if (k) { + SENTRY_SCOPE_NOTIFY(scope, remove_tag, k); + } + sentry_free(k); +} + void sentry_scope_set_extra( sentry_scope_t *scope, const char *key, sentry_value_t value) @@ -825,6 +844,25 @@ sentry_scope_set_extra_n(sentry_scope_t *scope, const char *key, size_t key_len, } } +void +sentry_scope_remove_extra(sentry_scope_t *scope, const char *key) +{ + if (sentry_value_remove_by_key(scope->extra, key) == 0) { + SENTRY_SCOPE_NOTIFY(scope, remove_extra, key); + } +} + +void +sentry_scope_remove_extra_n( + sentry_scope_t *scope, const char *key, size_t key_len) +{ + char *k = sentry__value_remove_and_take_key_n(scope->extra, key, key_len); + if (k) { + SENTRY_SCOPE_NOTIFY(scope, remove_extra, k); + } + sentry_free(k); +} + void sentry_scope_set_attribute( sentry_scope_t *scope, const char *key, sentry_value_t attribute) @@ -879,6 +917,26 @@ sentry_scope_set_context_n(sentry_scope_t *scope, const char *key, } } +void +sentry_scope_remove_context(sentry_scope_t *scope, const char *key) +{ + if (sentry_value_remove_by_key(scope->contexts, key) == 0) { + SENTRY_SCOPE_NOTIFY(scope, remove_context, key); + } +} + +void +sentry_scope_remove_context_n( + sentry_scope_t *scope, const char *key, size_t key_len) +{ + char *k + = sentry__value_remove_and_take_key_n(scope->contexts, key, key_len); + if (k) { + SENTRY_SCOPE_NOTIFY(scope, remove_context, k); + } + sentry_free(k); +} + void sentry_scope_update_context( sentry_scope_t *scope, const char *key, sentry_value_t value) @@ -909,6 +967,62 @@ sentry_scope_update_context_n(sentry_scope_t *scope, const char *key, SENTRY_SCOPE_NOTIFY(scope, set_context, k, value); } +void +sentry_scope_set_release_n( + sentry_scope_t *scope, const char *release, size_t release_len) +{ + sentry_free(scope->release); + scope->release = sentry__string_clone_n(release, release_len); + sentry_value_set_by_key(scope->dynamic_sampling_context, "release", + sentry_value_new_string(scope->release)); + SENTRY_SCOPE_NOTIFY(scope, set_release, scope->release); +} + +void +sentry_scope_set_release(sentry_scope_t *scope, const char *release) +{ + sentry_scope_set_release_n(scope, release, sentry__guarded_strlen(release)); +} + +void +sentry_scope_set_environment_n( + sentry_scope_t *scope, const char *environment, size_t environment_len) +{ + sentry_free(scope->environment); + scope->environment = sentry__string_clone_n(environment, environment_len); + sentry_value_set_by_key(scope->dynamic_sampling_context, "environment", + sentry_value_new_string(scope->environment)); + SENTRY_SCOPE_NOTIFY(scope, set_environment, scope->environment); +} + +void +sentry_scope_set_environment(sentry_scope_t *scope, const char *environment) +{ + sentry_scope_set_environment_n( + scope, environment, sentry__guarded_strlen(environment)); +} + +void +sentry_scope_set_transaction_n( + sentry_scope_t *scope, const char *transaction, size_t transaction_len) +{ + sentry_free(scope->transaction); + scope->transaction = sentry__string_clone_n(transaction, transaction_len); + + if (scope->transaction_object) { + sentry_transaction_set_name_n( + scope->transaction_object, transaction, transaction_len); + } + SENTRY_SCOPE_NOTIFY(scope, set_transaction, scope->transaction); +} + +void +sentry_scope_set_transaction(sentry_scope_t *scope, const char *transaction) +{ + sentry_scope_set_transaction_n( + scope, transaction, sentry__guarded_strlen(transaction)); +} + void sentry__scope_set_fingerprint_va( sentry_scope_t *scope, const char *fingerprint, va_list va) @@ -1033,6 +1147,17 @@ sentry__scope_add_attachment( return added; } +void +sentry_scope_remove_attachment( + sentry_scope_t *scope, sentry_attachment_t *attachment) +{ + if (attachment + && sentry__attachments_remove(&scope->attachments, attachment)) { + SENTRY_SCOPE_NOTIFY(scope, remove_attachment, attachment); + sentry__attachment_free(attachment); + } +} + sentry_attachment_t * sentry_scope_attach_file(sentry_scope_t *scope, const char *path) { diff --git a/tests/unit/test_attachments.c b/tests/unit/test_attachments.c index db8cf657a..f337f98fe 100644 --- a/tests/unit/test_attachments.c +++ b/tests/unit/test_attachments.c @@ -176,6 +176,16 @@ SENTRY_TEST(attachments_add_dedupe) SENTRY_TEST(attachments_add_remove) { + sentry_scope_t *scope = sentry_scope_new(); + sentry_attachment_t *scoped_attachment + = sentry_scope_attach_bytes(scope, "payload", 7, "file.bin"); + TEST_CHECK(scoped_attachment != NULL); + TEST_CHECK(scope->attachments != NULL); + sentry_scope_remove_attachment(scope, scoped_attachment); + TEST_CHECK(scope->attachments == NULL); + sentry_scope_remove_attachment(scope, NULL); + sentry_scope_free(scope); + SENTRY_TEST_OPTIONS_NEW(options); sentry_options_add_attachment(options, SENTRY_TEST_PATH_PREFIX ".a.txt"); sentry_options_add_attachment(options, SENTRY_TEST_PATH_PREFIX ".c.txt"); diff --git a/tests/unit/test_scope.c b/tests/unit/test_scope.c index e21e79e87..ca6f0daab 100644 --- a/tests/unit/test_scope.c +++ b/tests/unit/test_scope.c @@ -67,6 +67,16 @@ SENTRY_TEST(scope_contexts) local_scope, "local", sentry_value_new_string("local")); sentry_scope_set_context( local_scope, "scope", sentry_value_new_string("local")); + sentry_scope_set_context( + local_scope, "removed", sentry_value_new_string("removed")); + sentry_scope_set_context( + local_scope, "n-removed", sentry_value_new_string("removed")); + sentry_scope_remove_context(local_scope, "removed"); + sentry_scope_remove_context_n(local_scope, "n-removed-trailing", 9); + TEST_CHECK(sentry_value_is_null( + sentry_value_get_by_key(local_scope->contexts, "removed"))); + TEST_CHECK(sentry_value_is_null( + sentry_value_get_by_key(local_scope->contexts, "n-removed"))); // event: // {"all":"event","event":"event"} @@ -327,6 +337,16 @@ SENTRY_TEST(scope_extra) local_scope, "local", sentry_value_new_string("local")); sentry_scope_set_extra( local_scope, "scope", sentry_value_new_string("local")); + sentry_scope_set_extra( + local_scope, "removed", sentry_value_new_string("removed")); + sentry_scope_set_extra( + local_scope, "n-removed", sentry_value_new_string("removed")); + sentry_scope_remove_extra(local_scope, "removed"); + sentry_scope_remove_extra_n(local_scope, "n-removed-trailing", 9); + TEST_CHECK(sentry_value_is_null( + sentry_value_get_by_key(local_scope->extra, "removed"))); + TEST_CHECK(sentry_value_is_null( + sentry_value_get_by_key(local_scope->extra, "n-removed"))); // event: // {"all":"event","event":"event"} @@ -573,6 +593,14 @@ SENTRY_TEST(scope_tags) sentry_value_set_by_key( local_tags, "scope", sentry_value_new_string("local")); sentry_scope_set_tags(local_scope, local_tags); + sentry_scope_set_tag(local_scope, "removed", "removed"); + sentry_scope_set_tag(local_scope, "n-removed", "removed"); + sentry_scope_remove_tag(local_scope, "removed"); + sentry_scope_remove_tag_n(local_scope, "n-removed-trailing", 9); + TEST_CHECK(sentry_value_is_null( + sentry_value_get_by_key(local_scope->tags, "removed"))); + TEST_CHECK(sentry_value_is_null( + sentry_value_get_by_key(local_scope->tags, "n-removed"))); // event: // {"all":"event","event":"event"} @@ -1352,6 +1380,53 @@ SENTRY_TEST(scope_local_attributes) sentry_close(); } +SENTRY_TEST(scope_release) +{ + SENTRY_TEST_OPTIONS_NEW(options); + sentry_init(options); + + SENTRY_WITH_SCOPE_MUT (scope) { + sentry_scope_set_release(scope, "my-release"); + TEST_CHECK_STRING_EQUAL(scope->release, "my-release"); + TEST_CHECK_STRING_EQUAL( + sentry_value_as_string(sentry_value_get_by_key( + scope->dynamic_sampling_context, "release")), + "my-release"); + } + + sentry_close(); +} + +SENTRY_TEST(scope_environment) +{ + SENTRY_TEST_OPTIONS_NEW(options); + sentry_init(options); + + SENTRY_WITH_SCOPE_MUT (scope) { + sentry_scope_set_environment(scope, "my-environment"); + TEST_CHECK_STRING_EQUAL(scope->environment, "my-environment"); + TEST_CHECK_STRING_EQUAL( + sentry_value_as_string(sentry_value_get_by_key( + scope->dynamic_sampling_context, "environment")), + "my-environment"); + } + + sentry_close(); +} + +SENTRY_TEST(scope_transaction) +{ + SENTRY_TEST_OPTIONS_NEW(options); + sentry_init(options); + + SENTRY_WITH_SCOPE_MUT (scope) { + sentry_scope_set_transaction(scope, "my-transaction"); + TEST_CHECK_STRING_EQUAL(scope->transaction, "my-transaction"); + } + + sentry_close(); +} + typedef struct { sentry_value_t release; sentry_value_t environment; diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index 6baf02471..1326ff67f 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -357,6 +357,7 @@ XX(scope_clone_keeps_bound_span) XX(scope_clone_preserves_data) XX(scope_clone_shares_span) XX(scope_contexts) +XX(scope_environment) XX(scope_extra) XX(scope_fingerprint) XX(scope_fingerprint_n) @@ -383,11 +384,13 @@ XX(scope_observer_user) XX(scope_ownership) XX(scope_propagation_context) XX(scope_rebind_same_object) +XX(scope_release) XX(scope_remove_fingerprint_capture) XX(scope_set_attribute_invalid_decref_value) XX(scope_set_attribute_null_key_decref_value) XX(scope_tags) XX(scope_tags_flush) +XX(scope_transaction) XX(scope_update_context) XX(scope_user) XX(scope_user_id)