Skip to main content
rule

sentry — Cursor rule: error tracking and tracing done right

A Cursor rule that pins down how Sentry gets initialized in a project: entry point, env vars, context, and the cases where global init breaks things.

Install into Cursor · Manually: put the files in place All methods and platforms ↓
.cursor/rules/sentry.mdc
Open on GitHub

What sentry does

The sentry.mdc file lives in .cursor/rules/ and attaches to every task through globs: **/*. Cursor keeps its guidance in context whenever you touch Sentry setup, add tracing, or dig into a crash.

It covers initialization order: the SDK goes in once, at the application entry point, with DSN, environment and release read from environment variables. Bootstrap examples are given for Python and TypeScript, plus a separate section on AWS Lambda. Event context gets its own part — user, tags, and arbitrary data attached via push_scope.

One section is a hard no on Sentry.init() inside shared environments such as browser extensions and VS Code extensions. The rule wants a manually built client with integrations that depend on global state filtered out, because a global init pollutes someone else's runtime and leaks data. Read that part before wiring Sentry into an extension.

There is also an OpenTelemetry path: spans reach Sentry through SentrySpanProcessor, so existing instrumentation stays as it is.

What it helps with

  • initialize Sentry at the app entry point instead of a random module
  • move DSN, environment and release into environment variables
  • attach user context and tags to an error event
  • wire Sentry into AWS Lambda without extra wrappers
  • route OpenTelemetry spans to Sentry without rewriting instrumentation

Example prompts for the agent

  • add Sentry initialization to the app entry point following the sentry rule
  • set up OpenTelemetry span export to Sentry
  • review my Sentry init code against the sentry rule

How to install sentry

Manually: put the files in place

.cursor/rules/sentry.mdc

Frontmatter: description, globs, alwaysApply

Step by step, with commands for each platform: Cursor rules: .mdc files, four modes and what replaced .cursorrules

Questions about sentry

How do I install the sentry rule in Cursor?

Copy the file to .cursor/rules/sentry.mdc. Cursor picks it up on its own, since the rule declares globs: **/*.

What does the sentry rule do?

It sets mandatory Sentry practices: early centralized initialization, env vars for DSN and release, event context, OpenTelemetry tracing, and isolated clients for shared environments.

Can I call Sentry.init() in a browser extension?

The rule forbids it. Global init pollutes state and leaks data, so you build a dedicated client with the global-state integrations filtered out.

Source text

