diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6f676e65..9971ebcc2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,15 +62,18 @@ jobs: - name: macOS (xcode llvm) os: macOs-latest ERROR_ON_WARNINGS: 1 + SYSTEM_VERSION_COMPAT: 0 - name: macOS (xcode llvm + universal) os: macOs-latest ERROR_ON_WARNINGS: 1 + SYSTEM_VERSION_COMPAT: 0 CMAKE_DEFINES: -DCMAKE_OSX_ARCHITECTURES=arm64;x86_64 - name: macOS (clang 11 + asan + llvm-cov) os: macOs-latest CC: clang CXX: clang++ ERROR_ON_WARNINGS: 1 + SYSTEM_VERSION_COMPAT: 0 RUN_ANALYZER: asan,llvm-cov - name: Windows (VS2017, 32bit) os: vs2017-win2016 @@ -98,6 +101,7 @@ jobs: ANDROID_API: ${{ matrix.ANDROID_API }} ANDROID_NDK: ${{ matrix.ANDROID_NDK }} CMAKE_DEFINES: ${{ matrix.CMAKE_DEFINES }} + SYSTEM_VERSION_COMPAT: ${{ matrix.SYSTEM_VERSION_COMPAT }} steps: - uses: actions/checkout@v2 diff --git a/include/sentry.h b/include/sentry.h index 3c78e57f2..274169a4f 100644 --- a/include/sentry.h +++ b/include/sentry.h @@ -1226,6 +1226,55 @@ SENTRY_EXPERIMENTAL_API void sentry_options_set_traces_sample_rate( SENTRY_EXPERIMENTAL_API double sentry_options_get_traces_sample_rate( sentry_options_t *opts); +/* -- Performance Monitoring/Tracing APIs -- */ + +/** + * Constructs a new inert Transaction. The returned value needs to be passed + * into `sentry_start_transaction` in order to be recorded and sent to sentry. + * + * See + * https://docs.sentry.io/platforms/native/enriching-events/transaction-name/ + * for an explanation of a Transaction's `name`, and + * https://develop.sentry.dev/sdk/performance/span-operations/ for conventions + * around an `operation`'s value. + * + * Also see https://develop.sentry.dev/sdk/event-payloads/transaction/#anatomy + * for an explanation of `operation`, in addition to other properties and + * actions that can be performed on a Transaction. + */ +SENTRY_EXPERIMENTAL_API sentry_value_t sentry_value_new_transaction( + const char *name, const char *operation); + +/** + * Sets the `name` of a Transaction. + */ +SENTRY_EXPERIMENTAL_API void sentry_transaction_set_name( + sentry_value_t transaction, const char *name); + +/** + * Sets the `operation` of a Transaction. + * + * See https://develop.sentry.dev/sdk/performance/span-operations/ for + * conventions on `operation`s. + */ +SENTRY_EXPERIMENTAL_API void sentry_transaction_set_operation( + sentry_value_t transaction, const char *operation); + +/** + * Sets the `sampled` field on a Transaction. When turned on, the Transaction + * will bypass all sampling options and always be sent to sentry. If this is + * explicitly turned off in the Transaction, it will never be sent to sentry. + */ +SENTRY_EXPERIMENTAL_API void sentry_transaction_set_sampled( + sentry_value_t transaction, int sampled); + +/** + * Removes the sampled field on a Transaction. The Transaction will use the + * sampling rate as defined in `sentry_options`. + */ +SENTRY_EXPERIMENTAL_API void sentry_transaction_remove_sampled( + sentry_value_t transaction); + #ifdef __cplusplus } #endif diff --git a/src/sentry_value.c b/src/sentry_value.c index c45ce748b..c71c68ecf 100644 --- a/src/sentry_value.c +++ b/src/sentry_value.c @@ -1124,6 +1124,51 @@ sentry_value_new_stacktrace(void **ips, size_t len) return stacktrace; } +sentry_value_t +sentry_value_new_transaction(const char *name, const char *operation) +{ + sentry_value_t transaction = sentry_value_new_object(); + + sentry_transaction_set_name(transaction, name); + sentry_transaction_set_operation(transaction, operation); + + return transaction; +} + +void +sentry_transaction_set_name(sentry_value_t transaction, const char *name) +{ + sentry_value_t sv_name = sentry_value_new_string(name); + // TODO: Consider doing this checking right before sending or flushing + // the transaction. + if (sentry_value_is_null(sv_name) || sentry__string_eq(name, "")) { + sentry_value_decref(sv_name); + sv_name = sentry_value_new_string(""); + } + sentry_value_set_by_key(transaction, "name", sv_name); +} + +void +sentry_transaction_set_operation( + sentry_value_t transaction, const char *operation) +{ + sentry_value_set_by_key( + transaction, "op", sentry_value_new_string(operation)); +} + +void +sentry_transaction_set_sampled(sentry_value_t transaction, int sampled) +{ + sentry_value_set_by_key( + transaction, "sampled", sentry_value_new_bool(sampled)); +} + +void +sentry_transaction_remove_sampled(sentry_value_t transaction) +{ + sentry_value_remove_by_key(transaction, "sampled"); +} + static sentry_value_t sentry__get_or_insert_values_list(sentry_value_t parent, const char *key) { diff --git a/tests/unit/test_tracing.c b/tests/unit/test_tracing.c index 34cb331c9..cce9bbc7f 100644 --- a/tests/unit/test_tracing.c +++ b/tests/unit/test_tracing.c @@ -33,3 +33,43 @@ SENTRY_TEST(basic_tracing_context) sentry_value_decref(trace_context); sentry_value_decref(span); } + +SENTRY_TEST(basic_transaction) +{ + sentry_value_t tx_cxt = sentry_value_new_transaction(NULL, NULL); + TEST_CHECK(!sentry_value_is_null(tx_cxt)); + const char *tx_name + = sentry_value_as_string(sentry_value_get_by_key(tx_cxt, "name")); + TEST_CHECK_STRING_EQUAL(tx_name, ""); + const char *tx_op + = sentry_value_as_string(sentry_value_get_by_key(tx_cxt, "op")); + TEST_CHECK_STRING_EQUAL(tx_op, ""); + + sentry_value_decref(tx_cxt); + tx_cxt = sentry_value_new_transaction("", ""); + TEST_CHECK(!sentry_value_is_null(tx_cxt)); + tx_name = sentry_value_as_string(sentry_value_get_by_key(tx_cxt, "name")); + TEST_CHECK_STRING_EQUAL(tx_name, ""); + TEST_CHECK_STRING_EQUAL(tx_op, ""); + + sentry_value_decref(tx_cxt); + tx_cxt = sentry_value_new_transaction("honk.beep", "beepbeep"); + tx_name = sentry_value_as_string(sentry_value_get_by_key(tx_cxt, "name")); + TEST_CHECK_STRING_EQUAL(tx_name, "honk.beep"); + tx_op = sentry_value_as_string(sentry_value_get_by_key(tx_cxt, "op")); + TEST_CHECK_STRING_EQUAL(tx_op, "beepbeep"); + + sentry_transaction_set_name(tx_cxt, ""); + tx_name = sentry_value_as_string(sentry_value_get_by_key(tx_cxt, "name")); + TEST_CHECK_STRING_EQUAL(tx_name, ""); + + sentry_transaction_set_operation(tx_cxt, ""); + tx_op = sentry_value_as_string(sentry_value_get_by_key(tx_cxt, "op")); + TEST_CHECK_STRING_EQUAL(tx_op, ""); + + sentry_transaction_set_sampled(tx_cxt, 1); + TEST_CHECK( + sentry_value_is_true(sentry_value_get_by_key(tx_cxt, "sampled")) == 1); + + sentry_value_decref(tx_cxt); +} diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index 5ba245f18..4d697b156 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -5,6 +5,7 @@ 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_tracing_context) +XX(basic_transaction) XX(buildid_fallback) XX(concurrent_init) XX(count_sampled_events)