6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

LaravelのExceptionをSlackで通知する

Last updated at Posted at 2020-05-18

概要

Laravelの通知と例外処理の勉強のために実装してみました。

Notificationに関する記事は数多くあり、公式ドキュメントでも解説されていますが、備忘録としてかんたんな流れを残しておきます。

環境

  • Laravel 6.0
  • PHP 7.2

事前準備

Guzzleとslack-notification-channelのインストール

$ composer install guzzlehttp/guzzle
$ composer install laravel/slack-notification-channel

SlackのWebhookURLを取得する

今回はenvの値をconfig経由で使用します。
webhookURL取得手順については割愛しますね...

config\slack.php
return [
    'name' => env('SLACK_NAME'),
    'channel' => env('SLACK_CHANNEL'),
    'webhook_url' => env('SLACK_WEBHOOK_URL'),
];

通知用クラスの作成

ひとまずslackにメッセージを送信できるように実装します。
初期状態ではメール送信がデフォルトになっているので、slack用に変更してあげます。

App\Notifications\Slack.php;
<?php

namespace App\Notifications;

use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;

class Slack extends Notification
{
    use Queueable;

    protected $name;
    protected $channnel;
    protected $content;
     

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($message)
    {
        $this->name = config(slack.name);
        $this->channel = config(slack.channnel);
        $this->content = $message;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['slack'];
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }

    /**
     * @param $notifiable
     * @return $this
     */
    public function toSlack($notifiable)
    {
        return (new SlackMessage)
            ->from($this->name)
            ->to($this->channel)
            ->content($this->content);
    }
}

コンストラクタでmessageを受け取り、toSlack()でそのまま送信するシンプルな処理です。
通知を配信するチャンネルをslackにするため、via()の中を'slack'に変更します。

Slack通知用のルートを作成する

App\Service\Slack\SlackNotifiable.php
<?php

namespace App\Service\Slack;

use Illuminate\Notifications\Notifiable;
use App\Notifications\SlackNotification;
use Exception;
use Illuminate\Notifications\RoutesNotifications;

class SlackNotifiable
{
  use Notifiable;

  protected function routeNotificationForSlack()
  {
    return config('slack.webhook_url');
  }
}

実際にSlack通知をルートするために、routeNotificationForSlack()を定義しWebhookURLを返しています。
Notifiableトレイトを読み込み、notify()で通知を送信できます。

これでSlackにメッセージを送信する準備はOKです!

例外処理に通知を組み込む

Laravelのエラーハンドリングは基本的にapp\Exceptions\Handler.phpが担っています。
ざっくりした流れとしては

  1. report()で例外をキャッチ
  2. 親クラスであるIlluminate\Foundation\Exceptions\Handler.phpでrenderレスポンスのために条件分岐
    ログインエラーなのか,バリデーションエラーなのか等々...
  3. render()でレスポンスを返す。

今回は、例外検知時に通知を送りたいので、report()を編集します。

App\ExceptionsHandler.php
public function report(Exception $exception)
    {
        $slackHook = new SlackNotifiable();
        $slackHook->notify(new Slack($exception));
        parent::report($exception);
    }

SlackNotifiableのインスタンスを作成し,notify()メソッドを実行することで通知を送っています。
引数にキャッチした例外$exceptionを渡しています。

Slack通知用クラスの修正

最後にApp\Notifications\Slack.phpで例外内容を通知するように修正します。

App\Notifications\Slack.php;
<?php

namespace App\Notifications;

use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;

class Slack extends Notification
{
    use Queueable;

    protected $name;
    protected $channnel;
    protected $exception;
     

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct(Exception $e)
    {
        $this->name = config(slack.name);
        $this->channel = config(slack.channnel);
        $this->exception = $e;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['slack'];
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
    /**
     * @param $notifiable
     * @return $this
     */
    public function toSlack($notifiable)
    {
        $exception = $this->exception;

        return (new SlackMessage)
            ->from($this->name)
            ->to($this->channel)
            ->error()
            ->content('エラーを検知しました')
            ->attachment(function ($attachment) use ($exception) {
                $attachment
                    ->title(get_class($exception))
                    ->content($exception->getMessage());
            });
    }
}

コンストラクタでExceptionを受け取るように修正しています。

これでエラー内容をSlackで確認することができるようになりました!
スクリーンショット 2020-05-19 2.04.51.png

おわりに

最後まで読んでくださってありがとうございました。
至らぬ点など有りましたら、コメントで指摘して頂けるとありがたいです...

Laravelの通知処理を理解するのに良い勉強になりました。
次はキューとか使った非同期処理もやってみたいなぁ。

参考記事

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?