set_uk has asked for the wisdom of the Perl Monks concerning the following question:

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 lo +gs to it =cut my ($self, @args) = @_; my ($logfile, $logdir); # Just use the jobref id which will be a unique sequence to log in +to $logdir=$self->{LOG_DIR}.$args[0].$self->{U}.$self->LogTime; unless ( -e $logdir && -d $logdir){ mkpath($logdir) or throw TNBCriticalException("Cannot make direc +tory $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

Edit by tye, title, preserve formatting

Replies are listed 'Best First'.
Re: Log4Perl
by tilly (Archbishop) on Oct 29, 2003 at 18:26 UTC
    Reading the documentation for Log::Log4perl, it seems that they strongly prefer using config files. And then you would switch the logging behaviour just by changing the config files.

    If you don't like this answer, then the easiest thing to do is intercept all calls that initialize a logger and keep track of loggers automatically. When you need to reinitialize, you will then have that list and can walk it in an automated fashion. There are several ways to do this, but the one that I recommend is to rename your current Log4PerlInit methods to _Log4PerlInit and then somewhere high in your inheritance tree write the following (untested):

    sub Log4PerlInit { my ($self, @args) = @_; # Is this is an instance or class method? I don't # know what you are doing, so I will support both. $used_loggers{ref($self) || $self} = 1; $self->Log4PerlInit(@args); }
    And now you have a hash whose keys are all loggers that you have. Walk the keys of the hash and reset them.
      Thanks.

      Only reason I went with coding in the definitions was because I missed the part in the config which stated you could call in perl subs to define the parameters of the logger.

      Might be quicker to just revert to config file setup and then reread it every time I have a job switch

      Thanks for your help