Send a Slack Notification When Laravel Jobs Fail in Laravel 6 using Queue Failing

October 03, 2019
Written by
Michael Okoko
Contributor
Opinions expressed by Twilio contributors are their own

Send a Slack Notification When Laravel Jobs Fail in Laravel 6 using Queue Failing.png

Laravel provides a queue interface to help you defer long-running tasks such as sending emails/SMS, file processing, etc. As much as you try to avoid it, your queue will fail sometimes and because these failures are ignored by default, you need a way to be notified. In this article, we will explore how to send a Slack notification each time a queue fails.

Pre-requisites

Before Laravel 5.8.x, the Slack notification channel was pre-packaged into the framework. If your Laravel version is < 5.8.0, feel free to skip the installation (although you should look into upgrading as Laravel is currently on version 6.0). From Laravel 5.8.x and above, the Slack notification channel is packaged separately from the framework so we have to import it via:

$ composer require laravel/slack-notification-channel

Next, update your .env file to include your Slack webhook URL. This URL will be used by the Laravel notification to send our message to the associated Slack channel.

SLACK_WEBHOOK_URL="https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Next, generate a new notification with:

$ php artisan make:notification QueueFailed

Open the newly created file located at APP-FOLDER/app/Notifications/QueueFailed.php and paste in the following:

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\SlackAttachment;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\Events\JobFailed;

class QueueFailed extends Notification
{
    use Queueable;

    /**
    * @var JobFailed
    */
   public $event;

   /**
    * Create a new notification instance.
    *
    * @param JobFailed $event
    */

    public function __construct(JobFailed $event)
    {
        $this->event = $event;
    }

    public function via($notifiable)
    {
        return ['slack'];
    }

    public function toSlack($notifiable)
    {
        return (new SlackMessage())
            ->to("#general")
            ->content("Job failed at ". config('app.name'))
            ->attachment(function(SlackAttachment $attachment) use ($notifiable) {
               $attachment->fields([
                   'Payload' => $this>event->job->getRawBody(),
                   'Exception' => $this>event->exception->getTraceAsString(),
                   'Job' => $this>event->job->resolveName()
               ]);
            });
    }

    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

Now that our notification and queues are set up, update the boot() method in our app/Providers/AppServiceProvider.php file to the one below:

 public function boot()
{
    $slackUrl = env('SLACK_WEBHOOK_URL');
    Queue::failing(function (JobFailed $event) use ($slackUrl) {
        Notification::route('slack', $slackUrl)->notify(new QueueFailed($event));
    });
}

The Queue::failing() condition is trigged whenever the handle() method of your Laravel Job fails. Failure could be the result of an exception being thrown, but regardless of the reason, this will be how we test the Slack notification.

That’s it! You should now get a notification in the #general channel of your Slack group each time a queue fails.

Testing

To test the Slack notification, simply run your job with a condition that would cause the job to fail.

If you’ve used the tutorial “Create a Database Queue to Send SMS in PHP with Laravel Queues and Twilio SMS”, setting the To field in the database to empty will cause the job to fail.

Conclusion

If you're planning to handle your failed queues separately, you might want to start from the official queue documentation.

In any case, feel free to reach out to me on Twitter @firechael if you have questions or suggestions.