From: Simon T. <se...@no...> - 2003-10-29 22:48:58
|
I am using log4perl in a system which does the following:- Iterates over a list of jobs it gets from a database Creates a CommandHandler which uses Log4Perl CommandHandler calls Config which uses Log4Perl Calls CommandIterator which uses Log4Perl I am defining a Log4Perl logger each time I change jobs in perl code. sub Log4PerlInit{ # Set up log4perl =head2 NAME Used to set up the Log4Perl logger Sets it up for the calling class - but also ensures that this class logs to it =cut my ($self, @args) = @_; my ($logfile, $logdir); # Just use the jobref id which will be a unique sequence to log into $logdir=$self->{LOG_DIR}.$args[0].$self->{U}.$self->LogTime; unless ( -e $logdir && -d $logdir){ mkpath($logdir) or throw TNBCriticalException("Cannot make directory $logdir"); } $logfile=$logdir.$self->{DLM}."job".$args[0].".log"; $self->{CurLogFile} = $logfile; # Jump off and define a logger for this class $self->{_logfile} = $self->SelfLog("DEBUG"); # Define a category logger for the calling class my $log = Log::Log4perl->get_logger($args[1]); # Define a layout my $layout = Log::Log4perl::Layout::PatternLayout->new("[%d][%p] %M %m%n"); # Define a file appender my $file_appender = Log::Log4perl::Appender->new( "Log::Log4perl::Appender::File", name => "filelog", filename => "$logfile"); # Define a stdout appender my $stdout_appender = Log::Log4perl::Appender->new( "Log::Log4perl::Appender::Screen", name => "screenlog", stderr => 0); $stdout_appender->layout($layout); $file_appender->layout($layout); $log->add_appender($stdout_appender); $log->add_appender($file_appender); $log->level($args[2]); return $logdir,$log; } sub SelfLog{ # Set up log4perl for this class =head2 NAME Used to set up the Log4Perl logger =cut my ($self, @args) = @_; # Jump off and define a logger for this class # Define a category logger for the calling class my $log = Log::Log4perl->get_logger("SDU::Config"); # Define a layout my $layout = Log::Log4perl::Layout::PatternLayout->new("[%d][%p] %M %m%n"); # Define a file appender my $file_appender = Log::Log4perl::Appender->new( "Log::Log4perl::Appender::File", name => "filelog", filename => $self->{CurLogFile}); # 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); return $log; } The logger resets the filename so I should get a new log for each job. The logger is then saved as part of the object Log4PerlInit - is called from Config. SelfLog is used when i want to get the Config module to log to the same file as the module that called Log4PerlInit Even though all my objects exist in CommandHandler and that is undefed at the end of the cycle. The Log4Perl loggers continue to point to the original logfile. Whats the best way to undef all the loggers at each job change. Or put another way when running a long job how do I safely get log4perl to switch to a new log appender and stop using the old one Simon Taylor Managed Services Technology Consultant Nortel Networks p - 01279 404289 (ESN 742 4289) m - 07740 533743 (ESN 748 3743) e - se...@no... "I code therefore I am" |
From: Mike S. <msc...@ao...> - 2003-10-30 04:40:15
|
Simon Taylor wrote on 10/29/2003, 2:48 PM: > The logger resets the filename so I should get a new log for each job. I'm assuming by "job" you mean a call within the same (Unix) process -- correct? > The logger is then saved as part of the object Actually, loggers should *never* be saved in objects or elsewhere. You can always obtain them cheaply by calling get_logger("category"). This way, you're safe to change the configuration on the fly without ending up with stale loggers. > Log4PerlInit - is called from Config. > SelfLog is used when i want to get the Config module to log to the > same file as the module that called Log4PerlInit Not quite sure why you have two different functions -- there's a lot of code duplication between the two. Hopefully, you'll like the approach outlined further down. > Whats the best way to undef all the loggers at each job change. Or put > another way when running a long job how do I safely get log4perl to > switch to a new log appender and stop using the old one I won't suggest to call Log4perl's init() on every job, although that would probably work for your scenario. Unfortunately, our current file appender doesn't have a "switch_file" method. So, for now, you could create a new file appender class, inherit from L4p::Appender::File and define a switch_file method, blatently making use of L4p::Appender::File's private data: ################################################## package ReopeningFileAppender; ################################################## use warnings; use strict; use base qw(Log::Log4perl::Appender::File); ################################################## sub switch_file { ################################################## my($self, $newname) = @_; undef $self->{fh}; $self->{filename} = $newname; my $arrows = ">"; if($self->{mode} eq "append") { $arrows = ">>"; } my $fh = do { local *FH; *FH; }; open $fh, "$arrows$self->{filename}" or die "Can't open $self->{filename} ($@)"; $self->{fh} = $fh; } 1; __END__ If you put that code into ReopeningFileAppender.pm and define a configuration file l4p.conf like # l4p.conf log4perl.logger = DEBUG, APP1 log4perl.appender.APP1=ReopeningFileAppender log4perl.appender.APP1.layout = Log::Log4perl::Layout::SimpleLayout log4perl.appender.APP1.filename = test.log then your code is free to do something like Log::Log4perl->init("l4p.conf"); DEBUG("logged to test.log"); # Get appender and switch file on it my $app = Log::Log4perl::appenders()->{APP1}; $app->switch_file("foobar.log"); DEBUG("logged to foobar.log"); which first logs to test.log, then obtains the appender and causes it to flush its buffer to the old file and open a new one. Again, not pretty, because it assumes L4p::Appender::File isn't changing its private 'fh' handle, but for the next version, I might add a switch_file() method to our file appender. - -- Mike Mike Schilli m...@pe... |