Setting Up Error Tracking (Sentry) for Your Web Application
Sentry is the de facto standard for error tracking in web applications. It captures exceptions with full stack traces, request context, environment variables, and breadcrumbs — the chain of events preceding an error. Unlike logs, Sentry groups identical errors, shows frequency and first occurrence, and can assign responsibility.
Usage Options
Sentry SaaS (sentry.io) — no infrastructure, free tier available (5000 errors/month). Self-hosted — Docker-based, requires ~4 GB RAM, suitable for teams with data requirements or large error volumes.
SDK Installation
PHP / Laravel:
composer require sentry/sentry-laravel
php artisan sentry:publish --dsn=https://[email protected]/project-id
config/sentry.php is created automatically. In .env:
SENTRY_LARAVEL_DSN=https://[email protected]/project-id
SENTRY_TRACES_SAMPLE_RATE=0.1
SENTRY_PROFILES_SAMPLE_RATE=0.1
In bootstrap/app.php (Laravel 11) or app/Exceptions/Handler.php (Laravel 9-10) — SDK registers automatically via service provider.
Manual submission with context:
use Sentry\State\Scope;
\Sentry\withScope(function (Scope $scope) use ($user, $order): void {
$scope->setUser(['id' => $user->id, 'email' => $user->email]);
$scope->setContext('order', [
'id' => $order->id,
'amount' => $order->total,
'status' => $order->status,
]);
$scope->setTag('payment_provider', 'stripe');
\Sentry\captureException(new \RuntimeException('Payment gateway timeout'));
});
JavaScript / React:
npm install @sentry/react
// src/main.tsx
import * as Sentry from '@sentry/react';
Sentry.init({
dsn: import.meta.env.VITE_SENTRY_DSN,
environment: import.meta.env.MODE,
release: import.meta.env.VITE_APP_VERSION,
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration({
maskAllText: false,
blockAllMedia: false,
}),
],
tracesSampleRate: 0.1,
replaysSessionSampleRate: 0.05,
replaysOnErrorSampleRate: 1.0, // 100% on error
});
Error Boundary for React:
import * as Sentry from '@sentry/react';
const App = () => (
<Sentry.ErrorBoundary
fallback={({ error, resetError }) => (
<div>
<p>Something went wrong</p>
<button onClick={resetError}>Try again</button>
</div>
)}
onError={(error, componentStack) => {
console.error('React error boundary caught:', error);
}}
>
<Router />
</Sentry.ErrorBoundary>
);
Source Maps for JavaScript
Without source maps, stack traces in Sentry show minified code. Configuration via Sentry Vite Plugin:
npm install @sentry/vite-plugin --save-dev
// vite.config.ts
import { sentryVitePlugin } from '@sentry/vite-plugin';
export default defineConfig({
build: { sourcemap: true },
plugins: [
react(),
sentryVitePlugin({
org: 'your-org',
project: 'your-project',
authToken: process.env.SENTRY_AUTH_TOKEN,
sourcemaps: {
assets: './dist/**',
ignore: ['node_modules'],
filesToDeleteAfterUpload: ['./dist/**/*.map'],
},
}),
],
});
Source maps are uploaded to Sentry during the build and removed from the public directory — they're not accessible in the user's browser.
Environment and Release Tracking Configuration
In CI/CD during deployment:
# Create release and attach commits
sentry-cli releases new "$VERSION"
sentry-cli releases set-commits "$VERSION" --auto
sentry-cli releases finalize "$VERSION"
sentry-cli releases deploys "$VERSION" new -e production
This allows seeing in Sentry: which commit first caused an error, which release introduced it, whether it existed in previous versions.
Filtering Noise
By default, Sentry captures everything — including expected 404s, bots, crashes from browser extensions. Filtering:
// config/sentry.php
'before_send' => function (\Sentry\Event $event, ?\Sentry\EventHint $hint): ?\Sentry\Event {
$exception = $hint?->exception;
// Ignore expected exceptions
if ($exception instanceof \Illuminate\Auth\AuthenticationException) {
return null;
}
if ($exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
return null;
}
// Ignore errors from bots
$userAgent = request()->header('User-Agent', '');
if (str_contains(strtolower($userAgent), 'bot')) {
return null;
}
return $event;
},
// JavaScript: ignore errors from browser extensions
Sentry.init({
denyUrls: [
/extensions\//i,
/^chrome:\/\//i,
/^chrome-extension:\/\//i,
],
ignoreErrors: [
'ResizeObserver loop limit exceeded',
'Non-Error promise rejection captured',
],
});
Alerts and Notifications
In Sentry: Settings → Alerts → Create Alert Rule:
- New issue — immediately on first occurrence of a new error type
- Error frequency — if error occurs > 100 times per hour
- Regression — error returned after being marked resolved
Integrations: Slack, Telegram (via webhook), PagerDuty, Jira (auto-create tasks).
Timeline
SDK installation and basic setup for backend + frontend, source map configuration, initial noise filtering, alert rules: 2-4 hours.







