sentry-setup-tracing
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.
Best use case
sentry-setup-tracing is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
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.
Teams using sentry-setup-tracing should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/sentry-setup-tracing/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How sentry-setup-tracing Compares
| Feature / Agent | sentry-setup-tracing | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
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.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
# 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:
| Concept | Description |
|---------|-------------|
| **Trace** | Complete journey of a request across services |
| **Transaction** | Single instance of a service being called (root span) |
| **Span** | Individual unit of work within a transaction |
| **Sample Rate** | Percentage of transactions to capture (0-1) |
---
## JavaScript/TypeScript Configuration
### Step 1: Locate Sentry Init
Find the `Sentry.init()` call:
- Next.js: `instrumentation-client.ts`, `sentry.server.config.ts`, `sentry.edge.config.ts`
- React: `src/index.tsx` or entry file
- Node.js: Entry point or config file
- Vue/Angular: Main app initialization
### Step 2: Enable Tracing
#### Browser/React - Add browserTracingIntegration
```javascript
import * as Sentry from "@sentry/react"; // or @sentry/browser
Sentry.init({
dsn: "YOUR_DSN_HERE",
// Add browser tracing integration
integrations: [Sentry.browserTracingIntegration()],
// Set sample rate (1.0 = 100% for testing, lower for production)
tracesSampleRate: 1.0,
// Configure which URLs receive trace headers for distributed tracing
tracePropagationTargets: [
"localhost",
/^https:\/\/yourserver\.io\/api/,
],
});
```
#### Next.js - Configure All Init Files
**Client (`instrumentation-client.ts`):**
```typescript
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "YOUR_DSN_HERE",
tracesSampleRate: 1.0,
// Browser tracing is automatic in @sentry/nextjs
});
```
**Server (`sentry.server.config.ts`):**
```typescript
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "YOUR_DSN_HERE",
tracesSampleRate: 1.0,
});
```
**Edge (`sentry.edge.config.ts`):**
```typescript
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "YOUR_DSN_HERE",
tracesSampleRate: 1.0,
});
```
**Next.js 14+ App Router Requirement:**
For distributed tracing in App Router, add trace data to root layout metadata:
```typescript
// app/layout.tsx
import * as Sentry from "@sentry/nextjs";
export async function generateMetadata() {
return {
other: {
...Sentry.getTraceData(),
},
};
}
```
#### Node.js
```javascript
const Sentry = require("@sentry/node");
Sentry.init({
dsn: "YOUR_DSN_HERE",
tracesSampleRate: 1.0,
});
```
### Step 3: Configure Sampling
#### Option A: Uniform Sample Rate (Simple)
```javascript
Sentry.init({
// Capture 20% of all transactions
tracesSampleRate: 0.2,
});
```
#### Option B: Dynamic Sampling (Advanced)
```javascript
Sentry.init({
tracesSampler: ({ name, attributes, parentSampled }) => {
// Always skip health checks
if (name.includes("healthcheck")) {
return 0;
}
// Always capture auth transactions
if (name.includes("auth")) {
return 1;
}
// Sample comments at 1%
if (name.includes("comment")) {
return 0.01;
}
// Inherit parent sampling decision if available
if (typeof parentSampled === "boolean") {
return parentSampled;
}
// Default: 50%
return 0.5;
},
});
```
**Note:** If both `tracesSampleRate` and `tracesSampler` are set, `tracesSampler` takes precedence.
---
## Browser Tracing Integration Options
The `browserTracingIntegration()` accepts many configuration options:
```javascript
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,
}),
],
});
```
---
## Python Configuration
### Step 1: Enable Tracing
```python
import sentry_sdk
sentry_sdk.init(
dsn="YOUR_DSN_HERE",
traces_sample_rate=1.0, # 100% for testing
)
```
### Step 2: Configure Sampling
#### Uniform Rate
```python
sentry_sdk.init(
dsn="YOUR_DSN_HERE",
traces_sample_rate=0.2, # 20% of transactions
)
```
#### Dynamic Sampling
```python
def traces_sampler(sampling_context):
transaction_name = sampling_context.get("transaction_context", {}).get("name", "")
if "healthcheck" in transaction_name:
return 0
if "auth" in transaction_name:
return 1.0
# Inherit from parent if available
if sampling_context.get("parent_sampled") is not None:
return sampling_context["parent_sampled"]
return 0.5
sentry_sdk.init(
dsn="YOUR_DSN_HERE",
traces_sampler=traces_sampler,
)
```
---
## Ruby Configuration
### Enable Tracing
```ruby
Sentry.init do |config|
config.dsn = "YOUR_DSN_HERE"
config.traces_sample_rate = 1.0 # 100% for testing
end
```
### Dynamic Sampling
```ruby
Sentry.init do |config|
config.dsn = "YOUR_DSN_HERE"
config.traces_sampler = lambda do |sampling_context|
transaction_name = sampling_context[:transaction_context][:name]
return 0 if transaction_name.include?("healthcheck")
return 1.0 if transaction_name.include?("auth")
0.5 # Default 50%
end
end
```
---
## Custom Instrumentation
### JavaScript Custom Spans
#### Using startSpan (Recommended)
```javascript
// 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
```javascript
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
```javascript
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)
```javascript
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)
```python
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
```python
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
```python
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
```python
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:
```javascript
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:
```javascript
// 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):
```javascript
// 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:
| Operation | Use Case |
|-----------|----------|
| `http.client` | Outgoing HTTP requests |
| `http.server` | Incoming HTTP requests |
| `db` | Database operations |
| `db.query` | Database queries |
| `cache` | Cache operations |
| `task` | Background tasks |
| `function` | Function execution |
| `ui.render` | UI rendering |
| `ui.action` | User interactions |
| `serialize` | Serialization |
| `middleware` | Middleware 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:
```javascript
Sentry.init({
dsn: "YOUR_DSN_HERE",
// Do NOT include tracesSampleRate or tracesSampler
});
```
---
## Production Sampling Recommendations
| Traffic Level | Recommended Rate |
|---------------|-----------------|
| Development/Testing | `1.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:
```javascript
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
```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
```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
---
## Common Issues and Solutions
### Issue: Transactions not appearing
**Solutions:**
1. Verify `tracesSampleRate > 0` or `tracesSampler` returns > 0
2. Check DSN is correct
3. For browser: Ensure `browserTracingIntegration()` is added
4. Wait a few minutes for data to process
### Issue: Distributed traces not connected
**Solutions:**
1. Check `tracePropagationTargets` includes your API URLs
2. Verify CORS allows `sentry-trace` and `baggage` headers
3. For SSR: Ensure trace meta tags are rendered
### Issue: Too many transactions (high volume)
**Solutions:**
1. Lower `tracesSampleRate`
2. Use `tracesSampler` to filter by transaction name
3. Use `shouldCreateSpanForRequest` to skip health checks
### Issue: Spans not nested correctly
**Solutions:**
1. Ensure parent span is still active when creating child
2. Use `startSpan` callback pattern (not manual)
3. For browser: Consider `parentSpanIsAlwaysRootSpan: false`
---
## Summary Checklist
```markdown
## Sentry Tracing Setup Complete
### Configuration Applied:
- [ ] `tracesSampleRate` or `tracesSampler` configured
- [ ] Browser: `browserTracingIntegration()` added
- [ ] `tracePropagationTargets` configured for APIs
- [ ] Next.js App Router: `getTraceData()` in metadata
### Sampling Strategy:
- [ ] Development: 100% sampling for testing
- [ ] Production: Appropriate rate based on traffic
### Custom Instrumentation (if applicable):
- [ ] Critical paths instrumented with custom spans
- [ ] Consistent `op` values used
### Next Steps:
1. Trigger some requests in your application
2. Check Sentry > Performance for transactions
3. Review trace waterfalls for span hierarchy
4. Adjust sampling rates based on volume
```
---
## 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) |Related Skills
setup-tanstack-start
Bootstrap a new web project with TanStack Start, React, Tailwind CSS v4, and shadcn/ui on top of the base tooling stack. Consult this skill whenever creating a web app, setting up a frontend project, starting a React application, or initializing anything involving TanStack Start, TanStack Router, TanStack Query, Tailwind, shadcn, or Vite.
setup-project
Setup Claude Code Configuration with full RALPH autonomous development integration
setup-node
Sets up Node.js/TypeScript development environment with npm/yarn, dependencies, ESLint, Prettier, testing (Jest/Vitest), and TypeScript type checking. Ensures consistent tooling configuration. Use when starting work on Node.js/TypeScript projects, after cloning repositories, setting up CI/CD, or troubleshooting environment issues.
setup-earl
Installs Earl, configures MCP integration for your agent platform, writes CLAUDE.md instructions, and routes to template creation or migration. Use when setting up Earl for the first time, when a new developer is onboarding to a project that uses Earl, or when Earl needs to be connected to an agent platform.
setup-claude-code
Claude Code 프로젝트 설정 생성
setup-cdk-templates
Use when creating CLAUDE.md files or .claude/ directories - detects project type, generates appropriate templates, and scaffolds Claude configuration with commands and hooks
setup-api-key
Guide users through obtaining and configuring a Vapi API key. Use when the user needs to set up Vapi, when API calls fail due to missing keys, or when the user mentions needing access to Vapi's voice AI platform.
sentry-setup-metrics
Setup Sentry Metrics in any project. Use this when asked to add Sentry metrics, track custom metrics, setup counters/gauges/distributions, or instrument application performance metrics. Supports JavaScript, TypeScript, Python, React, Next.js, and Node.js.
sentry-setup-logging
Setup Sentry Logging in any project. Use this when asked to add Sentry logs, enable structured logging, setup console log capture, or integrate logging with Sentry. Supports JavaScript, TypeScript, Python, Ruby, React, Next.js, and other frameworks.
sentry-python-setup
Setup Sentry in Python apps. Use when asked to add Sentry to Python, install sentry-sdk, or configure error monitoring for Python applications, Django, Flask, FastAPI.
sentry-python-sdk
Full Sentry SDK setup for Python. Use when asked to "add Sentry to Python", "install sentry-sdk", "setup Sentry in Python", or configure error monitoring, tracing, profiling, logging, metrics, crons, or AI monitoring for Python applications. Supports Django, Flask, FastAPI, Celery, Starlette, AIOHTTP, Tornado, and more.
sentry-debugger
Debug production issues using Sentry error tracking API. Use when Claude needs to investigate production errors, crashes, or issues by fetching error data from Sentry - including stack traces, user context, breadcrumbs, and error frequency. Triggers on requests like "check Sentry for errors", "debug this production issue", "what's causing crashes", "investigate errors in [project]", or when users share Sentry issue URLs.