Labsco
getsentry logo

sentry-setup-tracing

โœ“ Officialโ˜… 2

by sentry ยท part of getsentry/sentry-for-cursor

Setup Sentry Tracing (Performance Monitoring) in any project. Use this when asked to add performance monitoring, enable tracing, track transactions/spans, or instrument application performance. Supports JavaScript, TypeScript, Python, Ruby, React, Next.js, and Node.js.

๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅโœ“ VerifiedFreeQuick setup
๐Ÿงฐ Not standalone. This skill ships with getsentry/sentry-for-cursor and only works together with that tool โ€” install the tool first, then add this skill.

This is the playbook your agent receives when the skill activates โ€” you don't need to read it to use the skill, but it's here to audit before installing.

Setup Sentry Tracing

This skill helps configure Sentry's Tracing (Performance Monitoring) to track application performance, measure latency, and create distributed traces across services.

When to Use This Skill

Invoke this skill when:

  • User asks to "setup tracing" or "enable performance monitoring"
  • User wants to "track transactions" or "measure latency"
  • User requests "distributed tracing" or "span instrumentation"
  • User mentions tracking API response times or page load performance
  • User asks about tracesSampleRate or custom spans

Platform Detection

Before configuring, detect the project's platform:

JavaScript/TypeScript

Check package.json for:

  • @sentry/nextjs - Next.js
  • @sentry/react - React
  • @sentry/node - Node.js
  • @sentry/browser - Browser/vanilla JS
  • @sentry/vue - Vue
  • @sentry/angular - Angular
  • @sentry/sveltekit - SvelteKit

Python

Check for sentry-sdk in requirements

Ruby

Check for sentry-ruby in Gemfile


Core Concepts

Explain these concepts to the user:

ConceptDescription
TraceComplete journey of a request across services
TransactionSingle instance of a service being called (root span)
SpanIndividual unit of work within a transaction
Sample RatePercentage of transactions to capture (0-1)

Browser Tracing Integration Options

The browserTracingIntegration() accepts many configuration options:

Sentry.init({
  integrations: [
    Sentry.browserTracingIntegration({
      // Trace propagation targets (which URLs get trace headers)
      tracePropagationTargets: ["localhost", /^https:\/\/api\./],

      // Modify spans before creation (e.g., parameterize URLs)
      beforeStartSpan: (context) => {
        return {
          ...context,
          name: context.name.replace(/\/users\/\d+/, "/users/:id"),
        };
      },

      // Filter unwanted spans
      shouldCreateSpanForRequest: (url) => {
        return !url.includes("healthcheck");
      },

      // Timing configurations
      idleTimeout: 1000,        // ms before finishing idle spans
      finalTimeout: 30000,      // max span duration
      childSpanTimeout: 15000,  // max child span duration

      // Feature toggles
      instrumentNavigation: true,  // Track URL changes
      instrumentPageLoad: true,    // Track initial page load
      enableLongTask: true,        // Track long tasks
      enableInp: true,             // Track Interaction to Next Paint

      // INP sampling (separate from tracesSampleRate)
      interactionsSampleRate: 1.0,
    }),
  ],
});

Custom Instrumentation

JavaScript Custom Spans

// Synchronous operation
const result = Sentry.startSpan(
  { name: "expensive-calculation", op: "function" },
  () => {
    return calculateSomething();
  }
);

// Async operation
const result = await Sentry.startSpan(
  { name: "fetch-user-data", op: "http.client" },
  async () => {
    const response = await fetch("/api/user");
    return response.json();
  }
);

// With attributes
const result = await Sentry.startSpan(
  {
    name: "process-order",
    op: "task",
    attributes: {
      "order.id": orderId,
      "order.amount": amount,
    },
  },
  async () => {
    return processOrder(orderId);
  }
);

Nested Spans

await Sentry.startSpan({ name: "checkout-flow", op: "transaction" }, async () => {
  // Child span 1
  await Sentry.startSpan({ name: "validate-cart", op: "validation" }, async () => {
    await validateCart();
  });

  // Child span 2
  await Sentry.startSpan({ name: "process-payment", op: "payment" }, async () => {
    await processPayment();
  });

  // Child span 3
  await Sentry.startSpan({ name: "send-confirmation", op: "email" }, async () => {
    await sendConfirmationEmail();
  });
});

Manual Span Control

function middleware(req, res, next) {
  return Sentry.startSpanManual({ name: "middleware", op: "middleware" }, (span) => {
    res.once("finish", () => {
      span.setStatus({ code: res.statusCode < 400 ? 1 : 2 });
      span.end();
    });
    return next();
  });
}

Inactive Spans (Browser)

let checkoutSpan;

// Start inactive span
function onStartCheckout() {
  checkoutSpan = Sentry.startInactiveSpan({ name: "checkout-flow" });
  Sentry.setActiveSpanInBrowser(checkoutSpan);
}

// End when done
function onCompleteCheckout() {
  checkoutSpan?.end();
}

Python Custom Spans

Using Decorator (Simplest)

import sentry_sdk

@sentry_sdk.trace
def expensive_function():
    # Automatically creates a span
    return do_work()

# With parameters (SDK 2.35.0+)
@sentry_sdk.trace(op="database", name="fetch-users")
def fetch_users():
    return db.query(User).all()

Using Context Manager

