diff --git a/skills/sentry-miniapp-sdk/SKILL.md b/skills/sentry-miniapp-sdk/SKILL.md new file mode 100644 index 0000000..5928aee --- /dev/null +++ b/skills/sentry-miniapp-sdk/SKILL.md @@ -0,0 +1,290 @@ +--- +name: sentry-miniapp-sdk +description: Full Sentry SDK setup for Mini Programs — error monitoring, tracing, offline cache, source maps. Supports WeChat, Alipay, ByteDance, Baidu, QQ, DingTalk, Kuaishou and cross-platform frameworks (Taro / uni-app). +license: Apache-2.0 +category: sdk-setup +disable-model-invocation: true +--- + +> [All Skills](../../SKILL_TREE.md) > Mini Programs + +# Sentry Mini Program SDK Setup + +Set up Sentry error monitoring, performance tracing, and offline caching in mini program projects using [`sentry-miniapp`](https://github.com/lizhiyao/sentry-miniapp) — a community SDK built on `@sentry/core` v10. + +## Invoke This Skill When + +- User mentions **mini program**, **miniapp**, **小程序**, **WeChat**, **Alipay**, **ByteDance**, **Taro**, **uni-app** alongside Sentry +- User wants to add error monitoring or performance tracking to a mini program +- User asks about Sentry support for WeChat/Alipay/ByteDance mini programs +- User imports or references `sentry-miniapp` in their project + +> **Note:** SDK versions and APIs reflect the current sentry-miniapp docs. Always verify against the [sentry-miniapp README](https://github.com/lizhiyao/sentry-miniapp) before implementing. + +--- + +## Phase 1: Detect + +Run these commands to understand the project: + +```bash +# Detect mini program platform +ls app.json project.config.json mini.project.json 2>/dev/null +cat app.json 2>/dev/null | head -20 + +# Detect framework (Taro / uni-app / native) +cat package.json 2>/dev/null | grep -E '"@tarojs/|"@dcloudio/uni-|"sentry-miniapp"' + +# Check for existing Sentry SDK +grep -r "sentry" package.json 2>/dev/null +grep -r "Sentry.init" app.js app.ts src/app.js src/app.ts 2>/dev/null + +# Detect entry point +ls app.js app.ts src/app.js src/app.ts 2>/dev/null + +# Detect package manager +ls yarn.lock pnpm-lock.yaml package-lock.json 2>/dev/null +``` + +**What to determine:** + +| Question | Impact | +|----------|--------| +| Which mini program platform? | Determines `platform` option and API differences | +| Native or cross-platform framework (Taro/uni-app)? | Determines init pattern and build config | +| Is `sentry-miniapp` already installed? | Skip install if present, check version | +| Where is the app entry point? | Determines where to place `Sentry.init()` | +| Is there a build tool config (webpack/vite)? | Needed for Source Map setup | + +### Platform Detection Guide + +| File Present | Platform | +|-------------|----------| +| `project.config.json` | WeChat (微信) | +| `mini.project.json` | Alipay (支付宝) | +| `project.tt.json` | ByteDance (字节跳动) | +| `project.swan.json` | Baidu (百度) | +| `project.qq.json` | QQ | +| `@tarojs/*` in package.json | Taro (cross-platform) | +| `@dcloudio/uni-*` in package.json | uni-app (cross-platform) | + +--- + +## Phase 2: Recommend + +Present this recommendation based on detection results: + +**Recommended (core coverage):** + +- ✅ **Error Monitoring** — always. Automatic capture of `onError`, `onUnhandledRejection`, `onPageNotFound`, `onMemoryWarning` +- ✅ **Performance Tracing** — always. Navigation timing, render performance, resource loading, custom spans + +**Recommended for production:** + +- ⚡ **Source Map Upload** — when deploying to production. Maps minified stack traces back to source code +- ⚡ **Offline Cache** — when users are on unreliable networks. Caches events locally, retries when connectivity returns + +**Optional:** + +- ⚡ **Distributed Tracing** — when mini program calls backend APIs. Injects `sentry-trace`/`baggage` headers to link frontend and backend spans +- ⚡ **User Feedback** — when you want to collect user-reported issues via `Sentry.captureFeedback()` + +| Feature | Recommend when... | +|---------|-------------------| +| Error Monitoring | **Always** — zero-config automatic exception capture | +| Performance Tracing | **Always** — automatic page/network/render performance | +| Source Map | **Production** — required to read minified stack traces | +| Offline Cache | **Weak networks** — mobile users, rural areas | +| Distributed Tracing | **API calls** — mini program talks to backend services | +| User Feedback | **User-facing** — collect bug reports from end users | + +--- + +## Phase 3: Guide + +### Step 1: Install + +```bash +# npm +npm install sentry-miniapp + +# yarn +yarn add sentry-miniapp +``` + +### Step 2: Initialize + +Create or modify the app entry point. `Sentry.init()` **must** be called **before** `App()`. + +#### Native Mini Program (app.js) + +```javascript +const Sentry = require('sentry-miniapp'); + +Sentry.init({ + dsn: 'https://@.ingest.sentry.io/', + release: 'my-miniapp@1.0.0', + environment: 'production', +}); + +App({ + // Your app config... + // No need to manually call Sentry in onError — SDK handles it automatically +}); +``` + +#### Taro (app.js or app.ts) + +```typescript +import * as Sentry from 'sentry-miniapp'; + +Sentry.init({ + dsn: 'https://@.ingest.sentry.io/', + release: 'my-miniapp@1.0.0', + environment: 'production', +}); + +// Taro App component follows... +``` + +#### uni-app (App.vue or main.js) + +```javascript +const Sentry = require('sentry-miniapp'); + +Sentry.init({ + dsn: 'https://@.ingest.sentry.io/', + release: 'my-miniapp@1.0.0', + environment: 'production', +}); +``` + +### Step 3: Configure Platform (if needed) + +The SDK auto-detects the platform at runtime. No explicit `platform` option is required in most cases. + +If you need to force a specific platform: + +```javascript +Sentry.init({ + dsn: '...', + platform: 'wechat', // 'wechat' | 'alipay' | 'bytedance' | 'qq' | 'baidu' | 'dingtalk' +}); +``` + +### Step 4: Add User Context + +```javascript +// After user login +Sentry.setUser({ + id: 'user-123', + username: 'zhang_san', +}); + +// Add custom tags +Sentry.setTag('page', 'payment'); +Sentry.setContext('order', { orderId: '2024001', amount: 99.9 }); +``` + +### For Each Agreed Feature + +Walk through features one at a time. Load the corresponding reference file: + +| Feature | Reference | Load when... | +|---------|-----------|-------------| +| Error Monitoring | `${SKILL_ROOT}/references/error-monitoring.md` | Always | +| Performance Tracing | `${SKILL_ROOT}/references/tracing.md` | User agreed to tracing | +| Offline Cache | `${SKILL_ROOT}/references/offline-cache.md` | User agreed to offline cache | +| Source Map | `${SKILL_ROOT}/references/sourcemap.md` | User agreed to source maps | + +--- + +## Configuration Reference + +### Key Init Options + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `dsn` | `string` | — | Sentry DSN (required) | +| `release` | `string` | — | Release version, must match source map upload | +| `environment` | `string` | — | Environment name (production, staging, etc.) | +| `sampleRate` | `number` | `1.0` | Error event sample rate (0.0–1.0) | +| `tracesSampleRate` | `number` | — | Trace sample rate (0.0–1.0) | +| `tracesSampler` | `function` | — | Dynamic sampling function (overrides tracesSampleRate) | +| `enableSourceMap` | `boolean` | `true` | Auto-normalize stack trace paths for source map resolution | +| `enableOfflineCache` | `boolean` | `true` | Cache events when offline, retry when back online | +| `offlineCacheLimit` | `number` | `30` | Max events to store in offline cache | +| `enableTracePropagation` | `boolean` | `true` | Inject sentry-trace/baggage headers in outgoing requests | +| `tracePropagationTargets` | `Array` | `[]` | URL patterns for trace header injection (empty = all) | +| `enableAutoSessionTracking` | `boolean` | `true` | Automatic session lifecycle management | +| `enableConsoleBreadcrumbs` | `boolean` | `false` | Capture console.log/warn/error as breadcrumbs | +| `beforeSend` | `function` | — | Event processor for filtering/modifying events | + +### Platform Compatibility + +| Feature | WeChat | Alipay | ByteDance | Baidu | QQ | DingTalk | Kuaishou | +|---------|--------|--------|-----------|-------|----|----------|----------| +| Error Capture | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Performance | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Offline Cache | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Distributed Tracing | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Session Tracking | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Source Map | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + +--- + +## Verification + +After setup, verify the integration: + +1. **Trigger a test error:** + +```javascript +// In any page +Sentry.captureException(new Error('Test error from mini program')); +``` + +2. **Check Sentry dashboard:** + - Go to your Sentry project → Issues + - You should see the test error with: + - Device info (brand, model, OS) + - Mini program context (platform, SDK version) + - Breadcrumbs (page navigation, network requests) + +3. **Verify automatic capture works:** + - Throw an unhandled error in a page — it should appear in Sentry without any manual `captureException` call + +--- + +## Phase 4: Cross-Link + +After mini program setup, check for companion services: + +```bash +# Check for backend services in the same workspace +ls -d ../*/package.json ../*/requirements.txt ../*/go.mod ../*/Gemfile 2>/dev/null +``` + +| Backend Detected | Suggest | +|-----------------|---------| +| Node.js (`package.json` with server framework) | `sentry-node-sdk` skill | +| Python (`requirements.txt`) | `sentry-python-sdk` skill | +| Go (`go.mod`) | `sentry-go-sdk` skill | +| Ruby (`Gemfile`) | `sentry-ruby-sdk` skill | +| Java (`pom.xml` / `build.gradle`) | Sentry Java SDK docs | + +> **Tip:** Enable distributed tracing on both mini program and backend to get end-to-end request traces across services. + +--- + +## Troubleshooting + +| Issue | Solution | +|-------|----------| +| Events not appearing in Sentry | Check DSN is correct; verify Sentry domain is in mini program's trusted domain list | +| `sampleRate` filtering all events | Ensure `sampleRate` is not set to `0`; default is `1.0` | +| Minified stack traces | Set up Source Map upload — see `${SKILL_ROOT}/references/sourcemap.md` | +| Duplicate error reports | Do NOT manually call `Sentry.captureException` in `onError` — SDK captures automatically | +| Events lost on weak networks | Enable offline cache: `enableOfflineCache: true` (default) | +| WeChat DevTools not triggering `onError` | Test on a real device; DevTools may not trigger all error handlers | +| Stack trace paths don't match source maps | Ensure `--url-prefix "app:///"` when uploading; SDK normalizes paths to `app:///` automatically | diff --git a/skills/sentry-miniapp-sdk/references/error-monitoring.md b/skills/sentry-miniapp-sdk/references/error-monitoring.md new file mode 100644 index 0000000..0601b61 --- /dev/null +++ b/skills/sentry-miniapp-sdk/references/error-monitoring.md @@ -0,0 +1,141 @@ +# Error Monitoring — Mini Program SDK + +Automatic and manual error capture for mini programs across all supported platforms. + +## What's Captured Automatically + +Once `Sentry.init()` is called, the SDK automatically captures: + +- **`onError`** — unhandled JavaScript exceptions +- **`onUnhandledRejection`** — unhandled Promise rejections +- **`onPageNotFound`** — navigation to non-existent pages +- **`onMemoryWarning`** — system memory pressure warnings + +No manual code is needed for these. The SDK hooks into the platform's global error handlers. + +> **Important:** Do NOT manually call `Sentry.captureException()` inside `App.onError()`. The SDK already captures these errors automatically. Doing so causes duplicate reports. + +## Manual Error Capture + +For errors caught in `try-catch` blocks or business logic errors: + +```javascript +// Capture a caught exception +try { + riskyOperation(); +} catch (error) { + Sentry.captureException(error); +} + +// Capture a message (informational) +Sentry.captureMessage('User completed payment', 'info'); + +// Capture with extra context +Sentry.captureException(error, { + tags: { action: 'payment' }, + extra: { orderId: '2024001' }, +}); +``` + +## Enriching Error Context + +### User Identity + +```javascript +Sentry.setUser({ + id: 'user-123', + username: 'zhang_san', + ip_address: '{{auto}}', +}); + +// Clear user on logout +Sentry.setUser(null); +``` + +### Tags and Context + +```javascript +// Tags (indexed, searchable in Sentry) +Sentry.setTag('page', 'payment'); +Sentry.setTag('feature', 'coupon'); + +// Context (structured data, not indexed) +Sentry.setContext('order', { + orderId: '2024001', + amount: 99.9, + items: 3, +}); +``` + +### Breadcrumbs + +The SDK automatically records breadcrumbs for: +- Page navigation (route changes) +- Network requests (wx.request, etc.) +- User interactions (tap, longpress) +- Console output (when `enableConsoleBreadcrumbs: true`) + +Add custom breadcrumbs for business events: + +```javascript +Sentry.addBreadcrumb({ + category: 'payment', + message: 'User initiated payment', + level: 'info', + data: { amount: 99.9, method: 'wechat_pay' }, +}); +``` + +## Event Filtering + +Use `beforeSend` to filter or modify events before they're sent: + +```javascript +Sentry.init({ + dsn: '...', + beforeSend(event) { + // Drop events containing sensitive data + if (event.message && event.message.includes('password')) { + return null; + } + + // Limit breadcrumbs to prevent oversized events + if (event.breadcrumbs && event.breadcrumbs.length > 20) { + event.breadcrumbs = event.breadcrumbs.slice(-20); + } + + return event; + }, +}); +``` + +## Dynamic Sampling + +Control which errors get reported based on context: + +```javascript +Sentry.init({ + dsn: '...', + tracesSampler: ({ name, inheritOrSampleWith }) => { + // 100% sampling for critical pages + if (name.includes('pages/pay')) return 1; + // Lower sampling for less critical pages + if (name.includes('pages/about')) return 0.1; + // Default + return inheritOrSampleWith(0.5); + }, +}); +``` + +## User Feedback + +Collect user-reported feedback using `captureFeedback`: + +```javascript +Sentry.captureFeedback({ + message: 'The payment button is not responding', + name: 'Zhang San', + email: 'zhangsan@example.com', + associatedEventId: lastEventId, // optional: link to a captured error +}); +``` diff --git a/skills/sentry-miniapp-sdk/references/offline-cache.md b/skills/sentry-miniapp-sdk/references/offline-cache.md new file mode 100644 index 0000000..e5ec280 --- /dev/null +++ b/skills/sentry-miniapp-sdk/references/offline-cache.md @@ -0,0 +1,71 @@ +# Offline Cache — Mini Program SDK + +Reliable event delivery for mini programs in weak network environments. + +## Overview + +Mini programs often run on mobile networks where connectivity is unreliable. The offline cache feature ensures error events are not lost when the network is unavailable: + +1. When a request to Sentry fails (network error, timeout), the event is saved to local storage +2. When the app is next launched or network connectivity returns, cached events are automatically retried +3. Events expire after a configurable time period to prevent stale data + +## Configuration + +```javascript +Sentry.init({ + dsn: '...', + enableOfflineCache: true, // default: true + offlineCacheLimit: 30, // max events to store (default: 30) + offlineCacheMaxAge: 86400000, // expiry in ms (default: 24 hours) +}); +``` + +### Options + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `enableOfflineCache` | `boolean` | `true` | Enable/disable offline caching | +| `offlineCacheLimit` | `number` | `30` | Maximum events stored locally | +| `offlineCacheMaxAge` | `number` | `86400000` | Cache expiry time in milliseconds (default 24h) | + +## How It Works + +``` +Event captured + ↓ +Attempt to send to Sentry + ↓ +┌─ Success → Event delivered ✓ +└─ Failure (network error) → Save to local storage + ↓ + Next app launch / network restored + ↓ + Retry sending cached events + ↓ + ┌─ Success → Remove from cache ✓ + └─ Still failing → Keep in cache (retry later) +``` + +### Smart Eviction + +When the cache reaches `offlineCacheLimit`: +1. Non-error events (messages, info) are evicted first +2. Then oldest error events are evicted +3. New events always get stored (oldest are dropped) + +## Best Practices + +- **Don't set `offlineCacheLimit` too high** — each event consumes local storage, which is limited on mini programs (typically 10MB) +- **Keep `offlineCacheMaxAge` reasonable** — 24 hours is usually sufficient; very old events lose diagnostic value +- **Monitor storage usage** — if your events are large (lots of breadcrumbs/context), consider lowering the limit +- **The feature is enabled by default** — you only need to configure it if you want to change limits or disable it + +## Disabling + +```javascript +Sentry.init({ + dsn: '...', + enableOfflineCache: false, +}); +``` diff --git a/skills/sentry-miniapp-sdk/references/sourcemap.md b/skills/sentry-miniapp-sdk/references/sourcemap.md new file mode 100644 index 0000000..0eda65b --- /dev/null +++ b/skills/sentry-miniapp-sdk/references/sourcemap.md @@ -0,0 +1,204 @@ +# Source Map — Mini Program SDK + +Map minified stack traces back to original source code in Sentry. + +## Why Source Maps Matter + +Mini program code is minified before deployment. Without source maps, error stack traces show compressed variable names and wrong line numbers, making debugging nearly impossible. + +## How It Works + +The SDK includes a `RewriteFrames` integration (enabled by default via `enableSourceMap: true`) that normalizes platform-specific virtual paths to a standard `app:///` prefix: + +``` +WeChat: appservice/pages/index.js → app:///pages/index.js +Alipay: https://appx/pages/index.js → app:///pages/index.js +ByteDance: tt://pages/index.js → app:///pages/index.js +Baidu: swan://pages/index.js → app:///pages/index.js +``` + +This means you only need to upload source maps with `--url-prefix "app:///"` regardless of platform. + +## Setup + +### Step 1: Install sentry-cli + +```bash +npm install @sentry/cli --save-dev +``` + +### Step 2: Configure Authentication + +**Option A: `.sentryclirc` file** (for local development) + +```ini +[auth] +token=your-auth-token + +[defaults] +org=your-org +project=your-project +``` + +> Add `.sentryclirc` to `.gitignore` to protect your token. + +**Option B: Environment variables** (for CI/CD) + +```bash +export SENTRY_AUTH_TOKEN=your-auth-token +export SENTRY_ORG=your-org +export SENTRY_PROJECT=your-project +``` + +### Step 3: Generate Source Maps + +#### Webpack (Taro) + +```javascript +// config/index.js +const config = { + mini: { + webpackChain(chain) { + chain.devtool('hidden-source-map'); + }, + }, +}; +``` + +#### Vite + +```javascript +// vite.config.js +export default defineConfig({ + build: { + sourcemap: 'hidden', + }, +}); +``` + +#### uni-app (Vue CLI) + +```javascript +// vue.config.js +module.exports = { + productionSourceMap: true, + configureWebpack: { + devtool: 'hidden-source-map', + }, +}; +``` + +> Use `hidden-source-map` / `sourcemap: 'hidden'` to generate `.map` files without adding `sourceMappingURL` comments to production code. + +### Step 4: Upload Source Maps + +```bash +VERSION="my-miniapp@1.0.0" + +sentry-cli releases new "$VERSION" +sentry-cli releases files "$VERSION" upload-sourcemaps ./dist \ + --url-prefix "app:///" \ + --ext js --ext map +sentry-cli releases finalize "$VERSION" +``` + +> The `release` value here **must exactly match** the `release` option in `Sentry.init()`. + +### Step 5: Clean Up + +Delete `.map` files from deployment artifacts — they contain source code: + +```bash +find ./dist -name "*.map" -delete +``` + +## CI/CD Example (GitHub Actions) + +```yaml +- name: Upload Source Maps + run: | + npx sentry-cli releases new "$SENTRY_RELEASE" + npx sentry-cli releases files "$SENTRY_RELEASE" upload-sourcemaps ./dist \ + --url-prefix "app:///" \ + --ext js --ext map + npx sentry-cli releases finalize "$SENTRY_RELEASE" + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: your-org + SENTRY_PROJECT: your-project + SENTRY_RELEASE: my-miniapp@${{ github.ref_name }} +``` + +## Build Tool Plugins (Alternative) + +Instead of manual sentry-cli commands, use build plugins: + +**Webpack (`@sentry/webpack-plugin`):** + +```javascript +const { sentryWebpackPlugin } = require('@sentry/webpack-plugin'); + +chain.plugin('sentry').use(sentryWebpackPlugin, [{ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: 'your-org', + project: 'your-project', + release: { name: process.env.SENTRY_RELEASE }, + urlPrefix: 'app:///', + sourcemaps: { filesToDeleteAfterUpload: ['**/*.map'] }, +}]); +``` + +**Vite (`@sentry/vite-plugin`):** + +```javascript +import { sentryVitePlugin } from '@sentry/vite-plugin'; + +export default defineConfig({ + build: { sourcemap: true }, + plugins: [ + sentryVitePlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: 'your-org', + project: 'your-project', + release: { name: process.env.SENTRY_RELEASE }, + urlPrefix: 'app:///', + sourcemaps: { filesToDeleteAfterUpload: ['**/*.map'] }, + }), + ], +}); +``` + +## Platform Notes + +### WeChat Mini Program + +**Must disable** WeChat DevTools built-in compilation: +- ES6 to ES5 → OFF +- Code Minification → OFF +- Style Auto-Complete → OFF + +Let your build tool (Webpack/Vite) handle these. DevTools' built-in transforms break source map line/column alignment. + +## Verification + +```bash +# List uploaded files +sentry-cli releases files "my-miniapp@1.0.0" list +``` + +Should show entries like: +``` +app:///pages/index.js 12.5 KB +app:///pages/index.js.map 45.2 KB +``` + +Then trigger a test error — Sentry should display the original source code in the stack trace. + +## Troubleshooting + +| Issue | Solution | +|-------|----------| +| Minified code still shown | Check `release` matches exactly between `Sentry.init()` and `sentry-cli` | +| File paths don't match | Verify `--url-prefix "app:///"` and `enableSourceMap: true` (default) | +| Upload timeout | Increase timeout in `.sentryclirc`: `[http]` → `timeout = 120` | +| WeChat DevTools line numbers off | Disable DevTools' ES6/minification features | diff --git a/skills/sentry-miniapp-sdk/references/tracing.md b/skills/sentry-miniapp-sdk/references/tracing.md new file mode 100644 index 0000000..c3b5633 --- /dev/null +++ b/skills/sentry-miniapp-sdk/references/tracing.md @@ -0,0 +1,131 @@ +# Performance Tracing — Mini Program SDK + +Performance monitoring and distributed tracing for mini programs. + +## Automatic Performance Monitoring + +The SDK includes a `PerformanceIntegration` that automatically collects: + +- **Navigation performance** — page load timing (FCP, LCP equivalents) +- **Render performance** — page show/hide timing +- **Resource loading** — asset loading times +- **User timing** — custom performance marks + +Enable with `tracesSampleRate`: + +```javascript +Sentry.init({ + dsn: '...', + tracesSampleRate: 1.0, // 100% of transactions +}); +``` + +### Custom Performance Integration Options + +```javascript +Sentry.init({ + dsn: '...', + tracesSampleRate: 1.0, + integrations: [ + ...Sentry.getDefaultIntegrations(), + Sentry.performanceIntegration({ + enableNavigation: true, + enableRender: true, + enableResource: true, + enableUserTiming: true, + sampleRate: 1.0, + reportInterval: 30000, // Report every 30 seconds + }), + ], +}); +``` + +## Custom Spans + +Track specific operations with manual spans: + +```javascript +// Track an API request +const span = Sentry.startInactiveSpan({ + name: 'fetchUserProfile', + op: 'http.client', +}); + +wx.request({ + url: 'https://api.example.com/user/profile', + success: (res) => { + span.setStatus('ok'); + }, + fail: (err) => { + span.setStatus('internal_error'); + }, + complete: () => { + span.end(); + }, +}); +``` + +### Custom Performance Marks + +```javascript +// Mark start of an operation +Sentry.addPerformanceMark('checkout-start'); + +// ... perform operation ... + +// Mark end +Sentry.addPerformanceMark('checkout-end'); + +// Measure the interval +Sentry.measurePerformance('checkout-flow', 'checkout-start', 'checkout-end'); +``` + +## Distributed Tracing + +Automatically inject `sentry-trace` and `baggage` headers into outgoing network requests to link frontend and backend spans: + +```javascript +Sentry.init({ + dsn: '...', + enableTracePropagation: true, // default: true + tracePropagationTargets: ['api.example.com', /^https:\/\/api\./], +}); +``` + +- When `tracePropagationTargets` is empty (default), headers are injected into all non-Sentry requests +- When specified, only matching URLs receive trace headers +- Backend must have Sentry SDK with tracing enabled to complete the trace + +## Dynamic Sampling + +Use `tracesSampler` for per-page or per-operation sampling: + +```javascript +Sentry.init({ + dsn: '...', + tracesSampler: ({ name, inheritOrSampleWith }) => { + if (name.includes('pages/pay')) return 1; // Payment: 100% + if (name.includes('pages/index')) return 0.5; // Home: 50% + return inheritOrSampleWith(0.1); // Others: 10% + }, +}); +``` + +> **Note:** `tracesSampler` takes priority over `tracesSampleRate`. When set, `tracesSampleRate` is ignored. + +## Session Tracking + +Automatic session lifecycle management for Sentry Release Health: + +```javascript +Sentry.init({ + dsn: '...', + enableAutoSessionTracking: true, // default: true +}); +``` + +This tracks: +- Session start (app launch / `onShow`) +- Session end (app hide / `onHide`) +- Crash detection (error during session) +- Data appears in Sentry → Releases → Health dashboard