Custom Instrumentation

Learn how to capture performance data on any action in your app.

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

Copied
// Transaction can be started by providing, at minimum, the name and the operation
var transaction = SentrySdk.StartTransaction(
  "test-transaction-name",
  "test-transaction-operation"
);

// Transactions can have child spans (and those spans can have child spans as well)
var span = transaction.StartChild("test-child-operation");

// ...
// (Perform the operation represented by the span/transaction)
// ...

span.Finish(); // Mark the span as finished
transaction.Finish(); // Mark the transaction as finished and 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 invoked when a user clicks on the checkout button of your shop
public async Task PerformCheckoutAsync()
{
  // This will create a new Transaction for you
  var transaction = SentrySdk.StartTransaction(
      "checkout", // name
      "perform-checkout" // operation
  );

  // Set transaction on scope to associate with errors and get included span instrumentation
  // If there's currently an unfinished transaction, it may be dropped
  SentrySdk.ConfigureScope(scope => scope.Transaction = transaction);

  // Validate the cart
  var validationSpan = transaction.StartChild(
      "validation", // operation
      "validating shopping cart" // description
  );

  await ValidateShoppingCartAsync();

  validationSpan.Finish();

  // Process the order
  var processSpan = transaction.StartChild(
      "process", // operation
      "processing shopping cart" // description
  )

  await ProcessShoppingCartAsync();

  processSpan.Finish();

  transaction.Finish();
}

This example will send a transaction checkout to Sentry. The transaction will contain a validation span that measures how long ValidateShoppingCartAsync took and a process span that measures ProcessShoppingCartAsync. 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 SentrySdk.GetSpan(). If there is a running Transaction or Span currently on the scope, this method will return a SentryTransaction or Span; otherwise, it returns null.

Copied
var span = SentrySdk.GetSpan();

if (span == null)
{
    span = SentrySdk.StartTransaction("task", "op");
}
else
{
    span = span.StartChild("subtask");
}

You can add data attributes to your transactions. This data is visible and queryable in the trace explorer in Sentry. Data attributes can be of type string, number or boolean, as well as arrays of these types:

Copied
var transaction = SentrySdk.StartTransaction("ProcessOrderBatch()", "task");
SentrySdk.ConfigureScope(scope => scope.Transaction = transaction);
transaction.SetData("my-data-attribute-1", "value1");
transaction.SetData("my-data-attribute-2", 42);
transaction.SetData("my-data-attribute-3", true);

transaction.SetData("my-data-attribute-4", new[] {"value1", "value2", "value3"});
transaction.SetData("my-data-attribute-5", new[] {42, 43, 44});
transaction.SetData("my-data-attribute-6", new[] {true, false, true});

You can add data attributes to your transactions. This data is visible and queryable in the trace explorer in Sentry. Data attributes can be of type string, number or boolean, as well as arrays of these types:

Copied
var span = parent.StartChild("task", "operation");
span.SetData("my-data-attribute-1", "value1");
span.SetData("my-data-attribute-2", 42);
span.SetData("my-data-attribute-3", true);

span.SetData("my-data-attribute-4", new[] {"value1", "value2", "value3"});
span.SetData("my-data-attribute-5", new[] {42, 43, 44});
span.SetData("my-data-attribute-6", new[] {true, false, true});

To add an attribute to all spans and transactions, use the SetBeforeSendTransaction callback:

Copied
options =>
{
    options.SetBeforeSendTransaction(transaction =>
    {
        // Set the attribute on the root span (transaction's trace context)
        transaction.Contexts.Trace.SetData("myAttribute", "myValue");

        // And on all child spans
        foreach (var span in transaction.Spans)
        {
            span.SetData("myAttribute", "myValue");
        }

        return transaction;
    });
};
Was this helpful?
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").