エラーハンドリング・さらにつづき

先日のメモをまとめているうちに、おかしなところがちょっと見えてきたので、整理してコミットしました。大きくは変わっていないけれど、

  • ethna_handle_error()の定義をEthna_Logger.phpからEthna_Error.phpに移動
    • Ethna.phpでもよかったけれど、エラー回りって言うことで。
  • 「気を利かせて」エラーをprintしてくれちゃうのを抑制
    • エラーの表示設定はほぼアプリの設定ファイルだけで制御できるようになりました。

ってとこです。

ということで、設定ファイル etc/app-ini.php で関連する部分をかんたんにまとめてみました。

debug フラグ

'debug' => true,

気分としては、開発中と本番をわけるフラグ。これがtrueのときは、triggerされたエラーが(Ethna_Loggerの設定によらず)画面に表示されるようになります。ちなみに、以前はInfoManagerを表示するかどうかにしか使ってませんでした。

エラーがtriggerされたときの流れは次のようなかんじです。

  1. set_error_handler()されたethna_error_handler()が呼ばれる
  2. error_reporting()未満なら何もしないでreturn
  3. php自体のログが有効な時はerror_log()する
  4. Ethna_Loggerにログ出力を指示
    • 具体的に何をするかは app-ini.php の log の設定に依存
  5. debug=trueで、Ethna_Loggerにechoがない場合にエラー内容をprintする

たとえば、本番でとにかくエラーや警告を表示したくないときは、debug=falseでEthna_Loggerからechoを消しちゃえばOKです。

log_facility, log_level の設定

Ethna_Loggerがログ出力をするときに、具体的にどうするかを決めます。前にちょろっと書きましたが、エラーのレベルに応じてログを使い分けることが出来ます。

'log_facility'   => 'file,echo',
'log_level_file' => 'debug',
'log_level_echo' => 'notice',

こんなかんじで、debugレベルの細かすぎるログをファイルに、noticeレベルのエラーを画面に表示します。気分は開発中、ってとこですね。

ちょっと注意ですが、本当はログのレベルとエラーのレベルは別物です。上の例だとエラーレベルE_NOTICEがログレベルnoticeに対応しているので、混同してても問題ないってことです。2つのレベルの対応付けはEthna_Logger::errorLevelToLogLevel()でやっています。ふだん使うぶんにはごっちゃにしててもそんな問題ないと思います。

Ethna_Loggerがログ出力をする場面は

  • phpのエラーがtriggerされ、ethna_error_handler()の中でログ出力を指示された
  • Ethna::raiseError(), Ethna::raiseWarning(), Ethna::raiseNotice()が呼ばれ、コントローラのhandleError()からログ出力を指示された
  • ふつうにEthnaLoggerの$logger->log()が呼ばれた

の3つがあります。

エラーというよりログの話?

PEAR_Errorがそうであったように、エラー自体は「エラーというもの」でしかありません。それを見てどうするかが「エラーハンドリング」であり、まずはログを考えるのは自然だと思います。

ということで、上の話はほとんどログの設定みたいな内容でした。trigger_error()のようなphpのエラーは、returnされるわけでもtry-catchできるわけでもないので、ログをどうするかがほとんど全てになってしまいます。

ログ以外のEthna固有の話としては、error_reporting()とか@演算子をどう使うのがいいかとか、PEAR::raiseError(), Ethna::raiseError()ファミリをどう使い分けるか、っていうのがあると思います。これは個人のポリシがかなり反映されそうなので、また今度。