Log4perl: Как динамически загружать приложения во время выполнения? - PullRequest
8 голосов
/ 17 января 2011

Я хотел бы иметь модули, управляющие их журналированием во время выполнения, но не имея всего, ссылающегося на один монолитный файл конфигурации.Имея дело с процессами, выполняющимися с разными разрешениями, я действительно не хочу иметь дело с каждым процессом, которому необходимо иметь доступ к каждому журналу в системе, когда они только записывают подмножество из них.

ОднакоЯ не нахожу много документации в руководстве Log4perl о том, как инициализировать дополнительные дополнения из файла конфигурации во время выполнения.http://metacpan.org/pod/Log::Log4perl::Appender ссылается на метод add_appender, но он работает с экземплярами объектов appender, а не с файлами conf.Он также не определяет объекты logger и отношения logger-> appender.

Я попытался получить каждый пакет init из своего собственного 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, используемая различными классами, в значительной степени просто версия ответа MooseX :: Role :: Parameterized в Создание модулей самостоятельной регистрации с Log :: Log4perl .Таким образом, мой регистратор собирается в библиотеку, потребляющую его, и у меня нет глобальной переменной, с которой я могу работать каждый раз, когда использую ее.

Хотя ..

Если я объявлюглобальная переменная вне блока ролей MooseX :: Role :: Parameterized, будет ли каждый класс, использующий роль, использовать одну и ту же переменную conf?

Ответы [ 2 ]

5 голосов
/ 25 января 2011

Хотя я надеялся избежать этого, если я сам проанализирую файлы конфигурации, я смогу получить доступ к конфигурации в perl через API, описанный в http://search.cpan.org/perldoc?Log::Log4perl. А именно,

  ########################
  # 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);

Хотя другой метод работает, у меня слишком много предостережений, чтобы мне было удобно его использовать (ну и дела, я использовал эту библиотеку, почему моя регистрация остановилась?) - это слишком удивительно для моих вкусов.

Вместо этого, я думаю, я пойду, не смогу ли я перейти из конфигурационного файла в состояние Log :: Log4perl, посмотрев, как использовать Log :: Log4perl :: Config :: PropertyConfigurator, который делегируется -> init, когда требуется анализ файла конфигурации. Если я просматриваю возвращаемую структуру данных, я могу сравнить изменения с инициализацией на основе логгера за логгером и аппендера за аппендером и соответствующим образом изменить инициализированное состояние, правильно обработать коллизии пространства имен и т. Д.

5 голосов
/ 21 января 2011

Вы можете вспомнить, какие конфигурационные файлы уже были загружены (%log_configs хэш в коде ниже).Когда приходит новый класс, вы можете перечитать все конфиги, объединить их и снова инициализировать Log::Log4perl, используя строковый параметр ссылки на init.

Я обычно предпочитаю иметь одну конфигурацию журнала для каждого приложения, потому что это проще в обслуживаниии перезагрузить возможность.

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;
...