Skip to content

Commit

Permalink
feat(tracing): Drop unfinished spans from a transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
relaxolotl committed Dec 18, 2021
1 parent e32d01e commit 9e9ed29
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
4 changes: 4 additions & 0 deletions examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ main(int argc, char **argv)
sentry_value_t grandchild_ctx
= sentry_span_start_child(child_ctx, "littlest.teapot", NULL);

sentry_value_t unfinished_ctx
= sentry_span_start_child(child_ctx, "large.teapot", NULL);

sentry_value_decref(unfinished_ctx);
sentry_span_finish(grandchild_ctx);
sentry_span_finish(child_ctx);
}
Expand Down
19 changes: 18 additions & 1 deletion src/sentry_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,24 @@ sentry_transaction_finish()
sentry_value_remove_by_key(tx, "description");
sentry_value_remove_by_key(tx, "status");

// TODO: prune unfinished child spans
sentry_value_t spans = sentry_value_get_by_key(tx, "spans");
size_t span_count = sentry_value_get_length(spans);
// Go backwards to avoid accidentally skipping elements
for (size_t i = span_count; i > 0; i--) {
// TODO: Assume that tags and data from scope do not need to be merged
// into spans. This may be completely wrong.
bool should_remove = false;
{
sentry_value_t span = sentry_value_get_by_index(spans, i - 1);
should_remove = sentry_value_is_null(
sentry_value_get_by_key(span, "timestamp"));
}
if (should_remove) {
SENTRY_DEBUG("dropped an unfinished span from transaction");
sentry_value_remove_by_index(spans, i - 1);
}
}

// This decrefs for us, generates an event ID, merges scope
sentry__capture_event(tx);
}
Expand Down
55 changes: 55 additions & 0 deletions tests/unit/test_tracing.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,5 +430,60 @@ SENTRY_TEST(overflow_spans)
sentry_close();
}

static void
check_spans(sentry_envelope_t *envelope, void *data)
{
uint64_t *called = data;
*called += 1;

sentry_value_t transaction = sentry_envelope_get_transaction(envelope);
TEST_CHECK(!sentry_value_is_null(transaction));

size_t span_count = sentry_value_get_length(
sentry_value_get_by_key(transaction, "spans"));
TEST_CHECK_INT_EQUAL(span_count, 1);

sentry_envelope_free(envelope);
}

SENTRY_TEST(drop_unfinished_spans)
{
uint64_t called_transport = 0;

sentry_options_t *options = sentry_options_new();
sentry_options_set_dsn(options, "https://[email protected]/42");

sentry_transport_t *transport = sentry_transport_new(check_spans);
sentry_transport_set_state(transport, &called_transport);
sentry_options_set_transport(options, transport);

sentry_options_set_traces_sample_rate(options, 1.0);
sentry_options_set_max_spans(options, 2);
sentry_init(options);

sentry_value_t tx_cxt = sentry_value_new_transaction("wow!", NULL);
sentry_transaction_start(tx_cxt);

sentry_value_t child
= sentry_span_start_child(sentry_value_new_null(), "honk", "goose");
TEST_CHECK(!sentry_value_is_null(child));

sentry_value_t grandchild = sentry_span_start_child(child, "beep", "car");
TEST_CHECK(!sentry_value_is_null(grandchild));
sentry_span_finish(grandchild);

sentry_value_t scope_tx = sentry__scope_get_span();
TEST_CHECK_INT_EQUAL(
sentry_value_get_length(sentry_value_get_by_key(scope_tx, "spans")), 2);

sentry_transaction_finish();

sentry_value_decref(child);

sentry_close();

TEST_CHECK_INT_EQUAL(called_transport, 1);
}

#undef IS_NULL
#undef CHECK_STRING_PROPERTY
1 change: 1 addition & 0 deletions tests/unit/tests.inc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ XX(child_spans)
XX(concurrent_init)
XX(count_sampled_events)
XX(custom_logger)
XX(drop_unfinished_spans)
XX(dsn_parsing_complete)
XX(dsn_parsing_invalid)
XX(dsn_store_url_with_path)
Expand Down

0 comments on commit 9e9ed29

Please sign in to comment.