UPDATE: I have since wrapped all my logging gubbins in custom $SIG{__DIE__} and $SIG{__WARN__} handlers.

use Log::Log4perl qw/:easy :no_extra_logdie_message/; $SIG{__DIE__} = sub { return if $^S; # ignore die in an eval block # Get the actual caller for the "die" and not the wrapper local $Log::Log4perl::caller_depth; $Log::Log4perl::caller_depth++; LOGDIE($_[0]); };
This works as expected.




I am currently working on implementing Log::Log4perl in one of my scripts. I have never used this before, and I would like some advise/critiques please.

perl -v This is perl 5, version 16, subversion 3 (v5.16.3) built for MSWin32-x +86-multi-thread (with 1 registered patch, see perl -V for more detail) Copyright 1987-2012, Larry Wall Binary build 1603 [296746] provided by ActiveState http://www.ActiveSt +ate.com Built Mar 13 2013 11:29:21
Some background:
  1. I wrote a logging wrapper in $SIG{__DIE__} so I would not have to hunt down and replace all of my die(...) calls with $log->logdie(...)
    $SIG{__DIE__} = sub { my ($message) = @_; chomp $message; # Get the actual caller for the "die" and not the wrapper local $Log::Log4perl::caller_depth; $Log::Log4perl::caller_depth++; my $log = get_logger(''); $log->logdie($message); };
  2. This broke all my eval{...} error handling:
    # the new $SIG{__DIE__} causes everything to die here: eval{ do_something(\@args) or die "'do_something()' failed: $!"; }; # This never gets reached if ( $@ ) { warn "Could not do_something(): [$@]"; something_else(); }
  3. $SIG{__DIE__} also catches errors in other modules. I discovered this when I was working with YAML.pm:
    use YAML qw/LoadFile/; # dies with the following error: # Can't locate Mo/builder.pm in @INC (@INC contains: C:/Perl/site/lib +C:/Perl/lib .) at (eval 65) line 2, <$IN> line 1. my $yaml = LoadFile('./config.yml');
    (I fixed this particular issue by installing Mo via ppm, but it appears I have opened my self up to a veritable minefield...)

  4. I discovered the $^S variable on perlvar and how it can be used to selectively disable die() in an eval{...} block:
    $SIG{__DIE__} = sub { return if $^S; # ignore die in an eval block ... };
    This appears to work the way I expect, but the %SIG and $^S sections in perlvar and the die section in perldoc has some dire sounding warnings about this. (e.g. "Having to even think about the $^S variable in your exception handlers is simply wrong. $SIG{__DIE__} as currently implemented invites grievous and difficult to track down errors."). I am inexperienced enough to be worried about this.

With all that being said, is there a better way to write a Log4perl wrapper for my script's existing die() calls?

Thank you for your time

Full sample code:

#!/usr/bin/perl use Log::Log4perl qw/get_logger :no_extra_logdie_message/; use strict; use warnings; use YAML qw/LoadFile/; CHECK { LOG_INIT: { # Initialize logging local $/ = undef; Log::Log4perl::init(\<DATA>); } LOG_WRAPPERS: { # Wrapper for logging fatal errors $SIG{__DIE__} = sub { #return if $^S; # ignore die in an eval block my ($message) = @_; chomp $message; # Get the actual caller for the "die" and not the wrapper local $Log::Log4perl::caller_depth; $Log::Log4perl::caller_depth++; my $log = get_logger(''); $log->logdie($message); }; } } #################### ## MAIN { #Can't locate Mo/builder.pm in @INC (@INC contains: C:/Perl/site/l +ib C:/Perl/lib .) at (eval 65) line 2, <$IN> line 1. my $yaml = LoadFile('./path/to/yaml/file.yml') or die "Could not p +arse config file:\n$!\n$^E"; eval { die "a hot potato"; }; # dies here if ($@) { print "I caught something:\n[$@]"; exit; } # this is nev +er reached } __DATA__ layout_class = Log::Log4perl::Layout::PatternLayout # Layout for screen logging # [Priority] [File::Caller] [Line Number] > Message debug_layout_pattern = [%p] [%F{1}::%M] [%L] > %m %n ## ## LOGGERS ## log4perl.logger = TRACE, LogScreen # Logging to screen # (Includes TRACE and DEBUG priority level messages) log4perl.appender.LogScreen = Log::Log4perl::Appender::Screen log4perl.appender.LogScreen.utf8 = 1 log4perl.appender.LogScreen.layout = ${layout_class} log4perl.appender.LogScreen.layout.ConversionPattern = ${debug_layout_ +pattern}

In reply to [SOLVED] YAML, $SIG{__DIE__}, Log4perl, $^S, and eval{} by ateague

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.