Skip to content
Justin Rhodes edited this page Jul 16, 2025 · 3 revisions

This documentation provides a guide for integrating Sentry.io into Bison for robust error tracking and performance monitoring. Sentry helps monitor and fix crashes in real-time, providing detailed information needed to prioritize, identify, reproduce, and fix issues.

Sentry.io Integration with Laravel

1. Prerequisites

Before you begin, ensure you have:

  • A Sentry.io account. If you don't have one, sign up at [sentry.io](https://sentry.io/).
  • A Sentry project created for your Laravel application. This will provide you with a Data Source Name (DSN).
  • A Laravel application (Laravel 11.x or newer is recommended).
  • Composer installed on your development environment.

2. Installation

Install the official Sentry Laravel SDK via Composer:

composer require sentry/sentry-laravel

3. Configuration

After installation, you need to configure Sentry with your DSN and other settings.

3.1. Publish the Configuration File

Publish the Sentry configuration file to your config directory:

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

This command will create a config/sentry.php file.

3.2. Set your DSN

The most crucial step is to set your Sentry DSN. You can find your DSN in your Sentry project settings under "Client Keys".

Add your DSN to your .env file:

SENTRY_LARAVEL_DSN="YOUR_SENTRY_DSN_HERE"

Replace "YOUR_SENTRY_DSN_HERE" with your actual DSN.

Note: For local development and testing, you might want to disable Sentry or use a different DSN to avoid sending test errors to your production Sentry project.

3.3. Registering the Exception Handler (Laravel 10+)

For Laravel versions 10 and above, you should enable capturing unhandled exceptions by making the following change in bootstrap/app.php:

// bootstrap/app.php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Sentry\Laravel\Integration; // Add this line

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        Integration::handles($exceptions); // Add this line
    })->create();

3.4. Registering the Exception Handler (Older Laravel Versions)

For older Laravel versions (prior to Laravel 10), you will need to modify your app/Exceptions/Handler.php file to report exceptions to Sentry.

// app/Exceptions/Handler.php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Throwable  $exception
     * @return void
     *
     * @throws \Throwable
     */
    public function report(Throwable $exception)
    {
        if (app()->bound('sentry') && $this->shouldReport($exception)) {
            app('sentry')->captureException($exception);
        }

        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $exception
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $exception)
    {
        return parent::render($request, $exception);
    }
}

3.5. Using Sentry as a Log Channel (Recommended)

Instead of modifying the exception handler directly, a common and often more robust approach is to configure Sentry as a log channel in Laravel. This allows you to leverage Laravel's logging system and send various log levels to Sentry.

  1. Add a new Sentry log channel in config/logging.php:

    // config/logging.php
    
    'channels' => [
        // ... existing channels ...
    
        'sentry' => [
            'driver' => 'sentry',
            'level' => env('SENTRY_LOG_LEVEL', 'error'), // Only send errors and above to Sentry by default
            'bubble' => true, // Allow errors to be reported to other channels after Sentry handles them
        ],
    ],
  2. Configure your default log channel to use the sentry channel, or combine it with other channels using a stack:

    Option A: Dedicated Sentry Channel

    Change the LOG_CHANNEL in your .env file:

    LOG_CHANNEL=sentry
    

    Option B: Stack with Sentry and other channels (Recommended)

    If you want to continue logging to files (e.g., daily logs) in addition to Sentry, create a stack channel in config/logging.php:

    // config/logging.php
    
    'channels' => [
        // ...
    
        'stack' => [
            'driver' => 'stack',
            'channels' => ['daily', 'sentry'], // Log to daily files and Sentry
            'ignore_exceptions' => false,
        ],
    
        // ... sentry channel from above ...
    ],

    And then set your LOG_CHANNEL in .env:

    LOG_CHANNEL=stack
    

4. Verification

To ensure Sentry is correctly integrated and capturing errors, you can run a test command provided by the SDK:

php artisan sentry:test

This command will simulate an error and send it to Sentry. You should see a success message in your terminal and the event should appear in your Sentry.io dashboard.

Alternatively, you can create a simple route to throw an exception:

// routes/web.php

use Illuminate\Support\Facades\Route;

Route::get('/debug-sentry', function () {
    throw new \Exception('My first Sentry error!');
});

Visiting /debug-sentry in your browser will trigger an exception that Sentry should capture.

5. Advanced Usage and Best Practices

5.1. Enriching Events (Context)

Sentry automatically captures a lot of useful information, but you can add more context to your errors for better debugging.

User Context: To associate errors with the authenticated user, set SENTRY_SEND_DEFAULT_PII=true in your .env file, or manually configure the scope:

// In a service provider (e.g., AppServiceProvider's boot method) or middleware
use Sentry\Laravel\Integration;
use Sentry\State\Scope;

