Log4perl: How to dynamically load applications at runtime?

I would like to have modules that control their logging at runtime, but without using just one monolithic configuration file. When you work with processes running under different permissions, I really do not want to deal with every process that should have access to every log in the system when they write only a subset of them.

However, I did not find much documentation in the Log4perl manual on how to initialize additional applications from the configuration file at run time. http://metacpan.org/pod/Log::Log4perl::Appender refers to the add_appender method, but works with instances of appender objects instead of conf files. It also does not define journal objects and registrar-> attachment relationships.

I tried using every init package from my own conf, but it just grabs the existing configuration every time it gets initialized. What I would like to do is something like:

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 

How can I parse and add a configuration to the current configuration?

Edit: Probalem using a package variable is that it is simply the Moose role consumed by the various classes, pretty much just the MooseX :: Role :: Parameterized version of the Ether response in Creating Self-Service Modules with Log :: Log4perl . Thus, my registrar is populated into the library that consumes it, and I do not have a global variable that I can work with every time I use it.

Although..

If I declare a global variable outside the MooseX :: Role :: Parameterized role block, will each class that uses this role use the same conf variable?

+8
logging perl log4perl
source share
2 answers

You may recall which configuration files have already been downloaded ( %log_configs hash in the code below). When a new class arrives, you can re-read all the configs, merge it together and init Log::Log4perl again using the init string reference parameter.

I usually prefer to have one log configuration for each application due to easier support and reload.

 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; 
+5
source share

While I was hoping to avoid this, if I analyze the configuration files myself, I can access the configuration in perl through the API registered in http://search.cpan.org/perldoc?Log::Log4perl . Namely,

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

While the other method works, there are too many caveats for me to be comfortable using (I used this library, why did my journal stop?) - this is too surprising for my tastes.

Instead, I think I'll see if I can get the Log :: Log4perl state from the configuration file by looking at how to use the Log :: Log4perl :: Config :: PropertyConfigurator , to which → init is delegated when parsing the configuration file. If I go through the data structure that returns, I can compare the changes in the initialization based on the log behind the logger and appender-by-appender and change the initialization state accordingly, correctly handle namespace conflicts, etc.

+5
source share

Source: https://habr.com/ru/post/651172/


All Articles