2011-01-17 20 views
8

実行時にモジュールをロギングするようにしたいのですが、すべてが単一のモノリシックな設定ファイルを参照する必要はありません。異なる権限で実行されているプロセスを扱う場合、システムのすべてのログにアクセスできるようにするために、各プロセスに対処する必要はありません。Log4perl:実行時にアペンダーを動的にロードするにはどうすればよいですか?

しかし、実行時に構成ファイルから追加のアペンダーを初期化する方法については、Log4perlのマニュアルで多くのドキュメントが見つかりません。 http://metacpan.org/pod/Log::Log4perl::Appenderはadd_appenderメソッドを参照しますが、これはconfファイルの代わりにインスタンス化されたappenderオブジェクトで機能します。また、ロガーオブジェクトとlogger-> appender関係も定義しません。

私は独自のconfから各パッケージのinitを試してみましたが、初期化するたびに既存のconfigをclobbersするだけです。私がしたいのは、次の行に沿った何かです:

どのように解析して現在の設定に追加できますか?

編集:パッケージ変数を使用するProbalemは、さまざまなクラスによって消費されるMooseの役割であり、かなり多くのMooseX :: Role :: ParameterizedバージョンのEtherの回答はMaking self-logging modules with Log::Log4perlです。したがって、私のロガーはそれを消費するライブラリに構成されており、私はそれを使うたびに動作するグローバル変数を持っていません。私はMooseX ::役割の外でグローバル変数を宣言する場合は::パラメータ化された役割ブロックを

けれども...

、役割を消費一人ひとりのクラスは、同じconfに変数を使用することでしょうか?

+0

誰でも?私はLog4perlのソースをちょっと見てきましたが、これをやりたかった最初の人になることはできません。 configファイルをロールに渡すことができるクラスに適用できるMoose paramererizedロールを作成しようとしています。confファイルを初期化するか、confファイルの設定を現在の初期化されたファイルに追加するだけで正しいことができます。 Log4perl。 – Oesor

+0

@Oesor:パッケージグローバルは、Mooseの役割で宣言されていても、引き続きグローバルです。ロールを使用するために以下のソリューションを変更するのは簡単です( 'BUILD'メカニズムの代わりに' BUILDARGS'を非常によく似たコードで使用できます)。 – bvr

+0

@Oesor:前のコメントごとに以下のコードを更新しました。 – bvr

答えて

5

既にロードされている設定ファイル(以下のコードでは%log_configsハッシュ)を覚えておくことができます。新しいクラスが到着したら、すべてのコンフィグを再度読み込み、マージしてinitに文字列参照パラメータを使用してLog::Log4perlを再度初期化することができます。

私は一般的に、メンテナンスとリロードの容易性のために、アプリケーションごとに単一のログ構成を使用することをお勧めします。

package Logger; 
use Moose::Role; 
use Log::Log4perl; 

our %log_configs =(); 

around BUILDARGS => sub { 
    my $orig = shift; 
    my $class = shift; 

    my $config_name = lc($class) . '.conf'; 

    # if the config is not integrated yet 
    if(! defined $log_configs{$config_name}) { 
     $log_configs{$config_name} = 1; 

     # reload all configs including new one 
     my $config_text = ''; 
     for my $file (sort keys %log_configs) { 
      $config_text .= "\n" . do { 
       local $/; # slurp 
       unless(open my $fh, "<", $file) { 
        warn "$file could not be open\n"; 
        ''; 
       } 
       else { 
        <$fh> 
       } 
      }; 
     } 

     # refresh config 
     Log::Log4perl::init(\$config_text); 
    } 

    return $class->$orig(@_); 
}; 


package Foo; 
use Moose; 
with 'Logger'; 
use Log::Log4perl ':easy'; 

sub BUILD { 
    ERROR 'Foo reporting'; 
} 


package Bar; 
use Moose; 
with 'Logger'; 
use Log::Log4perl ':easy'; 

sub BUILD { 
    INFO 'Bar reporting'; 
} 


package main; 

my $foo = Foo->new; 
my $bar = Bar->new; 
+1

多かれ少なかれ私はそれをやるだろう。おそらく、initでevalをラップし、initで終了した場合は最新のconfigファイルを削除することをお勧めします。無関係のアプリケーションをクラッシュさせる悪いロギング設定ファイルより悪いことはありません。 %log_configsハッシュにフラグ値を追加して、不正な設定ファイルを示すことは難しくありません。 –

+1

@ Mark Tozzi - 実際のアプリケーションでこのようなアプローチを使用する場合は、間違いなく適切なエラー処理を追加する必要があります。スニペットを概念実証として考えてください。もう一つの便利な追加は、このハードコーディングされたサンプル(btwは 'Foo :: Bar'のような名前空間のクラスでは動作しません)ではなく、クラス名にデフォルト設定されているログconfigの名前を指定するプロパティかもしれません。 – bvr

5

私はそれを避けるために期待していたが、私は設定は自分自身をファイル解析場合、私はその後、http://search.cpan.org/perldoc?Log::Log4perlに文書化されたAPIを経由してperlでの設定にアクセスすることができます。すなわち、

######################## 
    # Initialization section 
    ######################## 
    use Log::Log4perl; 
    use Log::Log4perl::Layout; 
    use Log::Log4perl::Level; 

    # Define a category logger 
    my $log = Log::Log4perl->get_logger("Foo::Bar"); 

    # Define a layout 
    my $layout = Log::Log4perl::Layout::PatternLayout->new("[%r] %F %L %m%n"); 

    # Define a file appender 
    my $file_appender = Log::Log4perl::Appender->new(
          "Log::Log4perl::Appender::File", 
          name  => "filelog", 
          filename => "/tmp/my.log"); 

    # Define a stdout appender 
    my $stdout_appender = Log::Log4perl::Appender->new(
          "Log::Log4perl::Appender::Screen", 
          name  => "screenlog", 
          stderr => 0); 

    # Have both appenders use the same layout (could be different) 
    $stdout_appender->layout($layout); 
    $file_appender->layout($layout); 

    $log->add_appender($stdout_appender); 
    $log->add_appender($file_appender); 
    $log->level($INFO); 

他の方法で動作しますが、私はそれを使用して快適にするためにあまりにも多くの注意点(ジーは、私は私の伐採停止why'd、このライブラリを使用?)があります - それは私の好みのためあまりにも驚きです。

代わりに、configファイルからLog :: Log4perl状態に到達することができないかどうかは、configファイルの解析時に - > initによって委任されるLog::Log4perl::Config::PropertyConfiguratorの使い方を調べることで確認できます必要です。私が返すデータ構造を調べると、ロガーごとのロガーとアペンダーごとのアペンダーごとの初期化の変更を比較し、初期化された状態を適切に変更したり、名前空間の衝突を適切に処理したりすることができます。

関連する問題