Skip to content

Sentry

Overview

Sentry is an error tracking and performance monitoring platform that helps developers identify, diagnose, and fix issues in production. It provides real-time error tracking, performance monitoring, and release health insights for Laravel applications.

Official Website: https://sentry.io


Why Sentry?

Sentry provides several benefits:

  • Real-time error tracking - Get notified instantly when errors occur
  • Stack traces - Full context with code snippets
  • Breadcrumbs - User actions leading to errors
  • Performance monitoring - Track slow queries and requests
  • Release tracking - Monitor health of deployments
  • User context - See which users are affected
  • Integration - Works with Laravel, Slack, Jira, and more

Installation

Install Sentry SDK

bash
# Install via Composer
composer require sentry/sentry-laravel

# Publish configuration
php artisan vendor:publish --provider="Sentry\Laravel\ServiceProvider"

# Generate DSN in Sentry dashboard, then:
php artisan sentry:test

Environment Configuration

Add to .env:

env
SENTRY_LARAVEL_DSN=https://examplePublicKey@o0.ingest.sentry.io/0
SENTRY_TRACES_SAMPLE_RATE=0.2
SENTRY_PROFILES_SAMPLE_RATE=0.2
SENTRY_ENVIRONMENT=production

Configuration

Basic Configuration

Edit config/sentry.php:

php
<?php

return [
    'dsn' => env('SENTRY_LARAVEL_DSN'),

    // Release tracking
    'release' => env('SENTRY_RELEASE'),

    // Environment
    'environment' => env('SENTRY_ENVIRONMENT', env('APP_ENV')),

    // Sample rate for error events (0.0 to 1.0)
    'sample_rate' => env('SENTRY_SAMPLE_RATE', 1.0),

    // Traces sample rate (0.0 to 1.0)
    'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE', 0.0),

    // Profiles sample rate (0.0 to 1.0)
    'profiles_sample_rate' => env('SENTRY_PROFILES_SAMPLE_RATE', 0.0),

    // Send default PII (personally identifiable information)
    'send_default_pii' => false,

    // Breadcrumbs
    'breadcrumbs' => [
        'logs' => true,
        'cache' => true,
        'livewire' => true,
        'sql_queries' => true,
        'sql_bindings' => true,
        'queue_info' => true,
        'command_info' => true,
    ],
];

Production Optimization

env
# Production settings
SENTRY_ENVIRONMENT=production
SENTRY_TRACES_SAMPLE_RATE=0.1  # 10% of transactions
SENTRY_PROFILES_SAMPLE_RATE=0.1
SENTRY_SAMPLE_RATE=1.0  # All errors
env
# Development settings
SENTRY_ENVIRONMENT=local
SENTRY_TRACES_SAMPLE_RATE=1.0  # All transactions
SENTRY_SAMPLE_RATE=1.0  # All errors

Error Tracking

Automatic Error Capture

Sentry automatically captures:

  • Exceptions
  • Fatal errors
  • Warnings (if configured)
  • Failed jobs
  • HTTP errors (4xx, 5xx)
php
<?php

// This will be automatically sent to Sentry
throw new \Exception('Something went wrong!');

Manual Error Capture

php
<?php

use Sentry\Laravel\Facade as Sentry;

try {
    // Some risky operation
    processPayment($order);
} catch (\Exception $e) {
    // Capture exception
    Sentry::captureException($e);

    // Or capture with context
    Sentry::withScope(function ($scope) use ($e, $order) {
        $scope->setContext('order', [
            'id' => $order->id,
            'amount' => $order->total,
        ]);
        Sentry::captureException($e);
    });
}

Capture Messages

php
<?php

use Sentry\Laravel\Facade as Sentry;

// Info message
Sentry::captureMessage('Payment processing started', 'info');

// Warning
Sentry::captureMessage('API rate limit approaching', 'warning');

// Error
Sentry::captureMessage('Critical system failure', 'error');

Context and User Tracking

Set User Context

php
<?php

use Sentry\Laravel\Facade as Sentry;

// In middleware or controller
Sentry::configureScope(function ($scope) {
    $user = auth()->user();

    $scope->setUser([
        'id' => $user->id,
        'email' => $user->email,
        'username' => $user->name,
        'ip_address' => request()->ip(),
    ]);
});

Add Tags

php
<?php

use Sentry\Laravel\Facade as Sentry;

Sentry::configureScope(function ($scope) {
    $scope->setTag('payment_method', 'stripe');
    $scope->setTag('subscription_tier', 'premium');
    $scope->setTag('feature_flag', 'new_checkout_enabled');
});

