Search code examples
phplaravellaravel-5sentry

How to add a new exception handler to Laravel without disable the default one?


I'm using Sentry to keep tracking of exceptions from a Laravel application.

Sentry's docs say I should use the following code in my application bootstrap to setup the client:

$app->configureMonologUsing(function($monolog) {
    $client = new Raven_Client('your dsn');
    $handler = new Monolog\Handler\RavenHandler($client);
    $handler->setFormatter(new Monolog\Formatter\LineFormatter("%message% %context% %extra%\n"));
    $monolog->pushHandler($handler);
});

And that works fine!

The side effect is that Laravel's default exception handler, which writes the exceptions to the file at /storage/logs/laravel.log, stopped to work after adding the new exception handler.

How can I keep both handlers?

UPDATE for Laravel 5.6+

Starting on Laravel 5.6 log stacks are available. It now allows devs to set up multiple log channels with ease. Refer to the docs for more info on that.


Solution

  • You can look at Illuminate\Foundation\Bootstrap\ConfigureLogging to see how Laravel sets up its native logging. Then in your own bootstrap, just push another handler that does the same:

    $app->configureMonologUsing(function($monolog) {
    
        // Keep your existing Sentry configuration
        $client = new Raven_Client('your dsn');
        $handler = new Monolog\Handler\RavenHandler($client);
        $handler->setFormatter(new Monolog\Formatter\LineFormatter("%message% %context% %extra%\n"));
        $monolog->pushHandler($handler);
    
        // Add another handler that writes to laravel.log
        $handler = new Monolog\Handler\StreamHandler(storage_path('logs/laravel.log'));
        $handler->setFormatter(new Monolog\Formatter\LineFormatter(null, null, true, true));
        $monolog->pushHandler($handler);
    
    });
    

    Edit:

    If you don't need to reproduce Laravel's behaviour exactly, you could use the default formatter for a one-liner addition instead:

    $monolog->pushHandler(new Monolog\Handler\StreamHandler(storage_path('logs/laravel.log')));
    

    This differs from the native Laravel implementation in that it'll use the default constructor arguments for LineFormatter rather than those we were setting explicitly before.

    A third option that reuses Laravel's logic for configuring Monolog would be the addition of this line instead:

    with(new Illuminate\Log\Writer($monolog))->useFiles(storage_path('logs/laravel.log'));