Sentry Logging in Laravel

January 2018

Laravel 5.6 also introduced much better logging solutions called "channels". Take a look at the docs.

There are a few reasons why I just hooked Sentry into the Laravel logging on my current project:

  • It's hosted using Docker (highly available, multiple instances) and I need a central place to capture application logs
  • There are instances where I log messages that aren’t necessarily exceptions and want visibility
  • I’m already using Sentry for exception capturing

This was pretty easy to hook up. Let's dive in…

Setup

namespace App\Providers;

use Monolog\Handler\RavenHandler;
use Illuminate\Support\Facades\Log;
use Monolog\Formatter\LineFormatter;
use Illuminate\Support\ServiceProvider;

class LogServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if (app()->bound('sentry') && config('sentry.dsn') !== null) {
            $handler = new RavenHandler(app('sentry'));
            $handler->setFormatter(new LineFormatter("%message%\n"));
            $monolog = Log::getMonolog();
            $monolog->pushHandler($handler);
        }
    }
}

Note: You can add some additional fields to the LineFormatter. See the “Customization” section below.

Then you need to add the provider to your config/app.php file:

return [

    //...

    'providers' => [

      //...

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        App\Providers\LogServiceProvider::class,

      //...

];

Usage

Now anything that gets logged will be forwarded to Sentry. For example, you could use something like the following in your application to explicitly create a log entry.

logger()->error(
    'Unknown foo returned from the example service',
    [
        'foo' => 'bar',
        'user_id' => auth()->user()->getAuthIdentifier()
    ]
);

“Unknown foo returned from the example service” will become the title of the entry on the Sentry project and you can find the context that you passed toward the bottom of the UI.

LineFormatter("%message% %context% %extra%\n"))

Customization

The example in the Sentry docs passes the context and extras but I prefer to just send the message as this will become the title of the entry on Sentry.

sentry-context-screenshot

More on Monolog, the underlying log engine for Laravel, integration in the Sentry docs.

Beyond Sentry

You could also use this pattern for other log services too, for example, Graylog. It wouldn’t be hard to modify this setup to use Graylog instead.


Updates


After I published this article I got this response from the Founder/CEO of Sentry. Really excited to hear this!

we’re going to make this kind of use case even better this year — stay tuned! – David Cramer (@zeeg)