Add Context

php
<?php

use Sentry\Laravel\Facade as Sentry;

Sentry::configureScope(function ($scope) {
    $scope->setContext('order', [
        'id' => $order->id,
        'total' => $order->total,
        'items_count' => $order->items->count(),
    ]);

    $scope->setContext('cart', [
        'total_items' => $cart->count(),
        'total_value' => $cart->total(),
    ]);
});
php
<?php

use Sentry\Laravel\Facade as Sentry;

// Add custom breadcrumb
Sentry::addBreadcrumb([
    'category' => 'payment',
    'message' => 'Payment gateway contacted',
    'level' => 'info',
    'data' => [
        'gateway' => 'stripe',
        'amount' => 99.99,
    ],
]);

// Automatically captured breadcrumbs include:
// - HTTP requests
// - Database queries
// - Cache operations
// - Queue jobs
// - Artisan commands

Performance Monitoring

Transaction Tracking

php
<?php

use Sentry\Laravel\Facade as Sentry;
use function Sentry\startTransaction;

// Start a transaction
$transaction = startTransaction([
    'op' => 'task',
    'name' => 'Process Order',
]);

// Set transaction on scope
Sentry::getCurrentHub()->setSpan($transaction);

try {
    // Your code here
    processOrder($order);

    // Mark as success
    $transaction->setStatus(\Sentry\SpanStatus::ok());
} catch (\Exception $e) {
    // Mark as failed
    $transaction->setStatus(\Sentry\SpanStatus::internalError());
    throw $e;
} finally {
    // Finish transaction
    $transaction->finish();
}

Spans (Sub-operations)

php
<?php

use function Sentry\trace;

trace(function () {
    // This operation will be traced
    $user = User::find(1);

    trace(function () use ($user) {
        // Nested span
        $posts = $user->posts;
    }, 'fetch.user.posts');

    return $user;
}, 'fetch.user');

Database Query Performance

Automatically tracked when enabled in config:

php
'breadcrumbs' => [
    'sql_queries' => true,
    'sql_bindings' => true,
],

Filtering and Ignoring

Ignore Exceptions

php
// config/sentry.php
'ignore_exceptions' => [
    Illuminate\Auth\AuthenticationException::class,
    Illuminate\Validation\ValidationException::class,
    Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class,
],

Ignore by Type

php
// config/sentry.php
'ignore_exceptions' => [
    // Ignore all 404 errors
    Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class,

    // Ignore validation errors
    Illuminate\Validation\ValidationException::class,
],

Before Send Hook

php
// config/sentry.php
'before_send' => function (\Sentry\Event $event): ?\Sentry\Event {
    // Don't send events in local environment
    if (app()->environment('local')) {
        return null;
    }

    // Filter out sensitive data
    if ($event->getRequest()) {
        $request = $event->getRequest();
        if (isset($request['data']['password'])) {
            unset($request['data']['password']);
        }
        $event->setRequest($request);
    }

    return $event;
},

Before Breadcrumb Hook

php
// config/sentry.php
'before_breadcrumb' => function (\Sentry\Breadcrumb $breadcrumb): ?\Sentry\Breadcrumb {
    // Ignore cache breadcrumbs
    if ($breadcrumb->getCategory() === 'cache') {
        return null;
    }

    return $breadcrumb;
},

Release Tracking

Set Release Version

env
# .env
SENTRY_RELEASE=my-app@1.0.0

Or dynamically:

php
// config/sentry.php
'release' => trim(exec('git log --pretty="%h" -n1 HEAD')),

Deploy Notifications

bash
# Install Sentry CLI
curl -sL https://sentry.io/get-cli/ | bash

# Create release
sentry-cli releases new my-app@1.0.0

# Associate commits
sentry-cli releases set-commits my-app@1.0.0 --auto

# Mark as deployed
sentry-cli releases deploys my-app@1.0.0 new -e production

In Deployment Script

bash
#!/bin/bash

# Get git commit hash
RELEASE=$(git rev-parse --short HEAD)

# Create Sentry release
sentry-cli releases new $RELEASE

# Upload source maps (if using frontend)
sentry-cli releases files $RELEASE upload-sourcemaps ./public/js

# Associate commits
sentry-cli releases set-commits $RELEASE --auto

# Deploy
php artisan migrate --force
php artisan config:cache

# Mark deployment
sentry-cli releases deploys $RELEASE new -e production

# Finalize release
sentry-cli releases finalize $RELEASE

