Custom Instrumentation

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

This is valid for all JavaScript SDKs (both backend and frontend) and works independently of the Express, Http, and BrowserTracing integrations.

Copied
const transaction = Sentry.startTransaction({ name: "test-transaction" });
const span = transaction.startChild({ op: "functionX" }); // This function returns a Span
// functionCallX
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 on your page:

Copied
// Let's say this function is invoked when a user clicks on the checkout button of your shop
function shopCheckout() {
  // This will create a new Transaction for you
  const transaction = Sentry.startTransaction({ name: "shopCheckout" });
  // Set transaction on scope to associate with errors and get included span instrumentation
  // If there's currently an unfinished transaction, it may be dropped
  Sentry.getCurrentHub().configureScope(scope => scope.setSpan(transaction));

  // Assume this function makes an xhr/fetch call
  const result = validateShoppingCartOnServer();

  const span = transaction.startChild({
    data: {
      result
    },
    op: 'task',
    description: `processing shopping cart result`,
  });
  try {
    processAndValidateShoppingCart(result);
    span.setStatus(SpanStatus.Ok);
  } catch (err) {
    span.setStatus(SpanStatus.UnknownError);
    throw err;
  } finally {
    span.finish();
    transaction.finish();
  }
}

This example will send a transaction shopCheckout to Sentry. The transaction will contain a task span that measures how long processAndValidateShoppingCart took. Finally, the call to transaction.finish() will finish the transaction and send it to Sentry.

You can also take advantage of promises when creating spans for async operations. Keep in mind, though, that a span must finish before transaction.finish() is called to be included in the transaction.

For example:

Copied
function processItem(item, transaction) {
  const span = transaction.startChild({
    op: "http",
    description: `GET /items/:item-id`,
  });

  return new Promise((resolve, reject) => {
    http.get(`/items/${item.id}`, response => {
      response.on("data", () => {});
      response.on("end", () => {
        span.setTag("http.status_code", response.statusCode);
        span.setData("http.foobarsessionid", getFoobarSessionid(response));
        span.finish();
        resolve(response);
      });
    });
  });
}

Retrieve a Transaction

In cases where you want to attach spans to an already ongoing transaction, such as when grouping transactions, you can use Sentry.getCurrentHub().getScope().getTransaction(). This function will return a Transaction object when there is a running transaction on the scope, otherwise it returns undefined. If you are using our BrowserTracing integration, by default we attach the transaction to the Scope, so you could do something like this:

Copied
function myJsFunction() {
  const transaction = Sentry.getCurrentHub()
    .getScope()
    .getTransaction();
  if (transaction) {
    const span = transaction.startChild({
      op: "encode",
      description: "parseAvatarImages",
    });

    try {
      // Do something
      span.setStatus(SpanStatus.Ok);
    } catch (err) {
      span.setStatus(SpanStatus.UnknownError);
      throw err;
    } finally {
      span.finish();
    }
  }
}