Event::listen(function (\Illuminate\Auth\Events\Authenticated $event) {
    Integration::configureScope(static function (Scope $scope) use ($event): void {
        $user = $event->user;
        $scope->setUser([
            'id' => $user->id,
            'email' => $user->email,
            'username' => $user->name,
            // ... any other user-related data you want to send
        ]);
    });
});

Tags: Tags are key-value pairs that allow you to filter and categorize events in Sentry.

use Sentry\SentrySdk;

// Add a global tag
SentrySdk::getCurrentHub()->configureScope(function (\Sentry\State\Scope $scope): void {
    $scope->setTag('server_name', gethostname());
});

// Add tags to a specific event
try {
    // some code that might fail
} catch (\Throwable $exception) {
    SentrySdk::getCurrentHub()->withScope(function (\Sentry\State\Scope $scope) use ($exception): void {
        $scope->setTags([
            'module' => 'user_management',
            'action' => 'create_user',
        ]);
        SentrySdk::getCurrentHub()->captureException($exception);
    });
}

Breadcrumbs: Breadcrumbs capture a trail of events that happened before an error, providing valuable context. Sentry's Laravel SDK automatically captures many common Laravel events as breadcrumbs (e.g., database queries, HTTP requests, log messages). You can also add custom breadcrumbs:

use Sentry\SentrySdk;

SentrySdk::getCurrentHub()->addBreadcrumb(
    new \Sentry\Breadcrumb(
        \Sentry\Breadcrumb::LEVEL_INFO,
        \Sentry\Breadcrumb::TYPE_DEFAULT,
        'user_action',
        'User attempted to access restricted page',
        ['user_id' => auth()->id(), 'path' => request()->path()]
    )
);

5.2. Capturing Messages

Beyond exceptions, you can also manually capture messages to Sentry:

use Sentry\SentrySdk;

SentrySdk::getCurrentHub()->captureMessage('This is a custom message from my application.');

5.3. Performance Monitoring (Tracing)

Sentry can also monitor the performance of your application by tracing requests.

  1. Enable Tracing: Set SENTRY_TRACES_SAMPLE_RATE in your .env file to a value greater than 0.0. A value of 1.0 means 100% of transactions will be sampled. Adjust this based on your needs and Sentry quota.

    SENTRY_TRACES_SAMPLE_RATE=1.0
    
  2. Tracing Configuration: The config/sentry.php file contains options to configure what aspects of your Laravel application are traced automatically (e.g., queue jobs, SQL queries, cache operations, Redis commands, views). Review these options and enable/disable as needed.

    // config/sentry.php
    'tracing' => [
        'queue_job_transactions' => env('SENTRY_TRACE_QUEUE_ENABLED', true),
        'sql_queries' => env('SENTRY_TRACE_SQL_QUERIES_ENABLED', true),
        'cache' => env('SENTRY_TRACE_CACHE_ENABLED', true),
        // ... more tracing options
    ],

5.4. Local Development and Testing

It's common to disable Sentry for local development to avoid polluting your Sentry project with local errors. You can do this by leaving the SENTRY_LARAVEL_DSN empty in your .env file for local environments:

SENTRY_LARAVEL_DSN=

Or by setting the environment option in config/sentry.php to only send events from specific environments:

// config/sentry.php
'environment' => env('APP_ENV'), // Automatically uses APP_ENV from .env

And in your local .env:

APP_ENV=local

6. Troubleshooting

  • "DSN not found" or "Cannot reach Sentry instance": Double-check your SENTRY_LARAVEL_DSN in your .env file for typos or missing characters. Ensure it's correctly loaded by Laravel's configuration. Run php artisan config:clear if you've recently changed your .env file and have config caching enabled.
  • Errors not appearing in Sentry:
    • Verify your DSN is correct.
    • Check your config/sentry.php settings, especially sample_rate and traces_sample_rate.
    • Ensure the report method in app/Exceptions/Handler.php (or bootstrap/app.php for Laravel 10+) is correctly calling app('sentry')->captureException($exception); or that your log channel is set up.
    • Check your server's outgoing network connections to sentry.io (or your self-hosted Sentry instance) to ensure there are no firewall issues preventing the SDK from sending events.
    • Enable Sentry's internal logger for more verbose debugging by adding the following to your config/sentry.php (temporarily):
      'logger' => new \Sentry\Logger\DebugFileLogger(storage_path('logs/sentry.log')),
      This will write Sentry's internal logs to storage/logs/sentry.log.
  • Duplicate errors in Sentry: If you're using Sentry as a log channel and also explicitly calling captureException in your Handler.php, you might send duplicate events. Choose one method (log channel is generally preferred). If using a log channel, remove the captureException call from your Handler.php's report method.

7. Further Reading