sentry-performance-tuning

0
0
Source

Optimize Sentry performance monitoring configuration. Use when tuning sample rates, reducing overhead, or improving performance data quality. Trigger with phrases like "sentry performance optimize", "tune sentry tracing", "sentry overhead", "improve sentry performance".

Install

mkdir -p .claude/skills/sentry-performance-tuning && curl -L -o skill.zip "https://mcp.directory/api/skills/download/8417" && unzip -o skill.zip -d .claude/skills/sentry-performance-tuning && rm skill.zip

Installs to .claude/skills/sentry-performance-tuning

About this skill

Sentry Performance Tuning

Overview

Optimize Sentry's performance monitoring pipeline to maximize signal quality while minimizing SDK overhead and event volume costs. Covers the v8 SDK API for @sentry/node, @sentry/browser, and sentry-sdk (Python), targeting sentry.io or self-hosted Sentry 24.1+.

Prerequisites

  • Sentry SDK v8+ installed (@sentry/node >= 8.0.0 or sentry-sdk >= 2.0.0)
  • Sentry.init() called with a valid DSN before any application code runs
  • Performance monitoring enabled (tracesSampleRate > 0 or a tracesSampler function)
  • Access to the Sentry Performance dashboard to verify changes

Instructions

Step 1 — Replace Static tracesSampleRate with Dynamic tracesSampler

A flat tracesSampleRate: 0.1 samples all routes equally. The tracesSampler callback makes per-transaction decisions based on route, operation type, and upstream trace context.

import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  // tracesSampler replaces tracesSampleRate — do not set both
  tracesSampler: (samplingContext) => {
    const { name, attributes, parentSampled } = samplingContext;

    // Honor parent sampling for distributed trace consistency
    if (parentSampled !== undefined) return parentSampled ? 1.0 : 0;

    // Drop noise — health probes, static assets
    if (name?.match(/\/(health|ready|alive|ping|metrics)$/)) return 0;
    if (name?.match(/\.(js|css|png|jpg|svg|woff2?|ico)$/)) return 0;

    // Always sample business-critical paths
    if (name?.includes('/checkout') || name?.includes('/payment')) return 1.0;

    // Higher sampling for write operations (mutations are riskier)
    if (name?.startsWith('POST ') || name?.startsWith('PUT ')) return 0.25;

    // Moderate sampling for read APIs
    if (name?.startsWith('GET /api/')) return 0.1;

    // Low sampling for background work
    if (name?.startsWith('job:') || name?.startsWith('queue:')) return 0.05;

    // User-tier sampling (via custom attributes from middleware)
    if (attributes?.['user.plan'] === 'enterprise') return 0.5;

    return 0.05; // Default: 5%
  },
});

Step 2 — Configure Profiling with profilesSampleRate

The profilesSampleRate controls what fraction of traced transactions get profiled. Setting it to 1.0 with a 5% tracesSampler means 5% of traffic is profiled.

import { nodeProfilingIntegration } from '@sentry/profiling-node';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  integrations: [nodeProfilingIntegration()],
  tracesSampler: (ctx) => { /* ... from Step 1 ... */ },

  // Effective rate = tracesSampler rate * profilesSampleRate
  profilesSampleRate: 1.0,

  // Alternative: Continuous profiling (v8.7.0+) — profiles the entire process
  // profileSessionSampleRate: 0.1,  // 10% of server instances
});

Tuning: Start at profilesSampleRate: 0.1 in production. Profiling adds ~3-5% CPU overhead per profiled transaction. Continuous profiling (profileSessionSampleRate) has lower per-transaction cost but runs on sampled instances continuously.

Step 3 — Fix Transaction Naming (Prevent Cardinality Explosion)

Names with dynamic IDs (/api/users/12345) create thousands of unique entries, degrading dashboard performance and inflating quota. Route templates go in the name, dynamic values go in attributes.

// BAD — creates thousands of unique transaction entries
// GET /api/users/12345, GET /api/users/67890, ...

// GOOD — Sentry auto-parameterizes Express/Koa/Fastify routes
// GET /api/users/:userId

