リアルタイム出力とカスタムロガーの登録 | Logging

例えば、次のようなコードを試してみてください。
for ($i = 0; $i < 5; $i++) {
  l("my message.");
  sleep(2);
}
ログファイルの内容をtailコマンドなどで監視すると、アプリケーションの処理が全て終わった後に全てのメッセージが一斉にファイルに出力されることが分かります。そう、メッセージは2秒おきに出力されるわけではありません。

リアルタイムに、l()関数を呼び出す度に書き出して欲しい場合は、下記のコードを追加してください。
Sabel_Logger::create()->realtime(true);

for ($i = 0; $i < 5; $i++) {
  ...
}
なお、realtime()メソッドにtrueが渡された場合、その時点まででバッファされていたメッセージは一斉に出力されます。

カスタムロガーの登録

独自のログ出力クラスをロガーに登録することが可能です。例えば、クリティカルな箇所で発生したエラーに関するメッセージをロガーに渡し、それをカスタムロガーで捕捉し開発者にメールで通知するなどに使用できます。

例えば重要なロジックで、下記のようにメッセージをロガーに送ります。
try {
  ...
} catch (MyException $e) {
  l("ERROR: " . $e->getMessage(), SBL_LOG_ERR, "critical");
  return false;
}
※このメッセージはデフォルトのロガーにも渡されるため、logs/critical.log にも出力されます。

次に、上記のログメッセージを捕捉するためのクラスを作成します。addLogger()するインスタンスは Sabel_Logger_Interface を実装していなくてはなりません。
class MyLogger implements Sabel_Logger_Interface
{
  public function output($logs)
  {
  
  }
  
  public function write($identifier, $message)
  {
  
  }
}
output()メソッド には全てのログが渡されます。渡される引数は配列で、以下のような構造となっています。識別子が配列のキーになっています。
array(2) {
  ["default"]=>
  array(4) {
    [0]=>
    array(3) {
      ["time"]=>
      string(19) "2009-01-01 00:00:00"
      ["level"]=>
      int(1)
      ["message"]=>
      string(14) "my message."
    }
    [1]=>
    array(3) {
      ["time"]=>
      string(19) "2009-01-01 00:00:01"
      ["level"]=>
      int(1)
      ["message"]=>
      string(14) "my message."
    }
  }
  ["critical"]=>
  array(1) {
    [0]=>
    array(3) {
      ["time"]=>
      string(19) "2009-01-01 00:00:02"
      ["level"]=>
      int(8)
      ["message"]=>
      string(11) "my message."
    }
  }
}
write()メソッド の第1引数には識別子が、第2引数にはメッセージが渡されます。メッセージとは time, level, message のキーを持った配列です。なお、このwrite()メソッド はリアルタイム出力時にのみ呼び出されるものです。
output() にはメッセージの配列が、write() にはメッセージの一つ一つが渡されるため、下記のようにすれば write()メソッドに処理を集約することができます。
public function output($logs)
{
  foreach ($logs as $identifier => $messages) {
    foreach ($messages as $message) {
      $this->write($identifier, $message);
    }
  }
}
今回作成したロガーは "critical" メッセージだけ捕捉すれば良いので、write()メソッド は次のように実装できます。メールを送信するコードを記述すれば目的としていたカスタムロガーの完成です。
public function write($identifier, $message)
{
  if ($identifier === "critical") {
    $mail = new Sabel_Mail("ISO-2022-JP");
    $mail->setFrom("systemerr@example.com");
    $mail->setTo("developer@example.com");
    $mail->setSubject("...");
    $mail->setBody("...");
    $mail->send();
  }
}
※メールの送信に関してはメールの章を参照してください。

関連項目