Skip to main content الرئيسية المنشئون jeremylongshore tons-of-skills-marketplace sentry-performance-tuning
sentry-performance-tuning Optimize Sentry performance monitoring for lower overhead and higher signal.
Use when tuning tracesSampleRate vs tracesSampler, configuring continuous profiling,
fixing high-cardinality transaction names, adding custom span measurements,
reducing SDK overhead, or setting Web Vitals thresholds.
Trigger: "sentry performance optimize", "tune sentry sampling",
"reduce sentry overhead", "sentry web vitals", "sentry profiling setup".
الانتقال إلى التثبيت سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/jeremylongshore/tons-of-skills-marketplace --skill sentry-performance-tuningيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... المزيد من هذا المستودع langchain-deploy-integration Deploy a LangChain 1.0 / LangGraph 1.0 app to Cloud Run, Vercel, or LangServe correctly — with timeouts sized for chain length, cold-start mitigation, SSE anti-buffering headers, and Secret Manager over .env. Use when prepping a first production deploy, debugging a stream that hangs behind a proxy, or diagnosing p99 latency spikes. Trigger with "langchain deploy", "langchain cloud run", "langchain vercel python", "langchain langserve", or "langchain docker".
langchain-langgraph-agents Build a correct LangGraph 1.0 ReAct agent with create_react_agent — typed tools, error propagation, recursion caps, and stop conditions that actually stop. Use when writing a first tool-calling agent, migrating from AgentExecutor or initialize_agent, or diagnosing an agent that loops on vague prompts. Trigger with "langgraph agent", "create_react_agent", "langgraph tool calling", "AgentExecutor migration", or "agent loop cost".
langchain-langgraph-human-in-loop Build LangGraph 1.0 human-in-the-loop approval flows with interrupt_before /
interrupt_after and Command(resume=...) — JSON-serializable state, clean
resume semantics, and UI wiring for approval decisions. Use when adding an
approval gate before an expensive tool call, wiring a Slack/web UI for agent
approvals, or debugging a graph that crashes on interrupt.
Trigger with "langgraph human in loop", "langgraph interrupt_before",
"langgraph approval flow", "Command resume", "langgraph HITL".
name sentry-performance-tuning description Optimize Sentry performance monitoring for lower overhead and higher signal.
Use when tuning tracesSampleRate vs tracesSampler, configuring continuous profiling,
fixing high-cardinality transaction names, adding custom span measurements,
reducing SDK overhead, or setting Web Vitals thresholds.
Trigger: "sentry performance optimize", "tune sentry sampling",
"reduce sentry overhead", "sentry web vitals", "sentry profiling setup".
allowed-tools Read, Write, Edit, Grep, Glob, Bash(npm:*), Bash(npx:*), Bash(node:*), Bash(sentry-cli:*) version 1.51.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","sentry","monitoring","performance","optimization","profiling","web-vitals"] compatibility Designed for Claude Code
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 : (samplingContext ) => {
const { name, attributes, parentSampled } = samplingContext;
if (parentSampled !== undefined ) return parentSampled ? 1.0 : 0 ;
if (name?.match ( )) ;
(name?. ( )) ;
(name?. ( ) || name?. ( )) ;
(name?. ( ) || name?. ( )) ;
(name?. ( )) ;
(name?. ( ) || name?. ( )) ;
(attributes?.[ ] === ) ;
;
},
});
/\/(health|ready|alive|ping|metrics)$/
return
0
if
match
/\.(js|css|png|jpg|svg|woff2?|ico)$/
return
0
if
includes
'/checkout'
includes
'/payment'
return
1.0
if
startsWith
'POST '
startsWith
'PUT '
return
0.25
if
startsWith
'GET /api/'
return
0.1
if
startsWith
'job:'
startsWith
'queue:'
return
0.05
if
'user.plan'
'enterprise'
return
0.5
return
0.05
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 ) => { },
profilesSampleRate : 1.0 ,
});
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.
Sentry .startSpan (
{
name : 'order.process' ,
op : 'task' ,
attributes : {
'order.id' : orderId,
'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;
}
);
Measurement Unit Use 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 ,
maxValueLength : 500 ,
maxAttachmentSize : 5_242_880 ,
integrations : (defaults ) => defaults.filter (
(i ) => i.name !== 'Console'
),
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;
},
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.
function getConfig (key : string ) {
return Sentry .startSpan ({ name : 'config.get' , op : 'function' }, () => config[key]);
}
for (const item of items) {
await Sentry .startSpan ({ name : 'process.item' , op : 'function' }, () => processItem (item));
}
await Sentry .startSpan (
{ name : 'process.batch' , op : 'function' , attributes : { 'batch.size' : items.length } },
async () => Promise .all (items.map (processItem))
);
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 ,
});
Metric Good Poor Measures LCP < 2.5s > 4.0s Visual load completion INP < 200ms > 500ms Input responsiveness (replaced FID) CLS < 0.1 > 0.25 Visual stability TTFB < 800ms > 1800ms Server 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 Symptom Root Cause Fix Performance tab empty tracesSampler returns 0 for all routesLog sampler decisions; check default return "Too many unique transaction names" Dynamic IDs in names Parameterize names; IDs in attributes (Step 3) SDK adds >50ms latency Too many integrations/breadcrumbs Reduce maxBreadcrumbs to 20; disable Console Profiling tab empty Missing @sentry/profiling-node Install package; set profilesSampleRate: 1.0 Incomplete distributed traces Independent sampling decisions Check parentSampled first in sampler (Step 1) setMeasurement values missingCalled outside active span Call inside Sentry.startSpan() callback Web Vitals null Missing browserTracingIntegration Add integration; set tracesSampleRate > 0
Examples
TypeScript — Express Production Setup import * as Sentry from '@sentry/node' ;
import { nodeProfilingIntegration } from '@sentry/profiling-node' ;
import express from 'express' ;
Sentry .init ({
dsn : process.env .SENTRY_DSN ,
environment : process.env .NODE_ENV ,
release : process.env .SENTRY_RELEASE ,
integrations : [nodeProfilingIntegration ()],
tracesSampler : (ctx ) => {
const { name, parentSampled } = ctx;
if (parentSampled !== undefined ) return parentSampled ? 1.0 : 0 ;
if (name?.match (/\/(health|ready|ping)$/ )) return 0 ;
if (name?.includes ('/checkout' )) return 1.0 ;
if (name?.startsWith ('POST ' )) return 0.25 ;
if (name?.startsWith ('GET /api/' )) return 0.1 ;
return 0.05 ;
},
profilesSampleRate : 1.0 ,
maxBreadcrumbs : 20 ,
beforeSendSpan : (span ) =>
span.description ?.includes ('health' ) ? null : span,
});
const app = express ();
Sentry .setupExpressErrorHandler (app);
app.get ('/api/search' , async (req, res) => {
const results = await Sentry .startSpan (
{ name : 'search.execute' , op : 'function' },
async () => {
const data = await searchService.query (req.query .q as string );
Sentry .setMeasurement ('search.result_count' , data.length , 'none' );
return data;
}
);
res.json (results);
});
Python — FastAPI Production Setup import os, re, sentry_sdk
from fastapi import FastAPI
def traces_sampler (ctx: dict ) -> float :
tx = ctx.get("transaction_context" , {})
name = tx.get("name" , "" )
parent = ctx.get("parent_sampled" )
if parent is not None :
return 1.0 if parent else 0.0
if re.search(r"/(health|ready|ping)$" , name):
return 0.0
if "/checkout" in name or "/payment" in name:
return 1.0
if name.startswith(("POST " , "PUT " )):
return 0.25
if name.startswith("GET /api/" ):
return 0.1
if tx.get("op" ) == "task" :
return 0.05
return 0.05
sentry_sdk.init(
dsn=os.environ["SENTRY_DSN" ],
environment=os.environ.get("ENVIRONMENT" , "development" ),
release=os.environ.get("SENTRY_RELEASE" ),
traces_sampler=traces_sampler,
profiles_sample_rate=1.0 ,
max_breadcrumbs=20 ,
before_send_transaction=lambda event, hint: (
None if event.get("transaction" , "" ).endswith("/health" ) else event
),
)
app = FastAPI()
@app.get("/api/search" )
async def search (q: str ):
with sentry_sdk.start_span(op="function" , name="search.execute" ) as span:
results = await search_service.query(q)
sentry_sdk.set_measurement("search.result_count" , len (results), "none" )
span.set_data("search.query_length" , len (q))
return {"results" : results}
Resources
Next Steps
Validate sampling — Check Sentry Stats (Settings > Stats) to confirm volume dropped while critical route coverage is maintained
Set up alerts — Create metric alerts for LCP p75 > 2.5s and INP p75 > 200ms
Review flamegraphs — Navigate to a sampled transaction and examine the Profile tab for CPU hotspots
Audit cardinality — Run the Discover query from Step 3 to find remaining high-cardinality names
Add business measurements — Identify 3-5 KPIs (cart value, search latency) and add setMeasurement() calls
Server-side sampling — Use Sentry's Dynamic Sampling UI (Settings > Performance) for rules without code deploys