Queue Integration

Automatic Job Tracking

Failed jobs are automatically sent to Sentry:

php
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class ProcessOrder implements ShouldQueue
{
    use InteractsWithQueue, Queueable;

    public function handle()
    {
        // Any exception here will be sent to Sentry
        throw new \Exception('Job failed!');
    }
}

Manual Context in Jobs

php
<?php

use Sentry\Laravel\Facade as Sentry;

class ProcessOrder implements ShouldQueue
{
    public function handle()
    {
        Sentry::configureScope(function ($scope) {
            $scope->setTag('job', 'process_order');
            $scope->setContext('order', [
                'id' => $this->order->id,
            ]);
        });

        // Process order
    }
}

Alerts and Notifications

Slack Integration

  1. In Sentry dashboard: Settings → Integrations → Slack
  2. Install Slack integration
  3. Configure alert rules
  4. Set notification channels

Email Alerts

Configure in Sentry dashboard:

  • Settings → Alerts
  • Create new alert rule
  • Set conditions (e.g., error frequency)
  • Add email recipients

Custom Alert Rules

IF errors in project "my-app"
AND error.level equals "error"
AND event.tags.priority equals "high"
THEN send notification to #critical-alerts

Best Practices

1. Set Appropriate Sample Rates

env
# Production - sample to reduce costs
SENTRY_TRACES_SAMPLE_RATE=0.1  # 10% of requests
SENTRY_PROFILES_SAMPLE_RATE=0.1

# Development - capture everything
SENTRY_TRACES_SAMPLE_RATE=1.0

2. Add Meaningful Context

php
// ✅ Good - Helpful context
Sentry::configureScope(function ($scope) use ($user, $order) {
    $scope->setUser(['id' => $user->id, 'email' => $user->email]);
    $scope->setTag('order_status', $order->status);
    $scope->setContext('order', ['id' => $order->id, 'total' => $order->total]);
});

// ❌ Bad - No context
throw new \Exception('Order failed');

3. Filter Sensitive Data

php
'send_default_pii' => false,

'before_send' => function ($event) {
    // Remove sensitive fields
    return $event;
},

4. Use Tags for Filtering

php
Sentry::configureScope(function ($scope) {
    $scope->setTag('payment_gateway', 'stripe');
    $scope->setTag('user_tier', 'premium');
    $scope->setTag('feature', 'checkout_v2');
});

5. Monitor Performance

php
// Track slow operations
$threshold = 2; // seconds
$start = microtime(true);

processOrder($order);

$duration = microtime(true) - $start;
if ($duration > $threshold) {
    Sentry::captureMessage("Slow order processing: {$duration}s", 'warning');
}

Troubleshooting

Events Not Appearing

bash
# Test Sentry connection
php artisan sentry:test

# Check logs
tail -f storage/logs/laravel.log

# Verify DSN
echo $SENTRY_LARAVEL_DSN

Too Many Events

php
// Increase sample rate threshold
'sample_rate' => 0.5, // 50% of errors

// Add filters
'ignore_exceptions' => [
    // Add exceptions to ignore
],

Missing Stack Traces

php
// Ensure debug mode in development
APP_DEBUG=true

// Check if source maps are uploaded (for JS)
sentry-cli releases files $RELEASE list

Monitoring Dashboard

Key Metrics

  • Error Rate - Errors per time period
  • Crash-Free Rate - % of sessions without crashes
  • Affected Users - Number of unique users impacted
  • Performance - Average transaction duration

Custom Dashboards

Create custom dashboards in Sentry:

  1. Navigate to Dashboards
  2. Click "Create Dashboard"
  3. Add widgets for metrics
  4. Share with team


Quick Reference

Installation

bash
composer require sentry/sentry-laravel
php artisan vendor:publish --provider="Sentry\Laravel\ServiceProvider"

Configuration

env
SENTRY_LARAVEL_DSN=https://key@sentry.io/project
SENTRY_TRACES_SAMPLE_RATE=0.2
SENTRY_ENVIRONMENT=production

Capture Exception

php
use Sentry\Laravel\Facade as Sentry;

Sentry::captureException($exception);

Set User Context

php
Sentry::configureScope(function ($scope) {
    $scope->setUser([
        'id' => $user->id,
        'email' => $user->email,
    ]);
});

Add Tags

php
Sentry::configureScope(function ($scope) {
    $scope->setTag('key', 'value');
});

Test Connection

bash
php artisan sentry:test

CPR - Clinical Patient Records