stack trace with readable subroutine arguments
Is it possible to print 'fine' stacktrace with function params interpolated, such as Da开发者_Python百科ta::Dumper does? Instead of last line of this
  check_module_auth_cookie........... disabled, ok.
  check_module_auth_ntlm............. no NTLM, ok.
  check_module_auth_opensso.......... no OpenSSO, ok.
  check_module_auth_tinysso.......... no TinySSO, ok.
 checksums........................... SDBM, ok.
  checksum hashes...
   /etc/lighttpd/sites/holding2/docroot/dbm/db_model.sdbm... Couldn't tie SDBM file /etc/lighttpd/sites/holding2/docroot/dbm/db_model.sdbm: Отказано в доступе
 at /var/vh/eludia/Eludia/Content/Checksums/SDBM.pm line 52
        HOLDING::checksum_init('db_model') called at /var/vh/eludia/Eludia/Content/Checksums.pm line 195
        HOLDING::BEGIN() called at /var/vh/eludia/Eludia/Content/Checksums.pm line 206
        eval {...} called at /var/vh/eludia/Eludia/Content/Checksums.pm line 206
        require Eludia/Content/Checksums.pm called at /var/vh/eludia/Eludia.pm line 682
        HOLDING::check_module_checksums() called at /var/vh/eludia/Eludia.pm line 961
        HOLDING::BEGIN() called at /var/vh/eludia/Eludia/Content/Checksums.pm line 206
        eval {...} called at /var/vh/eludia/Eludia/Content/Checksums.pm line 206
        require Eludia.pm called at (eval 74) line 1
        eval 'package HOLDING; require Eludia;' called at /var/vh/eludia/Eludia/Loader.pm line 28
        Eludia::Loader::import('Eludia::Loader', 'ARRAY(0x41cf228)', 'HOLDING', 'HASH(0x41defc8)') called at (eval 72) line 7
I want to see
        Eludia::Loader::import('Eludia::Loader', 
                    [
                                '/var/projects/app', 
                                '/var/projects/submodule'
                    ],
                    'HOLDING',
                    {
                                mail_configuration => {etc..}
                    }
        ) called at (eval 72) line 7
In other words, substitute 'ARRAY(0x..)' and 'HASH(0x..)' in stacktrace
by their actual, useful values.
By setting your own signal handler you can customize the output without having to change how the errors are thrown. The Devel::StackTrace provides convenient access to stack trace data.
use Data::Dumper;
use Devel::StackTrace;
sub FatalErr {
    my ($message) = @_;
    my $trace = new Devel::StackTrace();
    $Data::Dumper::Terse = 1;
    print "$message";
    $trace->next_frame for 1..2;
    while (my $frame = $trace->next_frame) {
        my $arg_str = Dumper($frame->args);
        $arg_str =~ s/^/      /gm;
        $arg_str =~ s/^\s+//;
        printf '    during call to %1$s(%2$s) at %4$s:%5$s', $frame->subroutine, $arg_str, $frame->package, $frame->filename, $frame->line;
        print "\n";
    }
}
BEGIN{ $SIG{__DIE__} = \&FatalErr } # attaches the custom signal handler
this generates output like:
something bad happened at ./dietest.pl line 41.
    during call to stuff::foo() at dietest.pl:46
    during call to things::bar({
        'fruit' => [
                     'apple',
                     'orange',
                     'pear'
                   ],
        'veggies' => [
                       'peas',
                       'carrots'
                     ]
      }
      [
        0,
        1,
        2
      ]
) at dietest.pl:36
something bad happened at ./dietest.pl line 41.
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论