AgentSkillsCN

sentry-integration

在集成Sentry以实现错误追踪与性能监控时加载此模块。适用于在React/Next.js应用中实施源码映射、性能追踪、问题归类,或发布版本跟踪。

SKILL.md
--- frontmatter
name: sentry-integration
description: Load when integrating Sentry for error tracking and performance monitoring. Applies when implementing source maps, performance tracing, issue grouping, or release tracking in React/Next.js applications.

When This Rule Applies

Apply when implementing error tracking, performance monitoring, or release management with Sentry.


Source Maps Configuration

Next.js with withSentryConfig

javascript
// next.config.js
const { withSentryConfig } = require("@sentry/nextjs");

module.exports = withSentryConfig(
  { reactStrictMode: true },
  {
    org: process.env.SENTRY_ORG,
    project: process.env.SENTRY_PROJECT,
    authToken: process.env.SENTRY_AUTH_TOKEN,
    sourcemaps: {
      deleteSourcemapsAfterUpload: true, // CRITICAL: Security
    },
    tunnelRoute: "/sentry-tunnel", // Bypass ad blockers
  }
);

Vite/React

javascript
// vite.config.ts
import * as Sentry from '@sentry/vite-plugin';

export default defineConfig({
  build: { sourcemap: true },
  plugins: [
    react(),
    Sentry.sentryVitePlugin({
      org: process.env.SENTRY_ORG,
      project: process.env.SENTRY_PROJECT,
      authToken: process.env.SENTRY_AUTH_TOKEN,
    }),
  ],
});

Performance Monitoring

React Initialization with Tracing

javascript
import * as Sentry from "@sentry/react";

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  integrations: [new Sentry.BrowserTracing()],
  
  // Production: 10% sampling. Dev: 100%
  tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
  
  // Capture 100% of sessions with errors
  replaysOnErrorSampleRate: 1.0,
  replaysSessionSampleRate: 0.1,
  
  environment: process.env.NODE_ENV,
  release: process.env.NEXT_PUBLIC_RELEASE,
});

Dynamic Sampling (Capture More of What Matters)

javascript
Sentry.init({
  tracesSampler(context) {
    // Always inherit distributed tracing decisions
    if (context.parentSampled !== undefined) return context.parentSampled;
    
    // Sample database ops at 80%
    if (context.transactionContext.op === "db") return 0.8;
    
    // Sample background jobs less
    if (context.transactionContext.op === "queue") return 0.1;
    
    return 0.2; // Default
  },
});

Issue Grouping & Fingerprinting

Server-Side Fingerprint Rules

Configure in Sentry Dashboard → Project Settings → Issue Grouping:

code
# Group all database connection errors together
error.type:DatabaseConnectionError -> database-unavailable

# Group API errors by status + endpoint
error.type:ApiError error.value:"*status:4*" -> api-4xx, {{ tags.endpoint }}

# Group chunk loading errors by bundle version
error.type:ChunkLoadError -> chunk-load-error, {{ tags.bundle_version }}

SDK-Level Fingerprinting

javascript
Sentry.init({
  beforeSend(event) {
    // Custom grouping for API errors
    if (event.exception?.[0]?.type === "ApiError") {
      const status = event.exception[0].value?.match(/status:(\d+)/)?.[1];
      event.fingerprint = ["api-error", status || "unknown"];
    }
    return event;
  },
});

Release Tracking

GitHub Actions Integration

yaml
- name: Sentry Release
  uses: getsentry/action-release@v1
  env:
    SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
    SENTRY_ORG: your-org
    SENTRY_PROJECT: your-project
  with:
    environment: production
    version: ${{ github.sha }}
    sourcemaps: ./dist

Common Gotchas

Source Maps Not Working

  1. URL prefix mismatch: Ensure url_prefix matches deployed paths exactly
  2. Maps not uploaded: Check CI logs for upload confirmation
  3. Maps exposed publicly: Always set deleteSourcemapsAfterUpload: true

Ad Blockers Blocking Sentry

Use tunneling to route events through your server:

javascript
// In Sentry config
tunnelRoute: "/sentry-tunnel"
javascript
// API route (Next.js example)
export async function POST(req) {
  const envelope = await req.text();
  await fetch("https://sentry.io/api/envelope/", {
    method: "POST",
    body: envelope,
  });
  return new Response("OK");
}

Session Replay Quota

javascript
// Sample 10% of sessions, but 100% of error sessions
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,

React Error Boundaries

javascript
import * as Sentry from "@sentry/react";

root.render(
  <Sentry.ErrorBoundary fallback={<ErrorFallback />}>
    <App />
  </Sentry.ErrorBoundary>
);

Filtering Noise

javascript
Sentry.init({
  ignoreErrors: [
    /ResizeObserver loop/,
    /chrome-extension:/,
    /moz-extension:/,
  ],
  beforeSend(event) {
    // Filter third-party errors
    if (event.request?.url?.includes("/third-party")) return null;
    return event;
  },
});

Quick Reference

TaskPattern
Enable source mapssourcemap: true + upload plugin
Performance samplingtracesSampleRate: 0.1 (production)
Custom groupingevent.fingerprint = [...]
Release trackingGitHub Action + release in init
Bypass ad blockerstunnelRoute option
Reduce replay quotareplaysSessionSampleRate: 0.1

References