Custom Instrumentation

To instrument certain regions of your code, you can create transactions to capture them.

Copied
// Transaction can be started by providing the name and the operation
let tx_ctx = sentry::TransactionContext::new(
    "transaction name",
    "transaction operation",
);
let transaction = sentry::start_transaction(tx_ctx);

// Transactions can have child spans, and those spans can have child spans as well.
let span = transaction.start_child("span operation", "span description");

// ...
// Perform your operations
// ...

span.finish(); // Remember that only finished spans will be sent with the transaction
transaction.finish(); // Finishing the transaction will send it to Sentry

For example, if you want to create a transaction for a user interaction in your application:

Copied
// Let's say this method is called in a background thread when a user clicks on the checkout button of your shop
fn perform_checkout() {
    // This will create a new Transaction for you
    let tx_ctx = sentry::TransactionContext::new(
        "checkout",
        "perform-checkout",
    );
    let transaction = sentry::start_transaction(tx_ctx);

    // Validate the cart
    let validation_span = transaction.start_child(
        "validation",
        "validating shopping cart",
    );

    validate_shopping_cart() //Some long process, maybe a sync http request.

    validation_span.finish();

    // Process the order
    let process_span = transaction.start_child(
        "process",
        "processing shopping cart",
    )

    process_shopping_cart() //Another time consuming process.

    process_span.finish();

    transaction.finish();
}

This example will send a transaction named checkout to Sentry. The transaction will contain a validation span that measures how long validate_shopping_cart() took and a process span that measures process_shopping_cart(). Finally, the call to transaction.finish() will finish the transaction and send it to Sentry.

In cases where you want to attach spans to an already ongoing transaction, you can use Scope::get_span. This method will return a TransactionOrSpan in case there is a running transaction or span; otherwise it returns None.

Transactions or spans need to be manually attached to the scope using Scope::set_span.

Copied
// Retrieve the currently running span
let parent_span = sentry::configure_scope(|scope| scope.get_span());

let span: sentry::TransactionOrSpan = match &parent_span {
    Some(parent) => parent.start_child("subtask", "description").into(),
    None => {
        let ctx = sentry::TransactionContext::new("task", "op");
        sentry::start_transaction(ctx).into()
    }
};

// Set the currently running span
sentry::configure_scope(|scope| scope.set_span(Some(span)));

Special care must be taken when spawning operations as independent threads or asynchronous tasks.

In situations where the computation can run longer than the calling context, you should always start a new transaction. The SDK offers the TransactionContext::continue_from_span method to make that more convenient.

Copied
let parent_span = sentry::configure_scope(|scope| scope.get_span());
// Create a new transaction as an independent continuation
let ctx = sentry::TransactionContext::continue_from_span(
    "A long-running spawned task",
    "spawned_task",
    parent_span,
);

let task = async move {
  let transaction = sentry::start_transaction(ctx);
  // Set the newly created transaction as the *current span*
  sentry::configure_scope(|scope| scope.set_span(Some(transaction.clone().into())));

  // Do the actual computation
  // ...

  // Finish the span and send it to sentry
  transaction.finish();
  // The task gets a
}.bind_hub(Hub::new_from_top(Hub::current()));

task::spawn(task);

Sentry errors can be linked with transactions and spans.

Errors reported to Sentry while a transaction or span is bound to the scope are linked automatically:

Copied
let tx_ctx = sentry::TransactionContext::new(
    "checkout",
    "perform-checkout",
);
let transaction = sentry::start_transaction(tx_ctx);

// Bind the transaction / span to the scope:
sentry::configure_scope(|scope| scope.set_span(Some(transaction.into())));

// The error is linked to the transaction / span:
let err = "NaN".parse::<usize>().unwrap_err();
sentry::capture_error(&err);

transaction.finish();
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").