From: <log...@pe...> - 2002-12-17 05:11:48
|
Welcome to the Log::Log4perl recipe of the week. Today: ============================================================ Log::Log4perl Recipe of the Week (#8): What if I need dynamic values in a static Log4perl configuration file? ============================================================ Say, your application uses Log::Log4perl for logging and therefore comes with a Log4perl configuration file, specifying the logging behaviour. But, you also want it to take command line parameters to set values like the name of the log file. How can you have both a static Log4perl configuration file and a dynamic command line interface? As of Log::Log4perl 0.28, every value in the configuration file can be specified as a *Perl hook*. So, instead of saying log4perl.appender.Logfile.filename = test.log you could just as well have a Perl subroutine deliver the value dynamically: log4perl.appender.Logfile.filename = sub { logfile(); }; given that "logfile()" is a valid function in your "main" package returning a string containing the path to the log file. Or, think about using the value of an environment variable: log4perl.appender.DBI.user = sub { $ENV{USERNAME} }; When "Log::Log4perl->init()" parses the configuration file, it will notice the assignment above because of its "sub {...}" pattern and treat it in a special way: It will evaluate the subroutine (which can contain arbitrary Perl code) and take its return value as the right side of the assignment. A typical application would be called like this on the command line: app # log file is "test.log" app -l mylog.txt # log file is "mylog.txt" Here's some sample code implementing the command line interface above: use Log::Log4perl qw(get_logger); use Getopt::Std; getopt('l:', \our %OPTS); my $conf = q( log4perl.category.Bar.Twix = WARN, Logfile log4perl.appender.Logfile = Log::Dispatch::File log4perl.appender.Logfile.filename = sub { logfile(); }; log4perl.appender.Logfile.layout = SimpleLayout ); Log::Log4perl::init(\$conf); my $logger = get_logger("Bar::Twix"); $logger->error("Blah"); ########################################### sub logfile { ########################################### if(exists $OPTS{l}) { return $OPTS{l}; } else { return "test.log"; } } Every Perl hook may contain arbitrary perl code, just make sure to fully qualify eventual variable names (e.g. %main::OPTS instead of %OPTS). SECURITY NOTE: this feature means arbitrary perl code can be embedded in the config file. In the rare case where the people who have access to your config file are different from the people who write your code and shouldn't have execute rights, you might want to set $Log::Log4perl::ALLOW_CODE_IN_CONFIG_FILE = 0; before you call init(). This will prevent Log::Log4perl from executing *any* Perl code in the config file (including code for custom conversion specifiers (see "Custom cspecs" in Log::Log4perl::Layout::PatternLayout). Have fun! Until next week. -- Mike ################################### # Mike Schilli # # log...@pe... # # http://perlmeister.com # # http://log4perl.sourceforge.net # ################################### |