import sentry_sdk

def process_order(order_id):
    with sentry_sdk.start_span(name="process-order", op="task") as span:
        span.set_data("order.id", order_id)

        # Nested span
        with sentry_sdk.start_span(name="validate-order", op="validation"):
            validate(order_id)

        with sentry_sdk.start_span(name="charge-payment", op="payment"):
            charge(order_id)

        return {"success": True}

Manual Transaction

import sentry_sdk

with sentry_sdk.start_transaction(op="task", name="batch-process") as transaction:
    for item in items:
        with sentry_sdk.start_span(name=f"process-item-{item.id}"):
            process(item)

    transaction.set_tag("items_processed", len(items))

Centralized Configuration

sentry_sdk.init(
    dsn="YOUR_DSN_HERE",
    traces_sample_rate=1.0,
    functions_to_trace=[
        {"qualified_name": "myapp.services.process_order"},
        {"qualified_name": "myapp.services.send_notification"},
    ],
)

Distributed Tracing

How It Works

Sentry propagates trace context via HTTP headers:

  • sentry-trace: Contains trace ID, span ID, sampling decision
  • baggage: Contains additional trace metadata

Configure Trace Propagation Targets

Only URLs matching these patterns receive trace headers:

Sentry.init({
  tracePropagationTargets: [
    "localhost",
    "https://api.yourapp.com",
    /^https:\/\/.*\.yourapp\.com\/api/,
  ],
});

Server-Side Rendering (Meta Tags)

For SSR apps, inject trace data in HTML:

// Server renders these meta tags
const traceData = Sentry.getTraceData();
// Include in HTML <head>:
// <meta name="sentry-trace" content="..." />
// <meta name="baggage" content="..." />

The browser SDK automatically reads these and continues the trace.

Manual Propagation

For non-HTTP channels (WebSockets, message queues):

// Sender
const traceData = Sentry.getTraceData();
sendMessage({
  ...payload,
  _traceHeaders: traceData,
});

// Receiver
Sentry.continueTrace(
  {
    sentryTrace: message._traceHeaders["sentry-trace"],
    baggage: message._traceHeaders["baggage"],
  },
  () => {
    processMessage(message);
  }
);

Common Operation Types

Use consistent op values for better organization:

OperationUse Case
http.clientOutgoing HTTP requests
http.serverIncoming HTTP requests
dbDatabase operations
db.queryDatabase queries
cacheCache operations
taskBackground tasks
functionFunction execution
ui.renderUI rendering
ui.actionUser interactions
serializeSerialization
middlewareMiddleware execution

What Gets Automatically Traced

Browser (with browserTracingIntegration)

  • Page loads
  • Navigation/route changes
  • XHR/fetch requests
  • Long tasks
  • Interaction to Next Paint (INP)

Next.js

  • API routes
  • Server components
  • Page renders
  • Data fetching

Node.js (with framework integrations)

  • HTTP requests (Express, Fastify, etc.)
  • Database queries (with ORM integrations)
  • External API calls

Python (with framework integrations)

  • Django views, middleware, templates
  • Flask routes
  • FastAPI endpoints
  • SQLAlchemy queries
  • Celery tasks

Disabling Tracing

Important: Setting tracesSampleRate: 0 does NOT disable tracing - it still processes traces but never sends them.

To fully disable tracing, omit both sampling options:

Sentry.init({
  dsn: "YOUR_DSN_HERE",
  // Do NOT include tracesSampleRate or tracesSampler
});

Production Sampling Recommendations

Traffic LevelRecommended Rate
Development/Testing1.0 (100%)
Low traffic (<1K req/min)0.5 - 1.0
Medium traffic (1K-10K req/min)0.1 - 0.5
High traffic (>10K req/min)0.01 - 0.1

Use dynamic sampling to capture more of important transactions:

tracesSampler: ({ name }) => {
  // Always capture errors and slow endpoints
  if (name.includes("checkout") || name.includes("payment")) {
    return 1.0;
  }
  // Sample most at 10%
  return 0.1;
},

Verification Steps

After setup, verify tracing is working:

JavaScript

// Trigger a test transaction
await Sentry.startSpan(
  { name: "test-transaction", op: "test" },
  async () => {
    console.log("Tracing test");
    await new Promise(resolve => setTimeout(resolve, 100));
  }
);

Python

with sentry_sdk.start_transaction(op="test", name="test-transaction"):
    print("Tracing test")

Check in Sentry:

  1. Go to Performance section
  2. Look for your test transaction
  3. Verify spans appear in the trace waterfall

Summary Checklist


## Quick Reference

| Platform | Enable Tracing | Custom Span |
|----------|---------------|-------------|
| JS/Browser | `tracesSampleRate` + `browserTracingIntegration()` | `Sentry.startSpan()` |
| Next.js | `tracesSampleRate` (auto-integrated) | `Sentry.startSpan()` |
| Node.js | `tracesSampleRate` | `Sentry.startSpan()` |
| Python | `traces_sample_rate` | `@sentry_sdk.trace` or `start_span()` |
| Ruby | `traces_sample_rate` | `start_span()` |

| Sampling Option | Purpose |
|-----------------|---------|
| `tracesSampleRate` | Uniform percentage (0-1) |
| `tracesSampler` | Dynamic function (takes precedence) |