Создание модулей самостоятельной регистрации с Log :: Log4perl - PullRequest
8 голосов
/ 11 июня 2010

Есть ли способ использовать Log :: Log4perl для создания интеллектуального модуля самостоятельной регистрации, который записывает свои операции в файл даже в отсутствие вызывающего сценария, не инициализирующего Log4perl? Насколько я могу судить из документации, единственный способ использовать Log4perl - это инициализировать его в запущенном скрипте из конфигурации, а затем модули, реализующие вызовы Log4perl, сами регистрируют журнал на основе конфигурации Log4perl вызывающей стороны.

Вместо этого я бы хотел, чтобы модули предоставили конфигурацию инициализации по умолчанию для Log4perl. Это обеспечит стандартный файл appender для категории модуля. Затем я мог бы переопределить это поведение, запустив Log4perl в вызывающей программе с другой конфигурацией, если это необходимо, и, надеюсь, все будет просто работать.

Возможен ли такой тип защитного ведения журнала или мне нужно полагаться на запуск Log4perl в каждом сценарии .pl, который вызывает модуль, который я хочу зарегистрировать?

Ответы [ 2 ]

7 голосов
/ 11 июня 2010

Я делаю это в пользовательской роли Log в 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, чтобы включить некоторые функции, которые я добавил.

1 голос
/ 05 ноября 2010

Краткий ответ - вызвать Log :: Log4perl :: initialized ();в какой-то момент, и если оно ложно, настройте ведение журнала по умолчанию.

Сложная часть - это «какая-то точка».

Вы не можете сделать это в НАЧАЛЕ {}, потому что тогда основной скрипт помешает вашей инициализации, даже если вы создали ненужные файлы.Вы не хотите делать это перед каждым вызовом get_logger (), потому что это расточительно.Так что вы должны сделать это во время инициализации модуля, скажем, sub new или sub init.

...