Monitoring
Error Tracking
Capturing, reporting, and debugging frontend errors
Error Tracking
Error tracking helps identify, diagnose, and resolve issues affecting users in production.
Key Concepts
Error Types
| Type | Description | Example |
|---|---|---|
| JavaScript Errors | Runtime exceptions | TypeError, ReferenceError |
| Unhandled Promise Rejections | Async failures | Failed API calls |
| Network Errors | HTTP failures | 4xx, 5xx responses |
| Resource Errors | Failed asset loads | Missing images, scripts |
| Custom Errors | Application-specific | Validation failures |
Error Context
Essential context for debugging:
- Stack Trace: Call stack at time of error
- Breadcrumbs: User actions leading to error
- Environment: Browser, OS, device info
- User Info: Affected user (anonymized)
- Release Version: Deployed code version
Implementation
Basic Error Boundary (React)
class ErrorBoundary extends React.Component {
state = { hasError: false, error: null };
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// Send to error tracking service
errorTracker.captureException(error, {
extra: { componentStack: errorInfo.componentStack }
});
}
render() {
if (this.state.hasError) {
return <ErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}Global Error Handler
// Capture unhandled errors
window.onerror = (message, source, line, column, error) => {
errorTracker.captureException(error || new Error(message), {
extra: { source, line, column }
});
};
// Capture unhandled promise rejections
window.onunhandledrejection = (event) => {
errorTracker.captureException(event.reason, {
extra: { type: 'unhandledrejection' }
});
};Sentry Setup Example
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: 'https://xxx@sentry.io/xxx',
environment: process.env.NODE_ENV,
release: process.env.APP_VERSION,
// Sample rate for performance monitoring
tracesSampleRate: 0.1,
// Filter sensitive data
beforeSend(event) {
if (event.user) {
delete event.user.email;
}
return event;
},
// Ignore specific errors
ignoreErrors: [
'ResizeObserver loop limit exceeded',
'Network request failed',
],
});
// Add user context
Sentry.setUser({ id: userId });
// Add breadcrumbs
Sentry.addBreadcrumb({
category: 'ui.click',
message: 'User clicked checkout button',
level: 'info',
});
// Capture with extra context
Sentry.captureException(error, {
tags: { feature: 'checkout' },
extra: { orderId: '12345' },
});Best Practices
Source Maps
Upload source maps to error tracking service for readable stack traces:
# Sentry CLI example
sentry-cli releases files $VERSION upload-sourcemaps ./distError Grouping
Configure error grouping to reduce noise:
Sentry.init({
beforeSend(event, hint) {
const error = hint.originalException;
// Custom fingerprinting
if (error?.message?.includes('ChunkLoadError')) {
event.fingerprint = ['chunk-load-error'];
}
return event;
},
});Alerting Rules
| Condition | Action |
|---|---|
| New error type | Immediate notification |
| Error spike (>10x baseline) | Page on-call |
| Error rate >1% | Slack alert |
| Critical path error | SMS + call |
Metrics to Track
| Metric | Description | Target |
|---|---|---|
| Error Rate | Errors / total sessions | < 0.1% |
| Error Count | Total errors per period | Trending down |
| Unique Errors | Distinct error types | < 50 active |
| MTTR | Mean time to resolution | < 24 hours |
| Affected Users | Users experiencing errors | < 1% |