Performance monitoring helps you track the speed and reliability of your application. Sentry captures performance data through transactions and spans, giving you insights into what’s slow and why.
Getting Started
Enable performance monitoring during SDK initialization:
import * as Sentry from '@sentry/browser' ;
Sentry . init ({
dsn: 'your-dsn' ,
// Performance Monitoring
tracesSampleRate: 1.0 , // Capture 100% of transactions for performance monitoring
// Session Replay
replaysSessionSampleRate: 0.1 , // Capture 10% of all sessions
replaysOnErrorSampleRate: 1.0 // Capture 100% of sessions with errors
});
In production, adjust tracesSampleRate to a lower value (e.g., 0.1 for 10%) to reduce data volume and costs.
Sampling
Set a fixed sample rate for all transactions:
Sentry . init ({
dsn: 'your-dsn' ,
tracesSampleRate: 0.2 // Sample 20% of transactions
});
Dynamic Sampling
Use a function to dynamically sample transactions:
Sentry . init ({
dsn: 'your-dsn' ,
tracesSampler : ( samplingContext ) => {
// Sample 100% of checkout transactions
if ( samplingContext . name ?. includes ( 'checkout' )) {
return 1.0 ;
}
// Sample 100% of transactions with errors
if ( samplingContext . parentSampled === true ) {
return 1.0 ;
}
// Sample 10% of everything else
return 0.1 ;
}
});
Use tracesSampler for fine-grained control over which transactions to sample based on their context.
Transactions
Transactions represent a single instance of a service being called. Use startSpan to create transactions:
import * as Sentry from '@sentry/browser' ;
const result = Sentry . startSpan (
{
name: 'process_order' ,
op: 'function'
},
( span ) => {
// Your code here
const order = processOrder ();
return order ;
}
);
Transaction Operations
Use standard operation names for consistency:
// HTTP requests
Sentry . startSpan ({ name: 'GET /api/users' , op: 'http.client' }, () => {
// ...
});
// Database queries
Sentry . startSpan ({ name: 'SELECT * FROM users' , op: 'db.query' }, () => {
// ...
});
// Functions
Sentry . startSpan ({ name: 'calculateTotal' , op: 'function' }, () => {
// ...
});
// UI rendering
Sentry . startSpan ({ name: 'render_component' , op: 'ui.react.render' }, () => {
// ...
});
Async Operations
Transactions work seamlessly with async code:
const userData = await Sentry . startSpan (
{ name: 'fetch_user_data' , op: 'http.client' },
async ( span ) => {
const response = await fetch ( '/api/user' );
const data = await response . json ();
// Add custom data to the span
span . setAttribute ( 'user.id' , data . id );
span . setAttribute ( 'http.status_code' , response . status );
return data ;
}
);
Measuring Operations
Basic Timing
Measure how long operations take:
Sentry . startSpan ({ name: 'process_payment' , op: 'payment' }, ( span ) => {
// Validate payment
validatePaymentInfo ();
// Charge card
const result = chargeCard ();
// Send receipt
sendReceipt ();
return result ;
});
Nested Operations
Create child spans for detailed timing:
Sentry . startSpan ({ name: 'checkout' , op: 'function' }, () => {
// Validate cart
Sentry . startSpan ({ name: 'validate_cart' , op: 'function' }, () => {
validateCart ();
});
// Calculate total
const total = Sentry . startSpan ({ name: 'calculate_total' , op: 'function' }, () => {
return calculateTotal ();
});
// Process payment
Sentry . startSpan ({ name: 'process_payment' , op: 'payment' }, () => {
processPayment ( total );
});
});
Span Attributes
Add custom data to spans:
Sentry . startSpan ({ name: 'fetch_products' , op: 'http.client' }, ( span ) => {
span . setAttribute ( 'category' , 'electronics' );
span . setAttribute ( 'limit' , 10 );
span . setAttribute ( 'user.premium' , true );
const products = fetchProducts ({ category: 'electronics' , limit: 10 });
span . setAttribute ( 'result.count' , products . length );
return products ;
});
Span attributes are searchable and can be used for filtering and grouping in the Sentry UI.
Span Status
Set the status of a span to indicate success or failure:
Sentry . startSpan ({ name: 'api_request' , op: 'http.client' }, ( span ) => {
try {
const response = fetch ( '/api/data' );
span . setStatus ({ code: 1 , message: 'ok' }); // OK
return response ;
} catch ( error ) {
span . setStatus ({ code: 2 , message: 'internal_error' }); // Error
throw error ;
}
});
Status Codes
0 - UNSET: Default status
1 - OK: Success
2 - ERROR: Error occurred
HTTP Status Codes
Automatically set span status from HTTP responses:
import { setHttpStatus } from '@sentry/browser' ;
Sentry . startSpan ({ name: 'GET /api/users' , op: 'http.client' }, async ( span ) => {
const response = await fetch ( '/api/users' );
// Set status based on HTTP status code
setHttpStatus ( span , response . status );
return response . json ();
});
Custom Measurements
Add custom measurements to spans:
import { setMeasurement } from '@sentry/browser' ;
Sentry . startSpan ({ name: 'render_page' , op: 'ui.render' }, ( span ) => {
const startMemory = performance . memory ?. usedJSHeapSize ;
renderPage ();
const endMemory = performance . memory ?. usedJSHeapSize ;
const memoryUsed = endMemory - startMemory ;
// Add custom measurement
setMeasurement ( 'memory_used' , memoryUsed , 'byte' );
});
Suppressing Tracing
Temporarily disable tracing for specific operations:
import { suppressTracing } from '@sentry/browser' ;
suppressTracing (() => {
// No spans will be created inside this callback
internalOperation ();
debugLogging ();
});
Use suppressTracing sparingly and only when you need to prevent instrumentation of internal operations that would create noise.
Getting Active Span
Access the currently active span:
import { getActiveSpan , spanToJSON } from '@sentry/browser' ;
Sentry . startSpan ({ name: 'parent_operation' }, () => {
const activeSpan = getActiveSpan ();
if ( activeSpan ) {
// Get span details
const spanData = spanToJSON ( activeSpan );
console . log ( 'Trace ID:' , spanData . trace_id );
console . log ( 'Span ID:' , spanData . span_id );
// Add attributes to active span
activeSpan . setAttribute ( 'custom' , 'value' );
}
// Child spans will be children of this span
Sentry . startSpan ({ name: 'child_operation' }, () => {
// ...
});
});
Integration Examples
React Component
import * as Sentry from '@sentry/react' ;
function UserProfile ({ userId }) {
const [ user , setUser ] = React . useState ( null );
React . useEffect (() => {
Sentry . startSpan (
{ name: 'UserProfile.load' , op: 'ui.react.component' },
async () => {
const userData = await Sentry . startSpan (
{ name: 'fetch_user' , op: 'http.client' },
() => fetch ( `/api/users/ ${ userId } ` ). then ( r => r . json ())
);
setUser ( userData );
}
);
}, [ userId ]);
if ( ! user ) return < div > Loading... </ div > ;
return < div > { user . name } </ div > ;
}
Express.js Route
import * as Sentry from '@sentry/node' ;
import express from 'express' ;
const app = express ();
app . get ( '/api/users/:id' , async ( req , res ) => {
await Sentry . startSpan (
{
name: 'GET /api/users/:id' ,
op: 'http.server' ,
attributes: {
'http.method' : 'GET' ,
'http.route' : '/api/users/:id' ,
'user.id' : req . params . id
}
},
async ( span ) => {
// Query database
const user = await Sentry . startSpan (
{ name: 'SELECT users' , op: 'db.query' },
() => db . users . findById ( req . params . id )
);
span . setAttribute ( 'user.found' , !! user );
res . json ( user );
}
);
});
Best Practices
Use descriptive names : Name transactions and spans clearly to understand what they measure
Set appropriate operations : Use standard operation names for consistency
Add relevant attributes : Include data that helps identify slow operations
Sample wisely : Balance data volume with coverage needs
Measure meaningful operations : Focus on user-facing and critical operations
Keep spans focused : Each span should represent a single logical operation
Sentry’s performance monitoring is designed to have minimal impact:
Lightweight instrumentation
Efficient sampling
Async processing
No blocking operations
Start with a higher sample rate in development and lower it in production based on your traffic and needs.
Next Steps
Tracing Learn about distributed tracing
Spans Deep dive into spans and instrumentation
Distributed Tracing Track requests across services
Session Replay Combine performance data with session replay