質問

ActiveState Perl 5.12 on WinXP

I've recently become a convert to Log4perl and used it successfully where I defined a specific logger for each module that makes up my application. Example:

Upload.pm-----

my $logger = get_logger("Upload");  # specific logger
my $layout = Log::Log4perl::Layout::PatternLayout->new( "%d %p> %F{1}:%L %M - %m%n");
my $appender = Log::Log4perl::Appender->new( "Log::Dispatch::File",
                                     filename => "Upload.log",
                                     mode     => "append"
                    );
$appender->layout($layout);
$logger->level($OFF);    #  or $INFO
$logger->add_appender($appender)
....

This works but is hard to track program flow across numerous log files ie Upload.log , Parse.log , FileRead.log etc. Quick-n-dirty solution: use same filename in all loggers. This works much better, but only as long as the program is used serially and in sequence.

Now for the wrinkle - suppose module Upload.pm is used by several progams ie readMyFiles.pl, readHerFiles.pl and dumpAllFiles.pl . When running readMyFiles.pl I want the logger in Upload.pm to write to readMyFiles.pl.log and when runnng dumpAllFiles.pl want the logger in Upload.pm to write to dumpAllFiles.pl.log

One method might be to declare an our variable $logFileName in my .pl files and use it in all my modules like so:

                                      filename => $logFileName,

Another might be to remove all the loggers from my .pm's and define them only in the .pl's - but then how would I reference $logger in the .pm's ?

All thoughts and suggestions are appreciated.

Still-learning Steve

役に立ちましたか?

解決

Configure your logging settings in the caller, not in the module. If somebody else uses your module, they might not want to log things to the same place that you do. They might also want to format log messages differently, or use a different type of appender, or...the list goes on.

Your module should only get a logger and write messages to it:

MyModule.pm

#!/usr/bin/perl

package MyModule;

use strict;

use Log::Log4perl qw(get_logger);

sub foo {
    my $logger = get_logger("Foo");
    $logger->debug("Hello from MyModule");
}

1;

Your main program(s) should configure and initialize logging:

logtest

#!/usr/bin/perl

use strict;
use warnings;

use Log::Log4perl qw(get_logger);
use MyModule;

Log::Log4perl->init("log4perl.cfg");

my $logger = get_logger("Foo");
$logger->debug("Hello from main");

MyModule::foo();

I prefer to use a separate config file for Log4perl settings:

log4perl.cfg

log4perl.logger.Foo=DEBUG, Screen

log4perl.appender.Screen=Log::Dispatch::Screen
log4perl.appender.Screen.Threshold=DEBUG
log4perl.appender.Screen.layout=Log::Log4perl::Layout::PatternLayout
log4perl.appender.Screen.layout.ConversionPattern=[%r] %F %L %c - %m%n

Output:

[0] logtest 12 Foo - Hello from main
[0] MyModule.pm 11 Foo - Hello from MyModule

Note that you must initialize logging with Log::Log4perl->init in the caller before trying to get_logger in the module. If you don't, log messages from the module will be ignored and you'll get the following warning:

Log4perl: Seems like no initialization happened.
Forgot to call init()?

See the documentation for details.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top