Laravel5: エラーのログレベルを変更してみた

[2015 Laravel Advent Calendar](http://www.adventar.org/calendars/817) 1日目！ Laravel大好きな @M_Ishikawa と申します。

今年のphpconのLTで「サンタクロースを支えるIT技術」についての話をさせていただき、その際にも触れましたが趣味ではもっぱらLaravelを使用しております。＼サンタクロースの活動を支えているLaravel／

今日は初日らしく軽〜い感じの内容で、日本語のTipsがWeb上に見当たらないから書いちゃえ！と思った、「エラーログレベルを操作する」という内容です。

※なお、Laravel5のコードで説明しています。

<br>

----

<br>

ずばり以下の通り。コードに説明入れちゃいます。

[app/Exceptions/Handler.php](https://github.com/laravel/laravel/blob/b0a22fc51161630c81f20e23a9269b82a369953e/app/Exceptions/Handler.php)

```php:app/Exceptions/Handler.php
class Handler extends ExceptionHandler
{
    /**
     * ロギングの必要のないExceptionを指定できます
     */
    protected $dontReport = [
        HttpException::class,
        ModelNotFoundException::class,
    ];

    /**
     * エラーをロギングするならここです。
     * 3rd partyのエラーロギングWebサービス(SentryやBugsnag等)を挟むならここ！
     * 親メソッドでは  $this->log->error($e); しています。
     */
    public function report(Exception $e)
    {
        return parent::report($e);
    }

    /**
     * エラーをhttpレスポンスとしてレンダリングするならここです。
     */
    public function render($request, Exception $e)
    {
        if ($e instanceof ModelNotFoundException) {
            $e = new NotFoundHttpException($e->getMessage(), $e);
        }
        return parent::render($request, $e);
    }
}
```
ex: [Sentry](https://getsentry.com/welcome/), [Bugsnag](https://bugsnag.com/)


以上、初期のHandlerクラスでは非常にシンプルに必要最低限の調整が可能です。
たとえば csrf対策でLaravel5から実装された TokenMismatchException のログが必要なければ

```php:app/Exceptions/Handler.php
    protected $dontReport = [
        HttpException::class,
        ModelNotFoundException::class,
        TokenMismatchException::class, // 追加
    ];
```

のように追加すればロギングされなくなります。

もしくはロギングはするけどエラーレベルを変更したいという場合は

```php:app/Exceptions/Handler.php
    public function report(Exception $e)
    {
        if ($e instanceof TokenMismatchException) {
            // csrf tokenチェックはerrorではなくnoticeで
            $this->log->notice($e);
            return;
        }
        return parent::report($e);
    }
```

とすればerrorからnoticeにレベル変更できます。

ちなみに親メソッドはどうなっているかというと、

[vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php](https://github.com/laravel/framework/blob/ca2d794d2800e53391c51d117a133f2c2e6dd146/src/Illuminate/Foundation/Exceptions/Handler.php#L47-L52)

```php:vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php
    public function report(Exception $e)
    {
        if ($this->shouldReport($e)) {
            $this->log->error($e);
        }
    }
```

ただのこれだけ。 [こちらの親クラスのコード](https://github.com/laravel/framework/blob/ca2d794d2800e53391c51d117a133f2c2e6dd146/src/Illuminate/Foundation/Exceptions/Handler.php) をたどるとわかりますが、 `$dontReport` に含まれていなければ `shouldReport() = true` となり `log->error()` が吐かれます。

このLaravelのエラーは

[src/Illuminate/Log/Writer.php](https://github.com/laravel/framework/blob/ea286e300a29a05e6586241653eed4b522b39959/src/Illuminate/Log/Writer.php#L41-L50)

```php:src/Illuminate/Log/Writer.php
    protected $levels = [
        'debug'     => MonologLogger::DEBUG,
        'info'      => MonologLogger::INFO,
        'notice'    => MonologLogger::NOTICE,
        'warning'   => MonologLogger::WARNING,
        'error'     => MonologLogger::ERROR,
        'critical'  => MonologLogger::CRITICAL,
        'alert'     => MonologLogger::ALERT,
        'emergency' => MonologLogger::EMERGENCY,
    ];
```
と8種類用意されていますので、お好みのものを利用できます。

<br>

----

<br>

いかがでしたでしょうか。
さらにいろいろカスタマイズしたい場合は、[親のHandlerクラス](https://github.com/laravel/framework/blob/ca2d794d2800e53391c51d117a133f2c2e6dd146/src/Illuminate/Foundation/Exceptions/Handler.php) に用意された変数やメソッド(publicとprotectedしか存在しない！)をオーバーライドすることで自由に実現できます。

さくっとやりたいときはズバリ必要最低限のものがイケてる感じで用意されていて、さらにカスタマイズしようと思った時も直感でスマートに実装できるLaravelまじ＋＋。
フレームワーク本体もとても分かり易く書かれているのでソースを追っかけるのが全然苦じゃないどころか、ワクワクしてきます。
ソースコードのコメントに [Sentry](https://getsentry.com/welcome/) や [Bugsnag](https://bugsnag.com/) といったイマドキのサービスを紹介しちゃうところもますます惚れてしまいます。

いじょーでした! 
enjoy! Laravel!!

<br>

<div><a href="http://twitter.com/M_Ishikawa"><img src="http://api.osae.me/retwipi/M_Ishikawa"> @M_Ishikawa</a></div>