【PHP】 例外をキャッチしてログに出力するとき 【#np2020】

PHP logo
例外をキャッチしてログに出力するときよくこう書いてました。


try {
   ....
   throw new \Exception('エラーが起きたよ');
}  catch(\Exception $e) {
   \Log::error($e->getMessage());
}


こうすると当然ログには


ERROR - 2019-09-02 13:44:52 --> エラーが起きたよ


としか記録されず、ファイル名やエラーが起きた場所などは記録されません。他のフレームワークだとちゃんと出力されるのになあ、Laravelだけこうなのかなあと疑問に思っていたんだけどそれはもちろん誤解で、普段使っているフレームワークではログ出力用の独自関数を用意して、加工してログ出力していただけでした。

たとえばこんなの。


\Log::error(json_encode(array(
   'URL'           => Input::server('REQUEST_URI')
   ,'Message'      => mb_convert_encoding($e->getMessage(),'UTF-8')
   ,'Filename'     => $e->getFile()
   ,'Line Number'  => $e->getLine()
   ,'Trace'        => $e->getTraceAsString()
),JSON_UNESCAPED_UNICODE));


(json_encode() してるのは CloudWatchで見る場合に1エラー1行になっていた方が見やすいからです)


その誤解に気付いてLaravelでも独自関数を実装しようと思ったのだけど……


これでいけることに気付きました。


try {
   ....
}  catch(\Exception $e) {
   \Log::error($e);
}


こうするだけでログ出力はこんな感じになります。


[2019-09-02 12:07:23] local.ERROR: ErrorException: Invalid argument supplied for foreach() in /laravel/app/Console/Commands/sample.php:62
Stack trace:
#0 /laravel/app/Console/Commands/sample.php(62): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Invalid argumen...', '/laravel/...', 62, Array)


ていうかまあこれ、PHPのドキュメントに書いてあるんですけどね。


例1 Exception::__toString() の例

<?php
try {
   throw new Exception("Some error message");
} catch(Exception $e) {
   echo $e;
}
?>

上の例の出力は、 たとえば以下のようになります。

exception 'Exception' with message 'Some error message' in /home/bjori/tmp/ex.php:3
Stack trace:
#0 {main}

PHP: Exception::__toString – Manual


RequestURIや、UserAgentなども出力したい場合には、独自関数や例外拡張などで出力をカスタマイズしてやる必要がありますが、どこでどんなエラーが起きたかを記録しておきたいだけならこれで十分です。


そうだったのか。