File Coverage

blib/lib/Log/Report/Die.pm
Criterion Covered Total %
statement 55 68 80.8
branch 24 34 70.5
condition 9 23 39.1
subroutine 8 9 88.8
pod 2 2 100.0
total 98 136 72.0


line stmt bran cond sub pod time code
1             # Copyrights 2007-2017 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5 15     15   9113 use warnings;
  15         33  
  15         606  
6 15     15   81 use strict;
  15         30  
  15         457  
7              
8             package Log::Report::Die;
9 15     15   77 use vars '$VERSION';
  15         27  
  15         805  
10             $VERSION = '1.23';
11              
12 15     15   83 use base 'Exporter';
  15         30  
  15         1960  
13              
14             our @EXPORT = qw/die_decode exception_decode/;
15              
16 15     15   87 use POSIX qw/locale_h/;
  15         29  
  15         130  
17              
18              
19             sub die_decode($%)
20 18     18 1 6785 { my ($text, %args) = @_;
21              
22 18         60 my @text = split /\n/, $text;
23 18 50       42 @text or return ();
24 18         35 chomp $text[-1];
25              
26             # Try to catch the error directly, to remove it from the error text
27 18         86 my %opt = (errno => $! + 0);
28 18         52 my $err = "$!";
29              
30 18         27 my $dietxt = $text[0];
31 18 100 66     158 if($text[0] =~ s/ at (.+) line (\d+)\.?$// )
    100          
32 11         47 { $opt{location} = [undef, $1, $2, undef];
33             }
34             elsif(@text > 1 && $text[1] =~ m/^\s*at (.+) line (\d+)\.?$/ )
35             { # sometimes people carp/confess with \n, folding the line
36 4         17 $opt{location} = [undef, $1, $2, undef];
37 4         7 splice @text, 1, 1;
38             }
39              
40             $text[0] =~ s/\s*[.:;]?\s*$err\s*$// # the $err is translation sensitive
41 18 100       197 or delete $opt{errno};
42              
43 18         44 my @msg = shift @text;
44 18 50       36 length $msg[0] or $msg[0] = 'stopped';
45              
46 18         22 my @stack;
47 18         35 foreach (@text)
48 15 50       74 { if(m/^\s*(.*?)\s+called at (.*?) line (\d+)\s*$/)
49 15         51 { push @stack, [ $1, $2, $3 ] }
50 0         0 else { push @msg, $_ }
51             }
52 18         30 $opt{stack} = \@stack;
53 18 100       52 $opt{classes} = [ 'perl', (@stack ? 'confess' : 'die') ];
54              
55             my $reason
56             = $opt{errno} ? 'FAULT'
57             : @stack ? 'PANIC'
58 18 100 100     63 : $args{on_die} || 'ERROR';
    100          
59              
60 18         96 ($dietxt, \%opt, $reason, join("\n", @msg));
61             }
62              
63              
64             sub _exception_dbix($$)
65 5     5   11 { my ($exception, $args) = @_;
66 5         7 my $on_die = delete $args->{on_die};
67 5         11 my %opts = %$args;
68              
69 5         31 my @lines = split /\n/, "$exception"; # accessor missing to get msg
70 5         30 my $first = shift @lines;
71 5         61 my ($sub, $message, $fn, $linenr) = $first =~
72             m/^ (?: ([\w:]+?) \(\)\: [ ] | \{UNKNOWN\}\: [ ] )?
73             (.*?)
74             \s+ at [ ] (.+) [ ] line [ ] ([0-9]+)\.?
75             $/x;
76 5 100 66     31 my $pkg = defined $sub && $sub =~ s/^([\w:]+)\:\:// ? $1 : $0;
77              
78 5   50     29 $opts{location} ||= [ $pkg, $fn, $linenr, $sub ];
79              
80 5         7 my @stack;
81 5         10 foreach (@lines)
82 2 50       14 { my ($func, $fn, $linenr)
83             = /^\s+(.*?)\(\)\s+called at (.*?) line ([0-9]+)$/ or next;
84 2         7 push @stack, [ $func, $fn, $linenr ];
85             }
86 5 100 50     16 $opts{stack} ||= \@stack if @stack;
87              
88             my $reason
89 5 100 50     20 = $opts{errno} ? 'FAULT'
    50          
90             : @stack ? 'PANIC'
91             : $on_die || 'ERROR';
92              
93 5         55 ('caught '.ref $exception, \%opts, $reason, $message);
94             }
95              
96             my %_libxml_errno2reason = (1 => 'WARNING', 2 => 'MISTAKE', 3 => 'ERROR');
97              
98             sub _exception_libxml($$)
99 0     0   0 { my ($exc, $args) = @_;
100 0         0 my $on_die = delete $args->{on_die};
101 0         0 my %opts = %$args;
102              
103 0   0     0 $opts{errno} ||= $exc->code + 13000;
104 0   0     0 $opts{location} ||= [ 'libxml', $exc->file, $exc->line, $exc->domain ];
105              
106 0         0 my $msg = $exc->message . $exc->context . "\n"
107             . (' ' x $exc->column) . '^'
108             . ' (' . $exc->domain . ' error ' . $exc->code . ')';
109              
110 0   0     0 my $reason = $_libxml_errno2reason{$exc->level} || 'PANIC';
111 0         0 ('caught '.ref $exc, \%opts, $reason, $msg);
112             }
113              
114             sub exception_decode($%)
115 5     5 1 106 { my ($exception, %args) = @_;
116 5         22 my $errno = $! + 0;
117              
118 5 50       26 return _exception_dbix($exception, \%args)
119             if $exception->isa('DBIx::Class::Exception');
120              
121 0 0         return _exception_libxml($exception, \%args)
122             if $exception->isa('XML::LibXML::Error');
123              
124             # Unsupported exception system, sane guesses
125 0           my %opt =
126             ( classes => [ 'unknown exception', 'die', ref $exception ]
127             , errno => $errno
128             );
129              
130 0 0 0       my $reason = $errno ? 'FAULT' : $args{on_die} || 'ERROR';
131              
132             # hopefully stringification is overloaded
133 0           ( "caught ".ref $exception, \%opt, $reason, "$exception");
134             }
135              
136             "to die or not to die, that's the question";