From b10f9089cdd8a56313b0ec453a43589903b84e7d Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Wed, 12 Jan 2022 12:38:27 +0100 Subject: [PATCH 01/12] feat: basic object merging This has a basic recursive merging of sentry_value_t objects. Generally values from the source object have preference, however when the values of a key are objects themselves in both the target and the source they are recursively merged. --- src/sentry_value.c | 33 +++++++++++++++++++++++++++ src/sentry_value.h | 13 +++++++++++ tests/unit/test_value.c | 50 +++++++++++++++++++++++++++++++++++++++++ tests/unit/tests.inc | 2 ++ 4 files changed, 98 insertions(+) diff --git a/src/sentry_value.c b/src/sentry_value.c index f4bf51f3d..103c240e3 100644 --- a/src/sentry_value.c +++ b/src/sentry_value.c @@ -1,3 +1,4 @@ +#include "sentry.h" #include "sentry_boot.h" #include @@ -806,6 +807,38 @@ sentry_value_is_null(sentry_value_t value) return value._bits == CONST_NULL; } +int +sentry__value_merge_objects(sentry_value_t dst, sentry_value_t src) +{ + if (sentry_value_get_type(dst) != SENTRY_VALUE_TYPE_OBJECT + || sentry_value_get_type(src) != SENTRY_VALUE_TYPE_OBJECT + || sentry_value_is_frozen(dst)) { + return 1; + } + thing_t *thing = value_as_thing(src); + if (!thing) { + return 1; + } + obj_t *obj = thing->payload._ptr; + for (size_t i = 0; i < obj->len; i++) { + char *key = obj->pairs[i].k; + sentry_value_t src_val = obj->pairs[i].v; + sentry_value_t dst_val = sentry_value_get_by_key(dst, key); + if (sentry_value_get_type(dst_val) == SENTRY_VALUE_TYPE_OBJECT + && sentry_value_get_type(src_val) == SENTRY_VALUE_TYPE_OBJECT) { + if (sentry__value_merge_objects(dst_val, src_val)) { + return 1; + } + } else { + if (sentry_value_set_by_key(dst, key, src_val)) { + return 1; + } + sentry_value_incref(src_val); + } + } + return 0; +} + void sentry__jsonwriter_write_value(sentry_jsonwriter_t *jw, sentry_value_t value) { diff --git a/src/sentry_value.h b/src/sentry_value.h index cba785364..f9136bcdc 100644 --- a/src/sentry_value.h +++ b/src/sentry_value.h @@ -1,6 +1,7 @@ #ifndef SENTRY_VALUE_H_INCLUDED #define SENTRY_VALUE_H_INCLUDED +#include "sentry.h" #include "sentry_boot.h" /** @@ -96,6 +97,18 @@ sentry_value_t sentry__value_clone(sentry_value_t value); int sentry__value_append_bounded( sentry_value_t value, sentry_value_t v, size_t max); +/** + * Deep-merges two objects into each other. + * + * For each key-value pair in the src object the same key in the dst object + * will be set to the value from src. If both the dst value and the src value + * are objects themselves they are stepped into recursively instead of + * overriding the entire dst object. + * + * Returns 0 on success. + */ +int sentry__value_merge_objects(sentry_value_t dst, sentry_value_t src); + /** * Parse the given JSON string into a new Value. */ diff --git a/tests/unit/test_value.c b/tests/unit/test_value.c index 783567f40..b087d6828 100644 --- a/tests/unit/test_value.c +++ b/tests/unit/test_value.c @@ -229,6 +229,56 @@ SENTRY_TEST(value_object) sentry_value_decref(val); } +SENTRY_TEST(value_object_merge) +{ + sentry_value_t dst = sentry_value_new_object(); + sentry_value_set_by_key(dst, "a", sentry_value_new_int32(1)); + sentry_value_set_by_key(dst, "b", sentry_value_new_int32(2)); + + sentry_value_t src = sentry_value_new_object(); + sentry_value_set_by_key(src, "b", sentry_value_new_int32(20)); + sentry_value_set_by_key(src, "c", sentry_value_new_int32(30)); + + int rv = sentry__value_merge_objects(dst, src); + TEST_CHECK_INT_EQUAL(rv, 0); + + sentry_value_t a = sentry_value_get_by_key(dst, "a"); + sentry_value_t b = sentry_value_get_by_key(dst, "b"); + sentry_value_t c = sentry_value_get_by_key(dst, "c"); + TEST_CHECK_INT_EQUAL(sentry_value_as_int32(a), 1); + TEST_CHECK_INT_EQUAL(sentry_value_as_int32(b), 20); + TEST_CHECK_INT_EQUAL(sentry_value_as_int32(c), 30); +} + +SENTRY_TEST(value_object_merge_nested) +{ + sentry_value_t dst = sentry_value_new_object(); + sentry_value_set_by_key(dst, "a", sentry_value_new_int32(1)); + sentry_value_t dst_nested = sentry_value_new_object(); + sentry_value_set_by_key(dst_nested, "ba", sentry_value_new_int32(1)); + sentry_value_set_by_key(dst_nested, "bb", sentry_value_new_int32(2)); + sentry_value_set_by_key(dst, "b", dst_nested); + + sentry_value_t src = sentry_value_new_object(); + sentry_value_t src_nested = sentry_value_new_object(); + sentry_value_set_by_key(src_nested, "bb", sentry_value_new_int32(20)); + sentry_value_set_by_key(src_nested, "bc", sentry_value_new_int32(30)); + sentry_value_set_by_key(src, "b", src_nested); + + int rv = sentry__value_merge_objects(dst, src); + TEST_CHECK_INT_EQUAL(rv, 0); + + sentry_value_t a = sentry_value_get_by_key(dst, "a"); + sentry_value_t nested = sentry_value_get_by_key(dst, "b"); + sentry_value_t ba = sentry_value_get_by_key(nested, "ba"); + sentry_value_t bb = sentry_value_get_by_key(nested, "bb"); + sentry_value_t bc = sentry_value_get_by_key(nested, "bc"); + TEST_CHECK_INT_EQUAL(sentry_value_as_int32(a), 1); + TEST_CHECK_INT_EQUAL(sentry_value_as_int32(ba), 1); + TEST_CHECK_INT_EQUAL(sentry_value_as_int32(bb), 20); + TEST_CHECK_INT_EQUAL(sentry_value_as_int32(bc), 30); +} + SENTRY_TEST(value_freezing) { sentry_value_t val = sentry_value_new_list(); diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index 42cbed1c6..2341c3358 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -79,6 +79,8 @@ XX(value_json_surrogates) XX(value_list) XX(value_null) XX(value_object) +XX(value_object_merge) +XX(value_object_merge_nested) XX(value_string) XX(value_unicode) XX(value_wrong_type) From b439cce5e3736a40bac6269ed9160f59c6ce3d46 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Wed, 12 Jan 2022 15:06:57 +0100 Subject: [PATCH 02/12] Improve description --- src/sentry_value.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry_value.h b/src/sentry_value.h index f9136bcdc..64e965559 100644 --- a/src/sentry_value.h +++ b/src/sentry_value.h @@ -98,7 +98,7 @@ int sentry__value_append_bounded( sentry_value_t value, sentry_value_t v, size_t max); /** - * Deep-merges two objects into each other. + * Deep-merges object src into dst. * * For each key-value pair in the src object the same key in the dst object * will be set to the value from src. If both the dst value and the src value From c70b49616fe058aae107f966d9c9e7a94fba2a56 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Wed, 12 Jan 2022 15:38:12 +0100 Subject: [PATCH 03/12] Use the merging somewhere useful --- src/sentry_scope.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sentry_scope.c b/src/sentry_scope.c index 5a4731c53..09f24be5e 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -1,4 +1,5 @@ #include "sentry_scope.h" +#include "sentry.h" #include "sentry_backend.h" #include "sentry_core.h" #include "sentry_database.h" @@ -7,6 +8,7 @@ #include "sentry_string.h" #include "sentry_symbolizer.h" #include "sentry_sync.h" +#include "sentry_value.h" #include @@ -293,9 +295,10 @@ sentry__scope_apply_to_event(const sentry_scope_t *scope, PLACE_STRING("transaction", scope->transaction); PLACE_VALUE("sdk", scope->client_sdk); - // TODO: these should merge - PLACE_CLONED_VALUE("tags", scope->tags); - PLACE_CLONED_VALUE("extra", scope->extra); + sentry_value_t event_tags = sentry_value_get_by_key(event, "tags"); + sentry__value_merge_objects(event_tags, scope->tags); + sentry_value_t event_extra = sentry_value_get_by_key(event, "extra"); + sentry__value_merge_objects(event_extra, scope->extra); #ifdef SENTRY_PERFORMANCE_MONITORING // TODO: better, more thorough deep merging From 826d322cabb4ad16e8eefa92e0dc98e8251128a7 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Wed, 12 Jan 2022 16:22:45 +0100 Subject: [PATCH 04/12] Make this a bit more robust --- src/sentry_scope.c | 15 ++++++++++++++- src/sentry_value.c | 7 +++++-- src/sentry_value.h | 4 ++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/sentry_scope.c b/src/sentry_scope.c index 09f24be5e..e0008415b 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -296,8 +296,21 @@ sentry__scope_apply_to_event(const sentry_scope_t *scope, PLACE_VALUE("sdk", scope->client_sdk); sentry_value_t event_tags = sentry_value_get_by_key(event, "tags"); - sentry__value_merge_objects(event_tags, scope->tags); + if (sentry_value_is_null(event_tags)) { + sentry_value_t tags = sentry__value_clone(scope->tags); + if (!sentry_value_is_null(tags)) { + sentry_value_set_by_key(event, "tags", tags); + } + } else { + sentry__value_merge_objects(event_tags, scope->tags); + } sentry_value_t event_extra = sentry_value_get_by_key(event, "extra"); + if (sentry_value_is_null(event_extra)) { + sentry_value_t extra = sentry__value_clone(scope->extra); + if (!sentry_value_is_null(extra)) { + sentry_value_set_by_key(event, "extra", extra); + } + } sentry__value_merge_objects(event_extra, scope->extra); #ifdef SENTRY_PERFORMANCE_MONITORING diff --git a/src/sentry_value.c b/src/sentry_value.c index 103c240e3..2480a57e3 100644 --- a/src/sentry_value.c +++ b/src/sentry_value.c @@ -810,6 +810,9 @@ sentry_value_is_null(sentry_value_t value) int sentry__value_merge_objects(sentry_value_t dst, sentry_value_t src) { + if (sentry_value_is_null(src)) { + return 0; + } if (sentry_value_get_type(dst) != SENTRY_VALUE_TYPE_OBJECT || sentry_value_get_type(src) != SENTRY_VALUE_TYPE_OBJECT || sentry_value_is_frozen(dst)) { @@ -826,11 +829,11 @@ sentry__value_merge_objects(sentry_value_t dst, sentry_value_t src) sentry_value_t dst_val = sentry_value_get_by_key(dst, key); if (sentry_value_get_type(dst_val) == SENTRY_VALUE_TYPE_OBJECT && sentry_value_get_type(src_val) == SENTRY_VALUE_TYPE_OBJECT) { - if (sentry__value_merge_objects(dst_val, src_val)) { + if (sentry__value_merge_objects(dst_val, src_val) != 0) { return 1; } } else { - if (sentry_value_set_by_key(dst, key, src_val)) { + if (sentry_value_set_by_key(dst, key, src_val) != 0) { return 1; } sentry_value_incref(src_val); diff --git a/src/sentry_value.h b/src/sentry_value.h index 64e965559..500e67c89 100644 --- a/src/sentry_value.h +++ b/src/sentry_value.h @@ -105,6 +105,10 @@ int sentry__value_append_bounded( * are objects themselves they are stepped into recursively instead of * overriding the entire dst object. * + * If src is null nothing needs to be merged and this is handled gracefully, + * otherwise if dst is any other type than an object or src is neither an + * object nor null an error is returned. + * * Returns 0 on success. */ int sentry__value_merge_objects(sentry_value_t dst, sentry_value_t src); From 96cd844f10167a4f8ed791efbb8b774c1f8364c9 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Thu, 13 Jan 2022 11:41:02 +0100 Subject: [PATCH 05/12] Maybe fix memory leak in tests? --- tests/unit/test_value.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit/test_value.c b/tests/unit/test_value.c index b087d6828..994419d49 100644 --- a/tests/unit/test_value.c +++ b/tests/unit/test_value.c @@ -241,6 +241,7 @@ SENTRY_TEST(value_object_merge) int rv = sentry__value_merge_objects(dst, src); TEST_CHECK_INT_EQUAL(rv, 0); + sentry_value_decref(src); sentry_value_t a = sentry_value_get_by_key(dst, "a"); sentry_value_t b = sentry_value_get_by_key(dst, "b"); @@ -248,6 +249,7 @@ SENTRY_TEST(value_object_merge) TEST_CHECK_INT_EQUAL(sentry_value_as_int32(a), 1); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(b), 20); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(c), 30); + sentry_value_decref(dst); } SENTRY_TEST(value_object_merge_nested) @@ -267,6 +269,7 @@ SENTRY_TEST(value_object_merge_nested) int rv = sentry__value_merge_objects(dst, src); TEST_CHECK_INT_EQUAL(rv, 0); + sentry_value_decref(src); sentry_value_t a = sentry_value_get_by_key(dst, "a"); sentry_value_t nested = sentry_value_get_by_key(dst, "b"); @@ -277,6 +280,7 @@ SENTRY_TEST(value_object_merge_nested) TEST_CHECK_INT_EQUAL(sentry_value_as_int32(ba), 1); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(bb), 20); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(bc), 30); + sentry_value_decref(dst); } SENTRY_TEST(value_freezing) From ab5b0568acfae2c91b4688b7397da778b0088de6 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Thu, 13 Jan 2022 13:30:56 +0100 Subject: [PATCH 06/12] Do not explicitly include sentry.h, bad clangd --- src/sentry_value.c | 1 - src/sentry_value.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/sentry_value.c b/src/sentry_value.c index 2480a57e3..6b82e8866 100644 --- a/src/sentry_value.c +++ b/src/sentry_value.c @@ -1,4 +1,3 @@ -#include "sentry.h" #include "sentry_boot.h" #include diff --git a/src/sentry_value.h b/src/sentry_value.h index 500e67c89..447723dda 100644 --- a/src/sentry_value.h +++ b/src/sentry_value.h @@ -1,7 +1,6 @@ #ifndef SENTRY_VALUE_H_INCLUDED #define SENTRY_VALUE_H_INCLUDED -#include "sentry.h" #include "sentry_boot.h" /** From 15f38771fe63c341cd9fe87de0e8a74fb0300f84 Mon Sep 17 00:00:00 2001 From: Betty Da Date: Thu, 13 Jan 2022 14:18:58 -0500 Subject: [PATCH 07/12] fix minor bug --- src/sentry_scope.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sentry_scope.c b/src/sentry_scope.c index e0008415b..331d4d57a 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -310,8 +310,9 @@ sentry__scope_apply_to_event(const sentry_scope_t *scope, if (!sentry_value_is_null(extra)) { sentry_value_set_by_key(event, "extra", extra); } + } else { + sentry__value_merge_objects(event_extra, scope->extra); } - sentry__value_merge_objects(event_extra, scope->extra); #ifdef SENTRY_PERFORMANCE_MONITORING // TODO: better, more thorough deep merging From 8d35cbb73d5ece55cfa03918ece094af97e07a29 Mon Sep 17 00:00:00 2001 From: Betty Da Date: Thu, 13 Jan 2022 14:20:33 -0500 Subject: [PATCH 08/12] use macros since they're there --- src/sentry_scope.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/sentry_scope.c b/src/sentry_scope.c index 331d4d57a..9db662d84 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -297,18 +297,16 @@ sentry__scope_apply_to_event(const sentry_scope_t *scope, sentry_value_t event_tags = sentry_value_get_by_key(event, "tags"); if (sentry_value_is_null(event_tags)) { - sentry_value_t tags = sentry__value_clone(scope->tags); - if (!sentry_value_is_null(tags)) { - sentry_value_set_by_key(event, "tags", tags); + if (!sentry_value_is_null(scope->tags)) { + PLACE_CLONED_VALUE("tags", scope->tags); } } else { sentry__value_merge_objects(event_tags, scope->tags); } sentry_value_t event_extra = sentry_value_get_by_key(event, "extra"); if (sentry_value_is_null(event_extra)) { - sentry_value_t extra = sentry__value_clone(scope->extra); - if (!sentry_value_is_null(extra)) { - sentry_value_set_by_key(event, "extra", extra); + if (!sentry_value_is_null(scope->extra)) { + PLACE_CLONED_VALUE("extra", scope->extra); } } else { sentry__value_merge_objects(event_extra, scope->extra); From 078c4734aee1c10649f9b9c3c951a360b7a6dd06 Mon Sep 17 00:00:00 2001 From: Betty Da Date: Thu, 13 Jan 2022 14:59:33 -0500 Subject: [PATCH 09/12] use deep merging for contexts on an event as well --- src/sentry_scope.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/sentry_scope.c b/src/sentry_scope.c index 9db662d84..dfc45843b 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -313,13 +313,24 @@ sentry__scope_apply_to_event(const sentry_scope_t *scope, } #ifdef SENTRY_PERFORMANCE_MONITORING - // TODO: better, more thorough deep merging sentry_value_t contexts = sentry__value_clone(scope->contexts); - sentry_value_t trace = sentry__span_get_trace_context(scope->span); - if (!sentry_value_is_null(trace)) { - sentry_value_set_by_key(contexts, "trace", trace); + // prep contexts sourced from scope; data about transaction on scope needs + // to be extracted and inserted + sentry_value_t scope_trace = sentry__span_get_trace_context(scope->span); + if (!sentry_value_is_null(scope_trace)) { + if (sentry_value_is_null(contexts)) { + contexts = sentry_value_new_object(); + } + sentry_value_set_by_key(contexts, "trace", scope_trace); + } + + // merge contexts sourced from scope into the event + sentry_value_t event_contexts = sentry_value_get_by_key(event, "contexts"); + if (sentry_value_is_null(event_contexts)) { + PLACE_VALUE("contexts", contexts); + } else { + sentry__value_merge_objects(event_contexts, contexts); } - PLACE_VALUE("contexts", contexts); sentry_value_decref(contexts); #endif From 1d63196b9ac74888ede50c98f5a8142a204e2985 Mon Sep 17 00:00:00 2001 From: Betty Da Date: Thu, 13 Jan 2022 15:00:00 -0500 Subject: [PATCH 10/12] use merging when starting transactions --- src/sentry_core.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/src/sentry_core.c b/src/sentry_core.c index 0583ef145..7f63321bc 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -733,37 +733,25 @@ sentry_set_level(sentry_level_t level) sentry_value_t sentry_transaction_start(sentry_value_t tx_cxt) { - // TODO: it would be nice if we could just merge tx_cxt into tx. - // `sentry_value_new_transaction_event()` is also an option, but risks - // causing more confusion as there's already a - // `sentry_value_new_transaction`. The ending timestamp is stripped as well - // to avoid misleading ourselves later down the line. + // If the parent span ID is some empty-ish value, just remove it + sentry_value_t parent_span + = sentry_value_get_by_key(tx_cxt, "parent_span_id"); + if (sentry_value_get_length(parent_span) < 1) { + sentry_value_remove_by_key(tx_cxt, "parent_span_id"); + } + + // The ending timestamp is stripped to avoid misleading ourselves later + // down the line, as it is the only way to determine whether a transaction + // has ended or not. sentry_value_t tx = sentry_value_new_event(); sentry_value_remove_by_key(tx, "timestamp"); + sentry__value_merge_objects(tx, tx_cxt); + bool should_sample = sentry__should_send_transaction(tx_cxt); sentry_value_set_by_key( tx, "sampled", sentry_value_new_bool(should_sample)); - // Avoid having this show up in the payload at all if it doesn't have a - // valid value - sentry_value_t parent_span - = sentry_value_get_by_key_owned(tx_cxt, "parent_span_id"); - if (sentry_value_get_length(parent_span) > 0) { - sentry_value_set_by_key(tx, "parent_span_id", parent_span); - } else { - sentry_value_decref(parent_span); - } - sentry_value_set_by_key( - tx, "trace_id", sentry_value_get_by_key_owned(tx_cxt, "trace_id")); - sentry_value_set_by_key( - tx, "span_id", sentry_value_get_by_key_owned(tx_cxt, "span_id")); - sentry_value_set_by_key(tx, "transaction", - sentry_value_get_by_key_owned(tx_cxt, "transaction")); - sentry_value_set_by_key( - tx, "op", sentry_value_get_by_key_owned(tx_cxt, "op")); - sentry_value_set_by_key( - tx, "status", sentry_value_get_by_key_owned(tx_cxt, "status")); sentry_value_set_by_key(tx, "start_timestamp", sentry__value_new_string_owned( sentry__msec_time_to_iso8601(sentry__msec_time()))); From a057d52048185e560e5a9815ac8cf99ab52d3047 Mon Sep 17 00:00:00 2001 From: Betty Da Date: Thu, 13 Jan 2022 15:00:07 -0500 Subject: [PATCH 11/12] address leaks in unit tests --- tests/unit/test_value.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/test_value.c b/tests/unit/test_value.c index 994419d49..46170b145 100644 --- a/tests/unit/test_value.c +++ b/tests/unit/test_value.c @@ -249,6 +249,7 @@ SENTRY_TEST(value_object_merge) TEST_CHECK_INT_EQUAL(sentry_value_as_int32(a), 1); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(b), 20); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(c), 30); + sentry_value_decref(dst); } @@ -280,6 +281,7 @@ SENTRY_TEST(value_object_merge_nested) TEST_CHECK_INT_EQUAL(sentry_value_as_int32(ba), 1); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(bb), 20); TEST_CHECK_INT_EQUAL(sentry_value_as_int32(bc), 30); + sentry_value_decref(dst); } From 242704cad6658ab606235afbd2c9d62029d9e6ac Mon Sep 17 00:00:00 2001 From: Betty Da Date: Thu, 13 Jan 2022 15:07:16 -0500 Subject: [PATCH 12/12] missed a spot --- src/sentry_scope.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sentry_scope.c b/src/sentry_scope.c index d482f2350..b2b732470 100644 --- a/src/sentry_scope.c +++ b/src/sentry_scope.c @@ -320,7 +320,8 @@ sentry__scope_apply_to_event(const sentry_scope_t *scope, sentry_value_t contexts = sentry__value_clone(scope->contexts); // prep contexts sourced from scope; data about transaction on scope needs // to be extracted and inserted - sentry_value_t scope_trace = sentry__span_get_trace_context(scope->span); + sentry_value_t scope_trace + = sentry__transaction_get_trace_context(scope->span); if (!sentry_value_is_null(scope_trace)) { if (sentry_value_is_null(contexts)) { contexts = sentry_value_new_object();