sentry.mdc · CC0-1.0
---
description: Definitive guidelines for integrating and using Sentry for error tracking and performance monitoring, ensuring optimal setup, performance, and debuggability across all applications.
globs: **/*
---
# Sentry Best Practices

Sentry is our definitive platform for error tracking and performance monitoring. Proper integration ensures we debug faster, ship more reliably, and maintain high application health. This guide outlines the mandatory best practices for all projects.

## 1. Code Organization and Initialization

Always initialize the Sentry SDK early in your application's bootstrap process. This ensures maximum coverage for errors and performance tracing.

### 1.1. Early and Centralized Initialization

Initialize Sentry once, as close to your application's entry point as possible. Use environment variables for sensitive data like DSN and for configuration that varies by environment.

❌ **BAD: Late or Scattered Initialization**
```python
# app/views.py (Django) or a random module
import sentry_sdk

def my_function():
    if not sentry_sdk.is_initialized(): # Don't do this, it's too late and prone to race conditions
        sentry_sdk.init(dsn="YOUR_DSN")
    # ...
```

✅ **GOOD: Application Bootstrap (Python Example)**
```python
# app.py or wsgi.py/asgi.py for web apps
import os
import sentry_sdk
from sentry_sdk.integrations.aws_lambda import AwsLambdaIntegration # Example for Lambda

SENTRY_DSN = os.getenv("SENTRY_DSN")
SENTRY_ENVIRONMENT = os.getenv("SENTRY_ENVIRONMENT", "development")
SENTRY_RELEASE = os.getenv("SENTRY_RELEASE", "unknown")
SENTRY_TRACES_SAMPLE_RATE = float(os.getenv("SENTRY_TRACES_SAMPLE_RATE", "0.0")) # Default to 0.0 in prod

if SENTRY_DSN:
    sentry_sdk.init(
        dsn=SENTRY_DSN,
        environment=SENTRY_ENVIRONMENT,
        release=SENTRY_RELEASE,
        enable_tracing=True, # Always enable tracing, sampling controls overhead
        traces_sample_rate=SENTRY_TRACES_SAMPLE_RATE,
        # Add integrations as needed, e.g., for specific frameworks or platforms
        # integrations=[AwsLambdaIntegration()] if SENTRY_ENVIRONMENT == "aws-lambda" else [],
    )
```

✅ **GOOD: Application Bootstrap (JavaScript/TypeScript Example)**
```typescript
// src/index.ts or app.ts
import * as Sentry from "@sentry/node"; // or @sentry/browser, @sentry/react, etc.

const SENTRY_DSN = process.env.SENTRY_DSN;
const SENTRY_ENVIRONMENT = process.env.SENTRY_ENVIRONMENT || "development";
const SENTRY_RELEASE = process.env.SENTRY_RELEASE || "unknown";
const SENTRY_TRACES_SAMPLE_RATE = parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE || "0.0");

if (SENTRY_DSN) {
    Sentry.init({
        dsn: SENTRY_DSN,
        environment: SENTRY_ENVIRONMENT,
        release: SENTRY_RELEASE,
        integrations: [
            // Add framework-specific integrations here, e.g., new Sentry.Integrations.Http({ tracing: true })
            // new Sentry.Integrations.Express(),
        ],
        tracesSampleRate: SENTRY_TRACES_SAMPLE_RATE,
        enableTracing: true, // Redundant with tracesSampleRate > 0, but good for clarity
    });
}
```

### 1.2. Environment, Release, and User Context

Always set `environment` and `release` during initialization. Enrich events with user and other relevant context for faster debugging.

✅ **GOOD: Setting Context**
```python
import sentry_sdk

# ... Sentry init as above ...

def process_order(user_id: str, order_details: dict):
    with sentry_sdk.push_scope() as scope: # Use push_scope for temporary context
        scope.set_user({"id": user_id, "email": "[email protected]"})
        scope.set_tag("order_type", "premium")
        scope.set_context("order_details", order_details)
        try:
            # ... order processing logic ...
            raise ValueError("Failed to process payment")
        except Exception as e:
            sentry_sdk.capture_exception(e)
```

## 2. Common Patterns and Anti-patterns

### 2.1. Performance Tracing with OpenTelemetry

Leverage OpenTelemetry for distributed tracing. Sentry SDKs integrate seamlessly, allowing end-to-end visibility without rewriting existing instrumentation.

✅ **GOOD: OpenTelemetry Integration (Python Example)**
```python
import sentry_sdk
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from sentry_sdk.integrations.opentelemetry import SentrySpanProcessor

# Configure OpenTelemetry
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter())) # For local debugging
provider.add_span_processor(SentrySpanProcessor()) # Send spans to Sentry
trace.set_tracer_provider(provider)

# Initialize Sentry (ensure enable_tracing and traces_sample_rate are set)
sentry_sdk.init(
    dsn="YOUR_DSN",
    enable_tracing=True,
    traces_sample_rate=1.0, # Adjust for production
    # ... other config ...
)

# Use OpenTelemetry tracer
tracer = trace.get_tracer(__name__)

def my_traced_function():
    with tracer.start_as_current_span("my-custom-operation"):
        print("Executing traced operation...")
        # ... your code ...
```

### 2.2. Isolated Clients for Shared Environments (JavaScript/TypeScript)

**NEVER** use `Sentry.init()` in shared environments (e.g., browser extensions, VS Code extensions, third-party widgets). This pollutes global state and leads to data leakage. Create a dedicated client instance manually.

❌ **BAD: Global Init in Shared Environment**
```typescript
// browser_extension/background.ts
import * as Sentry from "@sentry/browser";

Sentry.init({ // ❌ DANGER: Do NOT use Sentry.init() in shared environments!
    dsn: "YOUR_DSN",
    // ...
});
```

✅ **GOOD: Manual Client Setup for Shared Environments**
```typescript
// browser_extension/background.ts
import {
    BrowserClient,
    defaultStackParser,
    getDefaultIntegrations,
    makeFetchTransport,
    Scope,
} from "@sentry/browser";

// Filter out integrations that rely on global state
const integrations = getDefaultIntegrations({}).filter(
    (defaultIntegration) =>
        !["BrowserApiErrors", "Breadcrumbs", "GlobalHandlers"].includes(defaultIntegration.name)
);

const client = new BrowserClient({
    dsn: "YOUR_DSN",
    transport: makeFetchTransport,
    stackParser: defaultStackParser,
    integrations: integrations,
    tracesSampleRate: 1.0, // Adjust for production
    enableTracing: true,
});

const scope = new Scope();
scope.setClient(client);
client.init(); // Initialize the client after setting it on the scope

// Manually capture exceptions using the client's scope
try {
    // Your extension code here
    throw new Error("Example error in extension");
} catch (error) {
    scope.captureException(error);
}
```

### 2.3. AWS Lambda Integration

For serverless functions, use the platform-specific integration.

✅ **GOOD: AWS Lambda (Python Example)**
```python
import os
import sentry_sdk
from sentry_sdk.integrations.aws_lambda import AwsLambdaIntegration

SENTRY_DSN = os.getenv("SENTRY_DSN")
SENTRY_TRACES_SAMPLE_RATE = float(os.getenv("SENTRY_TRACES_SAMPLE_RATE", "0.0"))

if SENTRY_DSN:
    sentry_sdk.init(
        dsn=SENTRY_DSN,
        integrations=[AwsLambdaIntegration()],
        traces_sample_rate=SENTRY_TRACES_SAMPLE_RATE,
        environment=os.getenv("SENTRY_ENVIRONMENT", "production"),
        release=os.getenv("SENTRY_RELEASE", "unknown"),
    )

def lambda_handler(event, context):
    # Your Lambda function logic
    print("Processing event...")
    raise ValueError("Something went wrong in Lambda!")
    return {"statusCode": 200, "body": "Success"}
```

## 3. Performance Considerations

### 3.1. Configure `traces_sample_rate` Judiciously

`traces_sample_rate` directly impacts performance overhead and Sentry quota usage.

*   **Development:** Set to `1.0` to capture all transactions for full visibility.
*   **Production:** Set to a lower value (e.g., `0.01` to `0.1`) to sample a representative subset of transactions. Adjust based on traffic volume and monitoring needs.

❌ **BAD: `traces_sample_rate=1.0` in Production**
```python
sentry_sdk.init(
    dsn="YOUR_PROD_DSN",
    traces_sample_rate=1.0, # ❌ This will send ALL traces, potentially incurring high costs and overhead.
    enable_tracing=True,
)
```

✅ **GOOD: Controlled Sampling in Production**
```python
sentry_sdk.init(
    dsn="YOUR_PROD_DSN",
    traces_sample_rate=0.05, # ✅ Sample 5% of transactions in production
    enable_tracing=True,
)
```

## 4. Common Pitfalls and Gotchas

### 4.1. Missing or Invalid DSN

Without a valid DSN, Sentry cannot send events. Always verify your DSN is correctly configured, ideally via environment variables.

❌ **BAD: Hardcoded or Missing DSN**
```python
sentry_sdk.init(
    dsn="", # ❌ No DSN means no events
    # ...
)
```

✅ **GOOD: DSN from Environment Variables**
```python
import os
sentry_sdk.init(
    dsn=os.getenv("SENTRY_DSN"), # ✅ Always load DSN from environment
    # ...
)
```

### 4.2. Unset `environment` and `release`

Events without `environment` or `release` are significantly harder to triage and correlate. Always set these values.

❌ **BAD: Omitting Environment/Release**
```python
sentry_sdk.init(
    dsn="YOUR_DSN",
    # No environment or release set ❌
)
```

✅ **GOOD: Explicit Environment/Release**
```python
sentry_sdk.init(
    dsn="YOUR_DSN",
    environment=os.getenv("SENTRY_ENVIRONMENT", "development"), # ✅
    release=os.getenv("SENTRY_RELEASE", "[email protected]"), # ✅
)
```

### 4.3. Ignoring Inbound Filters

If Sentry events aren't appearing, check your Sentry project's **Project Settings > Inbound Filters**. Ensure you haven't accidentally enabled filters that block events (e.g., "Filter out errors known to be caused by browser extensions" if you're in a shared environment).

## 5. Testing Approaches

### 5.1. Disabling Sentry in Test Environments

Prevent test noise and unnecessary Sentry events by disabling the SDK during automated tests.

✅ **GOOD: Conditional Sentry Initialization**
```python
import os
import sentry_sdk

# Only initialize Sentry if DSN is present AND not in a test environment
if os.getenv("SENTRY_DSN") and os.getenv("APP_ENV") != "test":
    sentry_sdk.init(
        dsn=os.getenv("SENTRY_DSN"),
        environment=os.getenv("SENTRY_ENVIRONMENT", "development"),
        release=os.getenv("SENTRY_RELEASE", "unknown"),
        traces_sample_rate=float(os.getenv("SENTRY_TRACES_SAMPLE_RATE", "0.0")),
        enable_tracing=True,
    )
```

### 5.2. Manual Error Capture

For specific, non-critical errors that you want to report without crashing the application, use `sentry_sdk.capture_message()` or `sentry_sdk.capture_exception()`.

✅ **GOOD: Manual Capture**
```python
import sentry_sdk

def process_data(data: list):
    if not data:
        sentry_sdk.capture_message("Received empty data for processing.", level="warning") # ✅ Report non-exception issues
        return False
    try:
        # ... process data ...
        raise ConnectionError("Database unreachable")
    except ConnectionError as e:
        sentry_sdk.capture_exception(e) # ✅ Explicitly capture exceptions
        return False
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Similar IDE rules

All IDE rules for DevOps and infrastructure →

From the same set69

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor