CodeIgniterの学習 42 - デバグ用のログメッセージを簡単且つ行番号付きで表示できるようにする

今日はCodeIgniterログメッセージの呼び出し方を楽にしてみる。

以下不平不満

CodeIgniterのログメッセージは、

system/codeigniter/Common.php 内で定義されている

function log_message($level = 'error', $message, $php_error = FALSE)

を使うのだが、(ちなみに第三引数は使ってないみたい。)

これが非常に気にくわない。



(理由)
1)綴りが長くて面倒、コーディング中にがしがしデバッグメッセージを差し込む気になれなくなる。
疲れるので4文字以上キーを打ちたくない。(コードアシスト使っているならば問題ないかもしれないが。)


2)引数の順序が $level ,$message の順のせいで、手早くデバグ用ダンプを渡したい時に$levelを毎回指定するのが面倒

log_message('debug',$str);みたいに毎回書くのはつらいのだ。
俺は記憶力が悪いので書いているうちに何やってんのか忘れる。

だいたい第一引数はデフォルト値を持っていて、第二引数にはデフォルト値を持たせていないのってどーなのよ?


3)stringにして渡すのが面倒
これは別に無くてもいいんだが、
arrayとかobjectの中身をちょっと覗きたい時に log_message('debug',print_r($val,true));みたいに渡さないといけないのが面倒。


4)ログの呼出元の情報を出したい。(呼出元のファイル名、行番号、メソッド名をログに出したい)
がりがり解析・デバグしていこうとすると、必要だよね。


5)log_messageが、Common.phpに居やがってくれるので、オーバーライドが出来ない。
他のヘルパみたいにオーバーライドしたいのに出来ないよー。



とまあいろいろある。

そもそもログ周りの機能が適当つうか貧弱に感じるので、ログはZend_Logに置き換えるつもり。その作業履歴は明日書く予定。
Log周りの仕様は、開発初期に適当に作ったソースが残り続けているように感じる。(今更いじれない感も)


改良ラッパーを作る

文句を言ってるだけでは始まらないので改良ラッパを作ることにする。

以前、俺俺ヘルパとして、application/helpers/cmn_helper.phpを作り、
これをautoloadで読み込むようにしているので、取りあえずこのファイルに追記することにする。

以下ソース

application/helpers/cmn_helper.php

<?php
//上略
if ( ! function_exists( 'logd' ) ) {
  //log_messageのラッパー
  //log_messageが長い上に引数の順序が非常に気に入らないので
  //短縮形のラッパを作った(デフォルトログレベルはdebug)
  //ついでに引数に配列、オブジェクトを渡せるようにした。
  //ついでに呼出元ファイル名、行番号、メソッド名を追記を可能にした

  function logd($data , $add_str='', $level='debug' , $show_filename=true)
  {

    //配列、オブジェクトは自動展開する
    if(is_array($data) || is_object($data)){
      $space = "\n";
      $message = print_r($data,true) . $space . $add_str ;

    }else{
      $space = ' ';
      $message = $data . $space . $add_str ;
    }

    if($show_filename){
      $dbg = debug_backtrace();
      //呼出元ファイル名、行番号、メソッド名を追記
      $fname = ( isset($dbg[0]['file'] ) ) ? 'FILE:' . $dbg[0]['file'] : '';
      $line = ( isset($dbg[0]['line'] ) ) ? ' , LINE:' . $dbg[0]['line'] : '';
      $func = ( isset($dbg[1]['function'] ) ) ? ' , FUNCTION:' . $dbg[1]['function'] : '';
      $message = '[' . $fname . $line . $func . ']' . $space . $message ;
    }
    log_message($level , $message);
  }
}
//下略
 ?>


使い方

1)デバグしたい任意の箇所で、

logd($query -> result());

みたいに書けばよい。これで書く時間が3秒は短縮できる。

2)ついでに何かメッセージを付加したければ

logd($query -> result(),'ほげほげ');

で渡せる。

3)単純に文字列だけならば、

logd('ふがふが');

でよい。


吐かれるログは、

DEBUG - 2008-11-16 01:51:08 --> Table Class Initialized
DEBUG - 2008-11-16 01:51:08 --> [FILE:/var/vhosts/citest.example.com/CodeIgniter_1.7.0/application/controllers/tasklist.php , LINE:52 , FUNCTION:page]
Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [user_name] => ユーザー名だよ
            [title] => タイトルだよ1
            [note] => 内容だよ
(中略)

        )

)

DEBUG - 2008-11-16 01:51:08 --> Pagination Class Initialized
DEBUG - 2008-11-16 01:51:08 --> File loaded: ../application/views/tasklist_index.php

みたいに、ファイル名行番号付きログを吐けるようになる。めでたしめでたし。

ちなみにprint_rなのは、var_exportだとでかいオブジェクトを渡したら「Fatal error: Nesting level too deep」になるから。

ファイル名行番号情報を先に記録するのは俺の好み。普通は後ろだと思う。


本当はこれでも足りないんだけど、あとはお好きに。
(仕事で真面目にやるならばエラーメッセージ(エラーコード表)一覧からメッセージ自動取得、エラー時に管理者にメール送信等々)



明日はZend_Logへの置き換えを予定。