26 Nov 2014

Setup logs and monitoring for Laravel applications on Heroku

Categories: Laravel, Heroku, Papertrail, Bugsnag, NewRelic

Whether you are bringing a Laravel application into production or are in active development, it is always good to have logging services in place so you can see what's going on and where problems lie. Furthermore it is important that you are notified when things go sideways in production applications. That's why we need monitoring and alerting. We have experimented with Heroku in the past couple of weeks, so we have put together a small guide to setup these services on Heroku. I was amazed how easy it all was.

Heroku Logging for Laravel

Setting up basic logging is really easy, once you know how. Heroku picks up everything that is written to stdout and puts it in its logs, which you can access by running heroku logs. To make your Laravel app write all logs to stdout you need to modify app/start/global.php.

<?php
...
/*
|--------------------------------------------------------------------------
| Application Error Logger
|--------------------------------------------------------------------------
*/

Log::useFiles('php://stderr');
/* Log::useFiles(storage_path().'/logs/laravel.log'); // remove this line */
...

These lines enable Monolog which is already included in Laravel. You can remove the line that enables writing the log to logs/laravel.log.

Setting up Papertrail

If you want to do more with your logs you can forward them to a service like Papertrail. With Papertrail you can set alerts for when something bad happens. To set up Papertrail run: heroku addons:add papertrail. Yeah, that’s right, a single command. And since Laravel already logs to stdout these logs will now also appear in Papertrail. You can access Papertrail from the Heroku Dashboard.

Setting up Bugsnag

With Papertrail you can now search your raw logs but we also want to group errors, see how many time a particular error occurred and view nice Laravel stacktraces. If you have used services like Crashlytics for crash log analysis on mobile apps you know how valuable this can be. Bugsnag is basically Crashlytics for the web. It gives you a nice overview of all unresolved internal server errors and uncaught exceptions. To setup Bugsnag you need to make small modifications to your Laravel application.

$ heroku addons:add bugsnag
$ composer require "bugsnag/bugsnag-laravel:1.*"
$ php artisan config:publish bugsnag/bugsnag-laravel
# afterwards commit the changes and push them up to heroku

Modify app/config/app.php and add the special Bugsnag service provider and facade. If you take a look at the code of BugsnagLaravelServiceProvider you will see that it will make sure it handles all the exceptions correctly and sends them to Bugsnag.

<?php
return array(
    ...
    'providers' => array(
        ...
        'Bugsnag\BugsnagLaravel\BugsnagLaravelServiceProvider',
    ),
    'aliases' => array(
        ...
        'Bugsnag' => 'Bugsnag\BugsnagLaravel\BugsnagFacade',
    )
);

Modify app/config/packages/bugsnag/bugsnag-laravel/config.php to set the API key. The heroku addons:add command automatically added the BUGSNAG_API_KEY environment variable.

<?php
return array(
  'api_key' => getenv('BUGSNAG_API_KEY'),
  ...
);

When you have several larger applications you could use Bugsnag’s default plan instead of the Heroku Addon, it looks like that is more affordable. When you switch you only need to change the value of the BUGSNAG_API_KEY environment variable.

Setting up NewRelic (with Nginx)

With NewRelic you can actively monitor your applications performance when it is in production. See which requests are slow and which request triggers the most database queries. In addition NewRelic is also a great tool for basic profiling when your application is in development. You should take a look at their transaction traces feature. NewRelic has even optimized their software for Laravel so we can view these transaction traces per route.

Setting up NewRelic is again as easy as executing a single command: heroku addons:add newrelic. You can also set up alerting with NewRelic from the Heroku Dashboard.

When we started using NewRelic we noticed that the transaction traces per route only worked if we used Nginx and PHP-FPM, it didn’t work with Apache. To use Nginx modify your Procfile.

web: vendor/bin/heroku-php-nginx -C ops/heroku/nginx.conf public

The -C argument points to the nginx.conf file we will create in a minute. The last argument points to the location Nginx should use as root of your application, in the case of a Laravel application this is the public folder.

Next, create a ops/heroku/nginx.conf file.

try_files $uri $uri/ @rewrite;

location @rewrite {
    rewrite ^/(.*)$ /index.php?_url=/$1;
}

The try_files line is the important line, it will first check if a static file exsists, if not it will pass the request to PHP.

Wrapup

If you use a central chat system like HipChat or Slack you can hookup Papertrail, Bugsnag and NewRelic to send alerts to your chatrooms. This is what we’ve done. It a great way to keep your e-mail inbox clean and keep all notifications for a specific project grouped.

All these services are free to use when you have a small application with small logs, so they are free to use in development. We have no large production applications running on Heroku yet, going by the pricing table the costs could go up quickly. With setup being this easy you should look at the information these services give you and how valuable you think this information is.

Author: Thijs Scheepers