日記
Zend Frameworkをどう使うか その16Edit

あとふつうに使いそうなクラスといったらどれだろうなー、とつらつらながめてみて、俺的に重要度が高そうだったZend_Logクラスを見てみた。

まず、基本的にZend_Logクラスでは、すべてのログ出力は、

Zend_Log::log($message, $level, $logName_or_fields, $logName);

というpublic staticなクラスメソッドを経由して行う。ログ出力がしたければどこでも

Zend_Log::log('log message', Zend_Log::LEVEL_INFO);

なんて書くだけでいい。ただし、これだけではログを記録する実体がないんで、何も起こらないけど。

ログ記録の実体は、Zend_Log_Adapter_*というクラスが受け持つ。これはZend_Log_Adapter_Interfaceを持つクラス群で、open、write、close、setOptionという4つのメソッドが実装されていればいい。

標準では

  • Zend_Log_Adapter_Console - コンソール出力用
  • Zend_Log_Adapter_Db - DB出力用
  • Zend_Log_File - ファイル出力用
  • Zend_Log_Null - 何もしない。これって何のためにあるんだっけ? Null Logの意味が説明されているテキストをどこかで読んだ気がするんだけど。

が用意されている。ファイルログを出力したければ、

Zend_Log::registerLogger(new Zend_Log_Adapter_File('/path/to/log');

なんてあらかじめログ出力用Adapterを登録しておけばいい。マルチログにも対応していて、

Zend_Log::registerLogger(new Zend_Log_Adapter_File('/path/to/log'), 'file');
Zend_Log::registerLogger(new Zend_Log_Adapter_Db($db /* Zend_Db_Adapter */, 'tablename'), 'db');

なんて感じで、第2引数にログ名をつけて複数のAdapterを登録しておく。特定のAdapterに対して操作したい場合は、ここでつけたログ名を指定した、Zend_Logのクラスメソッドを呼ぶことになる。ログ名が省略された場合はデフォルトのログ名('LOG')が使われる。

出力先ごとに出力を行うLogLevelを設定したい場合は、

Zend_Log::setLevel(Zend_Log::LEVEL_DEBUG, 'debuglog'); // debuglogはログ名
Zend_Log::setMask(Zend_Log::LEVEL_ALL ~ Zend_Log::LEVEL_DEBUG); // ログ名を省略した場合は標準のログ

なんて感じでセットすればいい。

んだけど、試してみたらうまく動かなかった。ソースを見てみたら、Zend/Log.phpの382行目が

        if ($level | $logger->_levelMask) {

になってたけど、これって

        if ($level & $logger->_levelMask) {

の間違いだよね。一応こっちもMLに投げておいた

ちなみに内部的に「ZF」というログ名は、Zend Framework内部のログ出力用に予約されている模様。Zend Frameworkレベルの動作が怪しい場合なんかには、ZFという名前でログ出力先を登録しておけば、フレームワークレベルでのログが保存されるようになるんだろう。ただ現時点ではZend Frameworkを構成するファイルで、その機能を使っているものはないみたいだけど。

とまあ一通りのことはできるんだけど、マルチログの機能をデフォルトで取り込んだんだったら、すべてのログ出力先に(LogLevelの設定に応じて)ログを出力する機能もつけて欲しいよなー。PEAR LogのComposite Loggerみたいなやつ。まあZend_Log_Adapter_Compositeとかを作って、それをデフォルトロガーにすれば、現在の仕様でもやりたいことはできるんだけど。

っつーか、Zend_Log::logは$logNameが指定されていない場合は、登録されているすべての出力先に(LogLevelに応じて)ログを出力する、という仕様の方がいいんじゃないだろうか。それがダメなら、Zend_Log::logAllとか別にメソッドを追加するか、かな。

ちなみに前者の方法を実現する場合は、Zend/Log.php 353行目あたりに、次のようなパッチを当てればいい。

        if (is_null($logName)) {
-             $logName = self::$_defaultLogName;
+             $logName = array_keys(Zend_Log::$_instances);
+             if (isset($logName['ZF'])) {unset($logName['ZF']);}

ひとまず現状の設計に合わせて、Zend_Log_Adapter_Compositeを作って試してみて、それがいまいちならこっちもMLに投げてみようかなー。でも俺の英語表現がつたないせいか、微妙にスルーされている気もしないでもない。

Published At2006-03-25 00:00Updated At2006-03-25 00:00