Performance Monitoring

When integrating Sentry with an Express application, you can leverage provided middlewares to automatically instrument and monitor the performance of your application.

Copied
const Sentry = require("@sentry/node");
const express = require("express");
const app = express();

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    // enable Express.js middleware tracing
    new Sentry.Integrations.Express({
      // to trace all requests to the default router
      app,
      // alternatively, you can specify the routes you want to trace:
      // router: someRouter,
    }),
  ],

  // We recommend adjusting this value in production, or using tracesSampler
  // for finer control
  tracesSampleRate: 1.0,
});

// RequestHandler creates a separate execution context, so that all
// transactions/spans/breadcrumbs are isolated across requests
app.use(Sentry.Handlers.requestHandler());
// TracingHandler creates a trace for every incoming request
app.use(Sentry.Handlers.tracingHandler());

// the rest of your app

// The error handler must be before any other error middleware and after all controllers
app.use(Sentry.Handlers.errorHandler());

app.listen(3000);

You can also manually create transactions in your app:

Copied
const Sentry = require("@sentry/node");
const http = require("http");

const transaction = Sentry.startTransaction({
  op: "transaction",
  name: "My Transaction",
});

// Note that we set the transaction as the span on the scope.
// This step makes sure that if an error happens during the lifetime of the transaction
// the transaction context will be attached to the error event
Sentry.getCurrentScope().setSpan(transaction);

let request;

try {
  // this should generate an http span
  request = http.get("http://sentry.io", (res) => {
    console.log(`STATUS: ${res.statusCode}`);
    console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
  });

  // this error event should have trace context
  foo();
} catch (err) {
  Sentry.captureException(err);
}

request.on("close", () => {
  transaction.finish();
});

To instrument a specific region of your code, you can create a transaction to capture it.

The following example creates a transaction for a part of the code that contains an expensive operation (for example, processItem), and sends the result to Sentry:

Copied
app.use(function processItems(req, res, next) {
  const item = getFromQueue();
  const transaction = Sentry.startTransaction({
    op: "task",
    name: item.getTransaction(),
  });

  // processItem may create more spans internally (see next examples)
  processItem(item, transaction).then(() => {
    transaction.finish();
    next();
  });
});

In cases where you want to attach Spans to an already ongoing Transaction you can use Sentry.getActiveTransaction(). This function will return a Transaction in case there is a running Transaction otherwise it returns undefined. If you are using our Express integration by default we attach the Transaction to the Scope. So you could do something like this:

Copied
app.get("/success", function successHandler(req, res) {
  const transaction = Sentry.getActiveTransaction();

  if (transaction) {
    let span = transaction.startChild({
      op: "encode",
      description: "parseAvatarImages",
    });
    // Do something
    span.finish();
  }
  res.status(200).end();
});
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").