Performance Monitoring

By default, Sentry error events will not get trace context unless you configure the scope with the transaction, as illustrated in the code sample below.

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

  dsn: "",
  integrations: [
    // enable HTTP calls tracing
    new Sentry.Integrations.Http({ tracing: true }),
    // enable Express.js middleware tracing
    new SentryTracing.Integrations.Express({
      // to trace all requests to the default router
      // 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 using domains, so that every
// transaction/span/breadcrumb is attached to its own Hub instance
// TracingHandler creates a trace for every incoming request

// the rest of your app

// The error handler must be before any other error middleware and after all controllers


You can also manually create transactions in your app:

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.configureScope(scope => {

let request;

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

  // this error event should have trace context
} catch (err) {

request.on("close", () => {

Custom Instrumentation

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:

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(() => {

Retrieving a Transaction

In cases where you want to attach Spans to an already ongoing Transaction you can use Sentry.getCurrentHub().getScope().getTransaction(). 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:

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

  if (transaction) {
    let span = transaction.startChild({
      op: "encode",
      description: "parseAvatarImages",
    // Do something

Connecting Services

If you are also using Performance Monitoring for JavaScript, depending on where your request originates, you can connect traces:

  1. For requests that start in your backend, by adding a meta tag in your HTML template that contains
    tracingThe process of logging the events that took place during a request, often across multiple services.
  2. For requests that start in JavaScript, by the SDK setting a header on requests to your backend.

Otherwise, backend services with Performance Monitoring connect automatically.

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