// For custom spans, always parameterize:
Sentry.startSpan(
  {
    name: 'order.process',           // No dynamic IDs in name
    op: 'task',
    attributes: {
      'order.id': orderId,           // Filterable in Discover queries
      'order.total_cents': totalCents,
      'customer.tier': customerTier,
    },
  },
  async (span) => {
    const result = await processOrder(orderId);
    span.setAttribute('order.status', result.status);
    return result;
  }
);

Detect cardinality issues with a Discover query:

SELECT count(), transaction FROM transactions GROUP BY transaction ORDER BY count() DESC

Step 4 — Add Custom Measurements

Custom measurements appear in the Performance dashboard and can be charted, alerted on, and queried in Discover. Unit types: 'millisecond', 'byte', 'none' (count), 'percent'.

await Sentry.startSpan(
  { name: 'search.execute', op: 'function' },
  async (span) => {
    const start = performance.now();
    const results = await searchService.query(term);

    Sentry.setMeasurement('search.latency', performance.now() - start, 'millisecond');
    Sentry.setMeasurement('search.result_count', results.length, 'none');
    Sentry.setMeasurement('search.memory_delta',
      process.memoryUsage().heapUsed - memBefore, 'byte');

    span.setAttribute('search.cache_hit', results.fromCache);
    return results;
  }
);
MeasurementUnitUse case
cart.total_centsnoneRevenue correlation with latency
query.rows_scannednoneDatabase query efficiency
cache.hit_ratepercentCache performance per route
upload.file_sizebyteFile upload impact on response time

Step 5 — Reduce SDK Overhead

For high-throughput services (>1000 req/s), every integration and breadcrumb counts.

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  maxBreadcrumbs: 20,           // Default: 100. Each ~0.5-2KB.
  maxValueLength: 500,          // Truncate long string values
  maxAttachmentSize: 5_242_880, // 5MB (default: 20MB)

  // Remove noisy integrations
  integrations: (defaults) => defaults.filter(
    (i) => i.name !== 'Console'
  ),

  // Trim oversized stack traces
  beforeSend: (event) => {
    if (event.exception?.values) {
      for (const exc of event.exception.values) {
        if (exc.stacktrace?.frames && exc.stacktrace.frames.length > 30) {
          exc.stacktrace.frames = [
            ...exc.stacktrace.frames.slice(0, 10),
            ...exc.stacktrace.frames.slice(-20),
          ];
        }
      }
    }
    return event;
  },

  // Drop internal/noise spans
  beforeSendSpan: (span) => {
    if (span.description?.startsWith('internal.')) return null;
    return span;
  },
});

Browser SDK lazy loading (saves ~30KB gzipped from critical path):

async function initSentry() {
  const Sentry = await import('@sentry/browser');
  Sentry.init({
    dsn: process.env.SENTRY_DSN,
    integrations: [Sentry.browserTracingIntegration()],
    tracesSampleRate: 0.1,
  });
}
window.addEventListener('load', initSentry, { once: true });

Step 6 — Span Best Practices (Avoid Span Explosion)

Only wrap operations with measurable latency (>1ms). Never span synchronous lookups or individual loop iterations.

// BAD — sub-microsecond config read; span overhead exceeds operation cost
function getConfig(key: string) {
  return Sentry.startSpan({ name: 'config.get', op: 'function' }, () => config[key]);
}

// BAD — N spans per request from loop iterations
for (const item of items) {
  await Sentry.startSpan({ name: 'process.item', op: 'function' }, () => processItem(item));
}

// GOOD — span the batch, count in attributes
await Sentry.startSpan(
  { name: 'process.batch', op: 'function', attributes: { 'batch.size': items.length } },
  async () => Promise.all(items.map(processItem))
);

// GOOD — span external I/O with real latency
async function fetchUserProfile(userId: string) {
  return Sentry.startSpan(
    { name: 'user.fetch_profile', op: 'http.client', attributes: { 'user.id': userId } },
    async () => fetch(`${USER_SERVICE_URL}/users/${userId}`).then(r => r.json())
  );
}

Step 7 — Web Vitals Monitoring

