From d2239452a7dec43df3993a507a18a6886f5501dc Mon Sep 17 00:00:00 2001 From: Betty Da Date: Thu, 16 Dec 2021 01:51:06 -0500 Subject: [PATCH] feat(tracing): Add in basic Envelope support for Transactions --- include/sentry.h | 12 +++++-- src/sentry_envelope.c | 62 ++++++++++++++++++++++++++++++++++++- src/sentry_envelope.h | 6 ++++ tests/unit/test_envelopes.c | 32 +++++++++++++++++++ tests/unit/tests.inc | 1 + 5 files changed, 110 insertions(+), 3 deletions(-) diff --git a/include/sentry.h b/include/sentry.h index 3675e5527..d0bcc485f 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -554,13 +554,21 @@ typedef struct sentry_envelope_s sentry_envelope_t; SENTRY_API void sentry_envelope_free(sentry_envelope_t *envelope); /** - * Given an envelope returns the embedded event if there is one. + * Given an Envelope, returns the embedded Event if there is one. * - * This returns a borrowed value to the event in the envelope. + * This returns a borrowed value to the Event in the Envelope. */ SENTRY_API sentry_value_t sentry_envelope_get_event( const sentry_envelope_t *envelope); +/** + * Given an Envelope, returns the embedded Transaction if there is one. + * + * This returns a borrowed value to the Transaction in the Envelope. + */ +SENTRY_EXPERIMENTAL_API sentry_value_t sentry_envelope_get_transaction( + const sentry_envelope_t *envelope); + /** * Serializes the envelope. * diff --git a/src/sentry_envelope.c b/src/sentry_envelope.c index 71cef6ed6..7ea05ad98 100644 --- a/src/sentry_envelope.c +++ b/src/sentry_envelope.c @@ -41,6 +41,9 @@ envelope_add_item(sentry_envelope_t *envelope) if (envelope->contents.items.item_count >= SENTRY_MAX_ENVELOPE_ITEMS) { return NULL; } + // TODO: Envelopes may have at most one event item or one transaction item, + // and not one of both. Some checking should be done here or in + // `sentry__envelope_add_[transaction|event]` to ensure this can't happen. sentry_envelope_item_t *rv = &envelope->contents.items @@ -197,7 +200,25 @@ sentry_envelope_get_event(const sentry_envelope_t *envelope) return sentry_value_new_null(); } for (size_t i = 0; i < envelope->contents.items.item_count; i++) { - if (!sentry_value_is_null(envelope->contents.items.items[i].event)) { + if (!sentry_value_is_null(envelope->contents.items.items[i].event) + && !sentry__event_is_transaction( + envelope->contents.items.items[i].event)) { + return envelope->contents.items.items[i].event; + } + } + return sentry_value_new_null(); +} + +sentry_value_t +sentry_envelope_get_transaction(const sentry_envelope_t *envelope) +{ + if (envelope->is_raw) { + return sentry_value_new_null(); + } + for (size_t i = 0; i < envelope->contents.items.item_count; i++) { + if (!sentry_value_is_null(envelope->contents.items.items[i].event) + && sentry__event_is_transaction( + envelope->contents.items.items[i].event)) { return envelope->contents.items.items[i].event; } } @@ -234,6 +255,45 @@ sentry__envelope_add_event(sentry_envelope_t *envelope, sentry_value_t event) return item; } +sentry_envelope_item_t * +sentry__envelope_add_transaction( + sentry_envelope_t *envelope, sentry_value_t transaction) +{ + sentry_envelope_item_t *item = envelope_add_item(envelope); + if (!item) { + return NULL; + } + + sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL); + if (!jw) { + return NULL; + } + + sentry_value_t event_id = sentry__ensure_event_id(transaction, NULL); + + item->event = transaction; + sentry__jsonwriter_write_value(jw, transaction); + item->payload = sentry__jsonwriter_into_string(jw, &item->payload_len); + + sentry__envelope_item_set_header( + item, "type", sentry_value_new_string("transaction")); + sentry_value_t length = sentry_value_new_int32((int32_t)item->payload_len); + sentry__envelope_item_set_header(item, "length", length); + + sentry_value_incref(event_id); + sentry__envelope_set_header(envelope, "event_id", event_id); + +#ifdef SENTRY_UNITTEST + sentry_value_t now = sentry_value_new_string("2021-12-16T05:53:59.343Z"); +#else + sentry_value_t now = sentry__value_new_string_owned( + sentry__msec_time_to_iso8601(sentry__msec_time())); +#endif + sentry__envelope_set_header(envelope, "sent_at", now); + + return item; +} + sentry_envelope_item_t * sentry__envelope_add_session( sentry_envelope_t *envelope, const sentry_session_t *session) diff --git a/src/sentry_envelope.h b/src/sentry_envelope.h index ac5c69136..b5a8f1ab0 100644 --- a/src/sentry_envelope.h +++ b/src/sentry_envelope.h @@ -36,6 +36,12 @@ sentry_uuid_t sentry__envelope_get_event_id(const sentry_envelope_t *envelope); sentry_envelope_item_t *sentry__envelope_add_event( sentry_envelope_t *envelope, sentry_value_t event); +/** + * Add a transaction to this envelope. + */ +sentry_envelope_item_t *sentry__envelope_add_transaction( + sentry_envelope_t *envelope, sentry_value_t transaction); + /** * Add a session to this envelope. */ diff --git a/tests/unit/test_envelopes.c b/tests/unit/test_envelopes.c index a579afa3e..2554be1c7 100644 --- a/tests/unit/test_envelopes.c +++ b/tests/unit/test_envelopes.c @@ -32,6 +32,38 @@ SENTRY_TEST(basic_http_request_preparation_for_event) sentry__dsn_decref(dsn); } +SENTRY_TEST(basic_http_request_preparation_for_transaction) +{ + sentry_dsn_t *dsn = sentry__dsn_new("https://foo@sentry.invalid/42"); + + sentry_uuid_t event_id + = sentry_uuid_from_string("c993afb6-b4ac-48a6-b61b-2558e601d65d"); + sentry_envelope_t *envelope = sentry__envelope_new(); + sentry_value_t transaction = sentry_value_new_object(); + sentry_value_set_by_key( + transaction, "event_id", sentry__value_new_uuid(&event_id)); + sentry_value_set_by_key( + transaction, "type", sentry_value_new_string("transaction")); + sentry__envelope_add_transaction(envelope, transaction); + + sentry_prepared_http_request_t *req + = sentry__prepare_http_request(envelope, dsn, NULL); + TEST_CHECK_STRING_EQUAL(req->method, "POST"); + TEST_CHECK_STRING_EQUAL( + req->url, "https://sentry.invalid:443/api/42/envelope/"); + TEST_CHECK_STRING_EQUAL(req->body, + "{\"event_id\":\"c993afb6-b4ac-48a6-b61b-2558e601d65d\",\"sent_at\":" + "\"2021-12-16T05:53:59.343Z\"}\n" + "{\"type\":\"transaction\",\"length\":72}\n" + "{\"event_id\":\"c993afb6-b4ac-48a6-b61b-2558e601d65d\",\"type\":" + "\"transaction\"}"); + + sentry__prepared_http_request_free(req); + sentry_envelope_free(envelope); + + sentry__dsn_decref(dsn); +} + SENTRY_TEST(basic_http_request_preparation_for_event_with_attachment) { sentry_dsn_t *dsn = sentry__dsn_new("https://foo@sentry.invalid/42"); diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index 781361644..716be19d4 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -4,6 +4,7 @@ XX(basic_function_transport) XX(basic_http_request_preparation_for_event) XX(basic_http_request_preparation_for_event_with_attachment) XX(basic_http_request_preparation_for_minidump) +XX(basic_http_request_preparation_for_transaction) XX(basic_tracing_context) XX(basic_transaction) XX(buildid_fallback)