8

Log::Log4perlを使用して、Log4perlを初期化していない呼び出しスクリプトがない場合でも、その操作をファイルに記録するスマートなセルフロギング モジュールを作成する方法はありますか? ドキュメントからわかる限り、Log4perl を使用する唯一の方法は、構成から実行中のスクリプトで初期化することです。次に、Log4perl 呼び出しを実装するモジュールは、呼び出し元の Log4perl 構成に基づいて自分自身をログに記録します。

代わりに、モジュールが Log4perl のデフォルトの初期化構成を提供することを望みます。これにより、モジュールのカテゴリのデフォルトのファイル アペンダが提供されます。次に、必要に応じて呼び出し側で別の構成を使用して Log4perl を開始することで、この動作をオーバーライドできます。うまくいけば、すべてがうまくいくでしょう。

この種の防御的なロギング動作は可能ですか? または、ログに記録したいモジュールを呼び出すすべての .pl スクリプトで Log4perl の初期化に依存する必要がありますか?

4

2 に答える 2

7

Mooseのカスタム ログ ロールでこれを行います(関係のない複雑なコードは削除されています)。

package MyApp::Role::Log;

use Moose::Role;
use Log::Log4perl;

my @methods = qw(
    log trace debug info warn error fatal
    is_trace is_debug is_info is_warn is_error is_fatal
    logexit logwarn error_warn logdie error_die
    logcarp logcluck logcroak logconfess
);

has _logger => (
    is => 'ro',
    isa => 'Log::Log4perl::Logger',
    lazy_build => 1,
    handles => \@methods,
);

around $_ => sub {
    my $orig = shift;
    my $this = shift;

    # one level for this method itself
    # two levels for Class:;MOP::Method::Wrapped (the "around" wrapper)
    # one level for Moose::Meta::Method::Delegation (the "handles" wrapper)
    local $Log::Log4perl::caller_depth;
    $Log::Log4perl::caller_depth += 4;

    my $return = $this->$orig(@_);

    $Log::Log4perl::caller_depth -= 4;
    return $return;

} foreach @methods;

method _build__logger => sub {
    my $this = shift;

    my $loggerName = ref($this);
    Log::Log4perl->easy_init() if not Log::Log4perl::initialized();
    return Log::Log4perl->get_logger($loggerName)
};

ご覧のとおり、ログ オブジェクトは自己初期化されます。Log::Log4perl->init呼び出されていない場合は、easy_init呼び出されます。これを簡単に変更して、各モジュールがそのロガーをカスタマイズできるようにすることができますref($this)。デフォルトのフォールバックとして、オプションの役割パラメーターを使用してそうします。

PS。MooseX::Log::Log4perlも参照してください。これは、上記のロガー ロールを使用する前に開始した場所です。いつの日か、私が追加したいくつかの機能を組み込むために、その MX モジュールに非常に必要なパッチをいくつか提出します。

于 2010-06-10T21:45:49.120 に答える
1

簡単な答えは、Log::Log4perl::initialized(); を呼び出すことです。ある時点で、それが false の場合は、デフォルトのログを設定します。

トリッキーな部分は「あるポイント」です。

BEGIN {} でそれを行うことはできません。なぜなら、不要なファイルを作成したとしても、メイン スクリプトが初期化を踏みにじるからです。get_logger() を呼び出すたびにそれを行うのは無駄なので、やりたくないでしょう。したがって、モジュールの初期化中にそれを行う必要があります。たとえば、sub new または sub init です。

于 2010-11-05T18:08:30.727 に答える