The Browser SDK auto-captures Core Web Vitals. Filter span creation to avoid noise from third-party scripts.

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  integrations: [
    Sentry.browserTracingIntegration({
      shouldCreateSpanForRequest: (url) =>
        !url.includes('googleapis.com') && !url.includes('analytics'),
    }),
  ],
  tracesSampleRate: 0.1,
});
MetricGoodPoorMeasures
LCP< 2.5s> 4.0sVisual load completion
INP< 200ms> 500msInput responsiveness (replaced FID)
CLS< 0.1> 0.25Visual stability
TTFB< 800ms> 1800msServer response time

Alert thresholds: LCP p75 > 2.5s (5 min), INP p75 > 200ms (5 min), CLS p75 > 0.1 (15 min).

Step 8 — Dashboard Queries for Performance Trends

-- Slowest transactions (p95)
SELECT transaction, p95(transaction.duration), count()
FROM transactions WHERE transaction.duration:>1000
ORDER BY p95(transaction.duration) DESC

-- Regression detection (20%+ slower vs last week)
SELECT transaction, p75(transaction.duration),
       compare(p75(transaction.duration), -7d) as vs_last_week
FROM transactions GROUP BY transaction
HAVING compare(p75(transaction.duration), -7d) > 1.2

-- Span breakdown for a route
SELECT span.op, span.description, p75(span.duration), count()
FROM spans WHERE transaction:/api/checkout
ORDER BY p75(span.duration) DESC

Output

  • Dynamic sampling active — health checks at 0%, payments at 100%, defaults at 5%
  • Profiling enabled with profilesSampleRate or continuous profileSessionSampleRate
  • Transaction names parameterized — cardinality under 500 unique names
  • Custom measurements tracking business KPIs alongside latency
  • SDK overhead reduced — fewer breadcrumbs, filtered integrations, trimmed payloads
  • Web Vitals monitored with alerts at Google's recommended thresholds

Verify at Sentry Stats (Settings > Stats) — volume should drop while data quality improves.

Error Handling

SymptomRoot CauseFix
Performance tab emp

Content truncated.

svg-icon-generator

jeremylongshore

Svg Icon Generator - Auto-activating skill for Visual Content. Triggers on: svg icon generator, svg icon generator Part of the Visual Content skill category.

8227

d2-diagram-creator

jeremylongshore

D2 Diagram Creator - Auto-activating skill for Visual Content. Triggers on: d2 diagram creator, d2 diagram creator Part of the Visual Content skill category.

4926

automating-mobile-app-testing

jeremylongshore

This skill enables automated testing of mobile applications on iOS and Android platforms using frameworks like Appium, Detox, XCUITest, and Espresso. It generates end-to-end tests, sets up page object models, and handles platform-specific elements. Use this skill when the user requests mobile app testing, test automation for iOS or Android, or needs assistance with setting up device farms and simulators. The skill is triggered by terms like "mobile testing", "appium", "detox", "xcuitest", "espresso", "android test", "ios test".

14217

performing-penetration-testing

jeremylongshore

This skill enables automated penetration testing of web applications. It uses the penetration-tester plugin to identify vulnerabilities, including OWASP Top 10 threats, and suggests exploitation techniques. Use this skill when the user requests a "penetration test", "pentest", "vulnerability assessment", or asks to "exploit" a web application. It provides comprehensive reporting on identified security flaws.

4615

designing-database-schemas

jeremylongshore

Design and visualize efficient database schemas, normalize data, map relationships, and generate ERD diagrams and SQL statements.

11514

analyzing-logs

jeremylongshore

Analyze application logs to detect performance issues, identify error patterns, and improve stability by extracting key insights.

11410

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

1,1421,171

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

969933

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

683829

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

691549

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

797540

pdf-to-markdown

aliceisjustplaying

Convert entire PDF documents to clean, structured Markdown for full context loading. Use this skill when the user wants to extract ALL text from a PDF into context (not grep/search), when discussing or analyzing PDF content in full, when the user mentions "load the whole PDF", "bring the PDF into context", "read the entire PDF", or when partial extraction/grepping would miss important context. This is the preferred method for PDF text extraction over page-by-page or grep approaches.

697374

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.