8

実行時にログを管理するモジュールが必要ですが、すべてが単一のモノリシック構成ファイルを参照することはありません。さまざまなアクセス許可で実行されているプロセスを処理する場合、システム上のすべてのログにアクセスできるようにする必要がある各プロセスを処理したくありません。

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

各パッケージを独自のconfから初期化しようとしましたが、初期化されるたびに既存の構成が単純に上書きされます。私がやりたいことは、次のようなものです。

my $foo = Foo->new() ## Checks Log::Log4perl::initialized(), sees that it
                     ## hasn't been initalized yet, inits Log4perl from foo.conf
my $bar = Bar->new() ## Checks Log::Log4perl::initialized(), sees that it
                     ## has been initalized. Adds appenders and loggers defined
                     ## in bar.conf into the initialized configuration

構成を解析して現在の構成に追加するにはどうすればよいですか?

編集:パッケージ変数を使用する際の問題は、これがさまざまなクラスによって消費される Moose ロールにすぎないことです。ほとんどの場合、Making self-logging modules with Log::Log4perlの Ether の回答の MooseX::Role::Parameterized バージョンです。したがって、私のロガーはそれを使用するライブラリに組み込まれており、使用するたびに作業できるグローバル変数がありません。

けれど..

MooseX::Role::Parameterized ロール ブロックの外でグローバル変数を宣言すると、そのロールを使用するすべてのクラスが同じ conf 変数を使用することになりますか?

4

2 に答える 2

5

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

メンテナンスとリロード機能が容易なため、通常はアプリケーションごとに 1 つのログ構成を使用することを好みます。

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;
于 2011-01-21T09:57:51.070 に答える
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);

他の方法は機能しますが、快適に使用するには注意点が多すぎます (このライブラリを使用したのに、なぜログが停止するのでしょうか?) -- 私の好みにはあまりにも驚くべきことです。

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

于 2011-01-25T15:09:59.813 に答える