1. M_Ishikawa

    Posted

    M_Ishikawa
Changes in title
+Laravel5: エラーのログレベルを変更してみた
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,131 @@
+2015 Laravel Advent Calendar 1日目! Laravel大好きな @M_Ishikawa と申します。
+
+今年のphpconのLTで「サンタクロースを支えるIT技術」についての話をさせていただき、その際にも触れましたが趣味ではもっぱらLaravelを使用しております。\サンタクロースの活動を支えているLaravel/
+
+今日は初日らしく軽〜い感じの内容で、日本語のドキュメントが見当たらないから書いちゃえ!と思った、「エラーログレベルを操作する」という内容です。
+
+※なお、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しか存在しない!)をオーバーライドすることで自由に実現できます。
+
+いじょーでした!
+enjoy! Laravel!!
+
+<br>
+
+<div><a href="http://twitter.com/M_Ishikawa"><img src="http://api.osae.me/retwipi/M_Ishikawa"> @M_Ishikawa</a></div>