読者です 読者をやめる 読者になる 読者になる

10分ぐらいで学べるSymfony2 〜Symfony2のログ設定を見てみる編〜

Symfony2のデフォルトの設定を見ていきます
デフォルトコンフィグ

ログ出力例

loggerは「Symfony\Bridge\Monolog\Logger」で「Monolog/Logger」を継承しており
そこでinfoやerrメソッドが定義されてます。
メイン処理は「vendor/monolog/src/Monolog/Logger.php」を見ると理解しやすいかなと思います

出力処理

$logger = $this->get('logger');
$logger->info('We just got the logger');
$logger->err('An error occurred');

表示結果

[2011-10-23 16:17:07] app.INFO: We just got the logger [] []
[2011-10-23 16:17:07] app.ERROR: An error occurred [] []

dev環境


devの設定を見るとこのような設定となっています。

$ vi app/config/config_dev.yml
monolog:
    handlers:
        main:
            type:  stream
            path:  %kernel.logs_dir%/%kernel.environment%.log
            level: debug
        firephp:
            type:  firephp
            level: info

devだとMonologBundleでDebugHandlerが追加されるのでログ出力時には3つのハンドラがコールされます。

(1)Symfony\Bridge\Monolog\Handler\FirePHPHandler
→実体:vendor/monolog/src/Monolog/Handler/FirePHPHandler.phpFirefoxのコンソール用ヘッダ出力

(2)Monolog\Handler\StreamHandler
→実体:vendor/monolog/src/Monolog/Handler/StreamHandler.php
→logファイルへ出力

(3)Symfony\Bridge\Monolog\Handler\DebugHandler
→実体:vendor/monolog/src/Monolog/Handler/TestHandler.php
→ログを配列に貯めこみます。(たぶんデバック用)

prod環境

prodの設定を見るとこのような設定となっています。

monolog:
    handlers:
        main:
            type:         fingers_crossed
            action_level: error
            handler:      nested
        nested:
            type:  stream
            path:  %kernel.logs_dir%/%kernel.environment%.log
            level: debug


prodの場合、ログ出力時に「Monolog\Handler\FingersCrossedHandler」のみコールされます。
FingersCrossedHandlerで「$this->buffer」にすべてのレベルのログをバッファしつつ
「$this->handler」に設定されてるnestedのハンドラをコールしてます。
エラー時にデバッグレベルも含めて出力してくれるための機能だそうです。

$ vi ./vendor/monolog/src/Monolog/Handler/FingersCrossedHandler.php
 61     public function handle(array $record)
 62     {
 63         if ($this->buffering) {
 64             $this->buffer[] = $record;
 65             if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) {
 66                 array_shift($this->buffer);
 67             }
 68             if ($record['level'] >= $this->actionLevel) {
 69                 if ($this->stopBuffering) {
 70                     $this->buffering = false;
 71                 }
 72                 if (!$this->handler instanceof HandlerInterface) {
 73                     $this->handler = call_user_func($this->handler, $record, $this);
 74                 }
 75                 if (!$this->handler instanceof HandlerInterface) {
 76                     throw new \RuntimeException("The factory callback should return a HandlerInterface");
 77                 }
 78                 $this->handler->handleBatch($this->buffer);
 79                 $this->buffer = array();
 80             }
 81         } else {
 82             $this->handler->handle($record);
 83         }
 84
 85         return false === $this->bubble;
 86     }


参考

■gitのmonologのREADME
https://github.com/Seldaek/monolog

■ゆっくり*ゆっくり
http://d.hatena.ne.jp/Fivestar/20110801/1312217024

■Symfony2のマニュアル
・cookbookマニュアル
http://symfony.com/doc/2.0/cookbook/logging/monolog.html
・コンフィグ
http://symfony.com/doc/2.0/reference/configuration/monolog.html
・さらなる設定例
http://symfony.com/doc/2.0/reference/dic_tags.html#dic-tags-monolog-processor