From: <msc...@ao...> - 2002-12-05 21:26:14
|
Hi all, welcome to the Log::Log4perl Recipe of the Week. Today: ============================================================ How can I make sure my application logs a message when it dies unexpectedly? ------------------------------------------------------------ Whenever you encounter a fatal error in your application, instead of saying something like open FILE, "<blah" or die "Can't open blah -- bailing out!"; just use Log::Log4perl's fatal functions instead: my $log = get_logger("Some::Package"); open FILE, "<blah" or $log->logdie("Can't open blah -- bailing out!"); This will both log the message with priority FATAL according to your current Log::Log4perl configuration and then call Perl's "die()" afterwards to terminate the program. It works the same with stealth loggers (see "Stealth Loggers" in the Log::Log4perl documentation), all you need to do is call use Log::Log4perl qw(:easy); open FILE, "<blah" or LOGDIE "Can't open blah -- bailing out!"; What can you do if you're using some library which doesn't use Log::Log4perl and calls "die()" internally if something goes wrong? Use a $SIG{__DIE__} pseudo signal handler: use Log::Log4perl qw(get_logger); $SIG{__DIE__} = sub { $Log::Log4perl::caller_depth++; my $logger = get_logger(""); $logger->fatal(@_); exit 1; }; This will catch every "die()"-Exception of your application or the modules it uses. It will fetch a root logger and pass on the "die()"-Message to it. If you make sure you've configured with a root logger like this: Log::Log4perl->init(\q{ log4perl.category = FATAL, Logfile log4perl.appender.Logfile = Log::Dispatch::File log4perl.appender.Logfile.filename = fatal_errors.log log4perl.appender.Logfile.layout = \ Log::Log4perl::Layout::PatternLayout log4perl.appender.Logfile.layout.ConversionPattern = \ %F{1}-%L (%M)> %m%n }); then all "die()" messages will be routed to a file properly. The line $Log::Log4perl::caller_depth++; in the pseudo signal handler above merits a more detailed explanation. With the setup above, if a module calls "die()" in one of its functions, the fatal message will be logged in the signal handler and not in the original function -- which will cause the %F, %L and %M placeholders in the pattern layout to be replaced by the filename, the line number and the function/method name of the signal handler, not the error-throwing module. To adjust this, Log::Log4perl has the $caller_depth variable, which defaults to 0, but can be set to positive integer values to offset the caller level. Increasing it by one will cause it to log the calling function's parameters, not the ones of the signal handler. See "Using Log::Log4perl from wrapper classes" in the Log::Log4perl manpage for more details. Have fun! -- Mike ############################ # Mike Schilli # # log...@pe... # # http://perlmeister.com # # log4perl.sourceforge.net # ############################ |