Fusicきばんブログ

Fusic基盤ユニットの非公式技術ブログ

CakePHP3でエラーを自由自在に処理するencount

基盤ユニットリーダーの櫻川です( @kozo )。

さて今回はまたCakePHPに戻って、自分が作成しているencount プラグインについて書かせてもらいます。

encountはこちらになります。 github.com

encount 何が出来るの?

PHPが出力する NoticeWarningException といったエラーに対して、簡単にフック処理するを作ることが出来るプラグインになります。
例えば、本番環境にリリースしたサービスにencountを入れておくと、Noticeが出たタイミングでメール通知を行うといったことが可能となります。

また、 Senderクラス というencount専用のクラスを実装することで、エラー時の処理を自由にカスタマイズすることが可能です。
例えば、「Slackに通知する」や「NoticeやWarningはメールに通知するけど、FatalはSlackに通知する」といったようなことも可能となります。

※ Railsだと、 exception_notification が近い分類になると思われます。

encountのインストール

お決まりのcomposer経由にインストールになります。

composer require fusic/encount

encountの設定

ErrorHandler をCakeデフォルトのものから、encountのものへ切り替えます。
config/bootstrap.php で設定されてます。

// config/bootstrap.php
<?php

// shell
use Encount\Console\EncountConsoleErrorHandler;
(new EncountConsoleErrorHandler(Configure::read('Error')))->register();

// web
use Encount\Error\EncountErrorHandler;
(new EncountErrorHandler(Configure::read('Error')))->register();

encountはデフォルトの状態だと、Notice等何らかしらのエラーが発生したタイミングでメールを送信します。
その為、メール送信用の設定をします。

// config/app.php
<?php

return [

    // Errorを修正
    'Error' => [
        'errorLevel' => E_ALL,
        // exceptionRendererを追加
        'exceptionRenderer' => 'Cake\Error\ExceptionRenderer',
        'skipLog' => [],
        'log' => true,
        'trace' => true,
        // encount用設定を追加
        'encount' => [
            'force' => false,
            'sender' => ['Encount.Mail'],
            'mail' => [
                'prefix' => '',
                'html' => true
            ]
        ],
    ],

    // Emailにerrorを追加する
    'Email' => [
        // encount用設定を追加
        'error' => [
            'transport' => 'default',
            'from' => 'from@example.com',
            'to' => 'to@example.com'
        ]
    ],

];

encountの確認

デフォルトの設定では、 開発時はエラーを通知しないようになってます。
ですので、 debug を0に設定して、 echo $a['test'] というような存在しないキーにアクセスしてNoticeを発生後、メールが送信されれば設定OKです。

※開発時でも通知を行いたい場合は、 app.phpに先ほど設定した、 Error.encount.forcetrue に設定してください。

Senderを使って拡張する

さて、デフォルトの設定ではなく、通知を自作したい場合は、 Senderクラス を作成することになります。
例としてエラー内容を Slackで通知するSender を作成します。

1.SenderClassを作成する

src/Sender/Slack.php

<?php
namespace App\Sender;

use Encount\Sender\SenderInterface;

class Slack implements SenderInterface
{
    public function send($config, $code, $errorType, $description, $file, $line, $context)
    {
        // エラーが発生した時の処理をここに書く
        $url = '{{Incoming WebHooks URLを記載する}}';
        $data = array(
            'text' => $description,
        );
        $options = array(
            'http' => array(
            'method' => 'POST',
            'header' => 'Content-Type: application/json',
            'content' => json_encode($data),
            )
        );
        file_get_contents($url, false, stream_context_create($options));
    }
}

2. SlackSenderを使うように設定する

config/app.php

<?php
    'Error' => [
        'errorLevel' => E_ALL,
        'exceptionRenderer' => 'Cake\Error\ExceptionRenderer',
        'skipLog' => [],
        'log' => true,
        'trace' => true,
        'encount' => [
            'force' => true,
            // 作成した SlackSender に切り替える
            'sender' => ['Slack'],
            // Mail + Slack両方送信する場合は、以下のように2個並べる
            // 'sender' => ['Encount.Mail', 'Slack'],
            'mail' => [
                'prefix' => '',
                'html' => true
            ]
        ],
    ],

3. 動作確認

先ほどと同じく、echo $a['test'] というような存在しないキーにアクセスしてNoticeを発生してSlackが送信されればOKです。

最後に

気になった方はぜひ!encount使ってみてください!
そして、encountへの プルリク、Issue、Watch、Starよろしくお願い致します。